dakies/OSS_Verilog huggingface dataset:
module test_fpga_core #
(
    parameter QUAD_CNT = 17,
    parameter CH_CNT = QUAD_CNT*4
)
(
    input wire clk,
    input wire rst
);

genvar n;

// XGMII 10G PHY
wire [CH_CNT-1:0]     eth_tx_clk;
wire [CH_CNT-1:0]     eth_tx_rst;
wire [CH_CNT*64-1:0]  eth_txd;
wire [CH_CNT*8-1:0]   eth_txc;
wire [CH_CNT-1:0]     eth_rx_clk;
wire [CH_CNT-1:0]     eth_rx_rst;
wire [CH_CNT*64-1:0]  eth_rxd;
wire [CH_CNT*8-1:0]   eth_rxc;

generate

for (n = 0; n < CH_CNT; n = n + 1) begin : ch

    wire         ch_tx_clk;
    wire         ch_tx_rst;
    wire [63:0]  ch_txd;
    wire [7:0]   ch_txc;
    wire         ch_rx_clk;
    wire         ch_rx_rst;
    wire [63:0]  ch_rxd;
    wire [7:0]   ch_rxc;

    assign eth_tx_clk[n +: 1] = ch_tx_clk;
    assign eth_tx_rst[n +: 1] = ch_tx_rst;
    assign ch_txd = eth_txd[n*64 +: 64];
    assign ch_txc = eth_txc[n*8 +: 8];
    assign eth_rx_clk[n +: 1] = ch_rx_clk;
    assign eth_rx_rst[n +: 1] = ch_rx_rst;
    assign eth_rxd[n*64 +: 64] = ch_rxd;
    assign eth_rxc[n*8 +: 8] = ch_rxc;

end

endgenerate

fpga_core #(
    .CH_CNT(CH_CNT)
)
core_inst (
    /*
     * Clock: 156.25 MHz
     * Synchronous reset
     */
    .clk(clk),
    .rst(rst),

    /*
     * Ethernet: QSFP28
     */
    .eth_tx_clk(eth_tx_clk),
    .eth_tx_rst(eth_tx_rst),
    .eth_txd(eth_txd),
    .eth_txc(eth_txc),
    .eth_rx_clk(eth_rx_clk),
    .eth_rx_rst(eth_rx_rst),
    .eth_rxd(eth_rxd),
    .eth_rxc(eth_rxc)
);

endmodule
module waves();
    initial begin
        if ($test$plusargs ("WAVES_ON")) begin
            $dumpfile(`WAVES_OUT);
            $dumpvars();
        end
    end
endmodule
module simplespi(
	input clk,
	input clk_spi_en,
	input reset,

	output req_next,

	input start,
	input finish,

	input CPOL,
	input CPHA,

	input[7:0] data_write,
	output[7:0] data_read,

    output sclk,
	output mosi,
	input  miso,
    output cs
);

	localparam STATE_IDLE = 0;
	localparam STATE_START = 1;
	localparam STATE_DATA_SETUP = 2;
	localparam STATE_DATA_SAMPLE = 3;

	reg latch_finish;

	reg [7:0] data_read;
	wire req_next;
    reg sclk_o, cs, mosi;

	assign sclk = (CPOL == 1'b 1) ? sclk_o : ~sclk_o;

	assign req_next = (bit_count == 8'd0) && ~start_sync;

	reg start_sync;
	reg [4:0] fsm_state;
	reg [7:0] bit_count;

	always @(posedge clk) begin
		if (reset == 1'b1) begin
			fsm_state <= STATE_IDLE;
			sclk_o <= 1'b 1;
			start_sync <= 1'b0;
		end	else begin
			if (start == 1'b1) begin
				start_sync <= 1'b1;
			end
			if (clk_spi_en == 1'b1) begin
				case(fsm_state)
					STATE_IDLE: begin
						cs <= 1'b 1;
                        sclk_o <= 1'b 1;
						if (start_sync == 1'b1) begin
							start_sync <= 1'b0;
							fsm_state <= STATE_START;
						end
					end

					STATE_START: begin
						latch_finish <= finish;
						bit_count <= 8'd 7;
						fsm_state <= STATE_DATA_SETUP;
						if (CPHA == 1'b1) begin
							cs <= 1'b 0;
						end
					end

					STATE_DATA_SETUP: begin
						sclk_o <= (CPHA == 1'b0) ? 1'b1 : 1'b0;
						cs <= 1'b 0;
						mosi <= data_write[bit_count];
						fsm_state <= STATE_DATA_SAMPLE;
					end

					STATE_DATA_SAMPLE: begin
						sclk_o <= (CPHA == 1'b0) ? 1'b0 : 1'b1;
						data_read[bit_count] <= miso;
						if (bit_count == 8'd0) begin
							if (start_sync == 1'b1) begin
								start_sync <= 1'b0;
								fsm_state <= STATE_START;
							end
							if (latch_finish == 1'b 1) begin
								fsm_state <= STATE_IDLE;
							end
						end else begin
							fsm_state <= STATE_DATA_SETUP;
							bit_count <= bit_count - 1;
						end
					end

				endcase
			end
		end
	end
endmodule
module memspram #(
    parameter ADDR_WIDTH = 14
) (
    input clk,
    input reset_n,
    output[7:0] data_out,
    input[7:0] data_in,
    input cs_n,
    input rd_n,
    input wr_n,
    input[ADDR_WIDTH-1:0] addr
);

    wire read_sel = !cs_n & !rd_n & wr_n;
    wire write_sel = !cs_n & rd_n & !wr_n;

	wire [15:0] spram_q;
	assign data_out = (read_sel) ? spram_q[7:0] : 8'b0;

	//SB_SPRAM256KA.ADDRESS is 14bit:
	wire [13:0] addr_sp;
	assign addr_sp = addr;

	SB_SPRAM256KA ram0
	(
		.ADDRESS(addr_sp),
		.DATAIN({8'b0, data_in}),
		.MASKWREN(4'b0011),
		.WREN(write_sel),
		.CHIPSELECT(1'b1),
		.CLOCK(clk),
		.STANDBY(1'b0),
		.SLEEP(1'b0),
		.POWEROFF(1'b1),
		.DATAOUT(spram_q)
	);

endmodule
module simplespi_wrapper (
    input clk,
    input reset_n,
    output[7:0] data_out,
    input[7:0] data_in,
    input cs_n,
    input rd_n,
    input wr_n,
    input[2:0] addr,
    output sclk,
	output mosi,
	input  miso,
    output cs
);

    wire read_sel = !cs_n & !rd_n & wr_n;
    wire write_sel = !cs_n & rd_n & !wr_n;

	wire[7:0] reg_status;
	reg[7:0] reg_config = 8'h0;
	reg[7:0] reg_command = 8'h0;
	reg[7:0] reg_data_wr = 8'h0;
	reg[7:0] reg_clockdiv = 8'h0;
	wire[7:0] reg_data_rd;
	wire req_next;

    reg[7:0] read_data;
    reg      err;
    
	assign data_out = (read_sel) ? read_data : 8'b0;
	assign reg_status = {6'b0, err, req_next};

    always @(*)
	begin
		case(addr)
			3'h0 : read_data = reg_status;
			3'h1 : read_data = reg_config;
			3'h2 : read_data = reg_clockdiv;
			3'h3 : read_data = reg_command;
			3'h4 : read_data = reg_data_rd;
			3'h5 : read_data = reg_data_wr;
			default : read_data = 8'h00;
		endcase
	end

    always @(posedge clk)
    begin
        if (write_sel) begin
            err <= ~reg_status[0];
        end
    end
    
    
    always @(posedge clk)
    begin
        if ( write_sel ) begin
            case(addr)
				3'h1 : reg_config <= data_in;
				3'h2 : reg_clockdiv <= data_in;
				3'h3 : reg_command <= data_in;
				3'h5 : reg_data_wr <= data_in;
            endcase
        end

		if( reg_command[0] == 1'b1 ) begin
			reg_command[0] <= 1'b0;
		end
    end

	wire spi_clk_en;

	clk_enable spi_clk_divider (
		.reset(!reset_n),
		.divider({ 8'h 00, reg_clockdiv}), //f=12E6/12=1MHz => div=12/2
		.clk_in(clk),
		.clk_en(spi_clk_en)
	);

	simplespi master (
		.clk			(clk),
		.clk_spi_en		(spi_clk_en),
		.reset			(!reset_n),

		.req_next		(req_next),

		.start			(reg_command[0]),
		.finish			(reg_command[1]),

		.CPOL			(reg_config[1]),
		.CPHA			(reg_config[0]),

		.data_write		(reg_data_wr),
		.data_read		(reg_data_rd),

		.sclk			(sclk),
		.mosi			(mosi),
		.miso			(miso),
		.cs				(cs)
	);

endmodule
module clk_enable(
    input wire clk_in,
    input wire reset,
	input wire[15:0] divider,
    output reg clk_en
);

	reg [15:0] count = 0;

	always @(posedge clk_in) begin
		if (reset == 1) begin
			clk_en <= 0;
			count <= 0;
		end	else begin
			if (count >= divider) begin
				clk_en <= 1'b1;
				count <= 0;
			end else begin
				clk_en <= 1'b0;
				count <= count + 1'b1;
			end
		end
	end

endmodule
module simpleuart_wrapper (
    input clk,
    input reset_n,
    output[7:0] data_out,
    input[7:0] data_in,
    input cs_n,
    input rd_n,
    input wr_n,
    input[2:0] addr,
    output tx,
    input rx
);

    wire read_sel = !cs_n & !rd_n & wr_n;
    wire write_sel = !cs_n & rd_n & !wr_n;

	reg[7:0] reg_status = 8'h0;
	reg[7:0] reg_command = 8'h0;
	reg[7:0] reg_data_wr = 8'h0;
	reg[7:0] reg_baudlow = 8'h0;
	reg[7:0] reg_baudhigh = 8'h0;
	wire[7:0] reg_data_rd;
	wire received;
	wire ready;

    reg[7:0] read_data;
    
	assign data_out = (read_sel) ? read_data : 8'b0;

    always @(*)
	begin
		case(addr)
			3'h0 : read_data = reg_status;
			3'h1 : read_data = reg_baudlow;
			3'h2 : read_data = reg_baudhigh;
			3'h3 : read_data = reg_command;
			3'h4 : read_data = reg_data_rd;
			3'h5 : read_data = reg_data_wr;
			default : read_data = 8'h00;
		endcase
	end
    
    always @(posedge clk)
    begin
        if ( write_sel ) begin
            case(addr)
				3'h1 : reg_baudlow <= data_in;
				3'h2 : reg_baudhigh <= data_in;
				3'h3 : reg_command <= data_in;
				3'h5 : reg_data_wr <= data_in;
            endcase
        end

        if ( read_sel ) begin
            if( addr == 3'h4 )begin
                reg_status[0] <= 1'b 0; // clear after read data
            end
        end
        if( received ) begin // is one clk active
            reg_status[0] <= 1'b 1;
        end

        reg_status[1] <= ready;
    end

    simpleuart uart (
        .clk        (clk),
	    .reset      (!reset_n),

        .baud_divider   ( {reg_baudhigh, reg_baudlow} ),

        .data_write (reg_data_wr),
        .transmit   (reg_command[0]),

        .data_read  (reg_data_rd),
        .received   (received),
        .ready      (ready),

        .tx         (tx),
        .rx         (rx)
    );

endmodule
module simplei2c_wrapper (
    input clk,
    input reset_n,
    output[7:0] data_out,
    input[7:0] data_in,
    input cs_n,
    input rd_n,
    input wr_n,
    input[2:0] addr,
	input i2c_sda_in,
	output i2c_sda_out,
	output i2c_sda_oen,
	output i2c_scl_out
);

    wire read_sel = !cs_n & !rd_n & wr_n;
    wire write_sel = !cs_n & rd_n & !wr_n;

	wire i2c_clk_en;

	wire[7:0] reg_status;
	reg[7:0] reg_command = 8'h0;
	reg[7:0] reg_data_wr = 8'h0;
	reg[7:0] reg_clockdiv = 8'h0;
	wire[7:0] reg_data_rd;

    reg[7:0] read_data;

	assign data_out = (read_sel) ? read_data : 8'b0;

    always @(*)
	begin
		case(addr)
			3'h0 : read_data = reg_status;
			3'h2 : read_data = reg_clockdiv;
			3'h3 : read_data = reg_command;
			3'h4 : read_data = reg_data_rd;
			3'h5 : read_data = reg_data_wr;
			default : read_data = 8'h00;
		endcase
	end

    always @(posedge clk)
    begin
        if ( write_sel ) begin
            case(addr)
				3'h2 : reg_clockdiv <= data_in;
				3'h3 : reg_command <= data_in;
				3'h5 : reg_data_wr <= data_in;
            endcase
        end

		if( reg_command[0] == 1'b1) begin
			reg_command[0] <= 1'b0;
		end
    end

	clk_enable i2c_clk_divider (
		.reset(!reset_n),
		.divider( { 8'h 00, reg_clockdiv } ), //f=12E6/120=100kHz => div=120/2
		.clk_in(clk),
		.clk_en(i2c_clk_en)
	);

	simplei2c master (
		.clk			(clk),
		.clk_i2c_en		(i2c_clk_en),
		.reset			(!reset_n),

		.req_next		(reg_status[0]),

		.start			(reg_command[0]),
		.restart		(reg_command[1]),
		.stop			(reg_command[2]),
		.mode_rw		(reg_command[3]), //write = 0, read = 1
		.ack_sda		(reg_command[4]), //sda = 1 or sda = 0 when ACK/NAK

		.data_write		(reg_data_wr),
		.data_read		(reg_data_rd),

		.i2c_sda_in		(i2c_sda_in),
		.i2c_sda_out	(i2c_sda_out),
		.i2c_sda_oen	(i2c_sda_oen),
		.i2c_scl_out	(i2c_scl_out)
	);

endmodule
module simpleio (
    input clk,
    input reset_n,
    output[7:0] data_out,
    input[7:0] data_in,
    input cs_n,
    input rd_n,
    input wr_n,
    input[1:0] addr,
    output[7:0] P1_out,
    input[7:0] P1_in,
    output P1_oen,
    output[7:0] P2_out,
    input[7:0] P2_in,
    output P2_oen
);
    `define MODE_WR 1'b0
    `define MODE_RD 1'b1
    reg[7:0] cfgreg;

    wire read_sel = !cs_n & !rd_n & wr_n;
    wire write_sel = !cs_n & rd_n & !wr_n;

    reg[7:0] out_1, out_2;
    reg[7:0] in_1, in_2;

    reg[7:0] read_data;

    assign P1_oen = (cfgreg[0] == `MODE_WR) ? 1'b1 : 1'b0;
    assign P2_oen = (cfgreg[1] == `MODE_WR) ? 1'b1 : 1'b0;
    assign P1_out = out_1;
    assign P2_out = out_2;

	assign data_out = (read_sel) ? read_data : 8'b0;

    always @(*)
	begin
		case(addr)
			2'h0 : read_data = ((cfgreg[0] == `MODE_RD) ? in_1 : out_1);
			3'h1 : read_data = ((cfgreg[1] == `MODE_RD) ? in_2 : out_2);
			default : read_data = 8'h00;
		endcase
	end

    always @(posedge clk)
    begin
        if ( write_sel ) begin
            case(addr)
                2'b00 : out_1 <= data_in;
                2'b01 : out_2 <= data_in;
                2'b10 : cfgreg <= data_in;
            endcase
        end
        in_1 <= P1_in;
        in_2 <= P2_in;
    end

endmodule
module membram #(
    parameter ADDR_WIDTH = 14,
	parameter MEM_HEX = "",
	parameter MEM_INIT = 0
) (
    input clk,
    input reset_n,
    output[7:0] data_out,
    input[7:0] data_in,
    input cs_n,
    input rd_n,
    input wr_n,
    input[ADDR_WIDTH-1:0] addr
);

    wire read_sel = !cs_n & !rd_n & wr_n;
    wire write_sel = !cs_n & rd_n & !wr_n;

    assign data_out = (read_sel) ? mem_8[addr] : 8'b0;

    reg [7:0] mem_8 [0:(1 << ADDR_WIDTH)-1];
    integer j;
    initial begin
        if( MEM_INIT > 0 ) begin
            $readmemh(MEM_HEX, mem_8, 0, (1 << ADDR_WIDTH)-1);
        end
    end

    always @(posedge clk)
    begin
        if (write_sel) begin
            mem_8[addr] <= data_in;
        end
    end

endmodule
module top(
	input clk,
	output D1,
	output D2,
	output D3,
	output D4,
	output D5,
	output D6,
	output D7,
	output D8,
	output uart_txd,
	input uart_rxd,
	output i2c_scl,
	inout i2c_sda,
    output spi_sclk,
	output spi_mosi,
	input  spi_miso,
    output spi_cs
);

	wire[7:0] P1_out;
	wire[7:0] P2_out;

	wire i2c_scl;
	wire i2c_sda_out;
	wire i2c_sda_in;
	wire i2c_sda_oen;

	assign D1 = P1_out[0];
	assign D2 = P1_out[1];
	assign D3 = P1_out[2];
	assign D4 = P1_out[3];
	assign D5 = P1_out[4];
	assign D6 = P1_out[5];
	assign D7 = P1_out[6];
	assign D8 = P1_out[7];

	SB_IO #(
		.PIN_TYPE(6'b 1010_01),
		.PULLUP(1'b 0)
	) i2c_sda_pin (
		.PACKAGE_PIN(i2c_sda),
		.OUTPUT_ENABLE(i2c_sda_oen),
		.D_OUT_0(i2c_sda_out),
		.D_IN_0(i2c_sda_in)
	);

	iceZ0mb1e core (
		.clk		(clk),
		.uart_txd	(uart_txd),
		.uart_rxd	(uart_rxd),
		.i2c_scl	(i2c_scl),
		.i2c_sda_in	(i2c_sda_in),
		.i2c_sda_out	(i2c_sda_out),
		.i2c_sda_oen	(i2c_sda_oen),
    	.spi_sclk	(spi_sclk),
		.spi_mosi	(spi_mosi),
		.spi_miso	(spi_miso),
    	.spi_cs		(spi_cs),
		.P1_out		(P1_out),
		.P1_in		(8'h55),
		.P1_oen		(),
		.P2_out		(P2_out),
		.P2_in		(8'hAA),
		.P2_oen		(),
		.debug		()
	);

endmodule
module top(
	output uart_txd,
	input uart_rxd,
	output LED_R,
	output LED_G,
	output LED_B,
	output oled_rst,
	output i2c_scl,
	inout i2c_sda,
    output spi_sclk,
	output spi_mosi,
	input  spi_miso,
    output spi_cs
);

	wire clk;

	wire[7:0] P1_out;
	wire[7:0] P2_out;

	wire i2c_scl;
	wire i2c_sda_out;
	wire i2c_sda_in;
	wire i2c_sda_oen;

	reg LED_R, LED_G, LED_B;
	reg oled_rst;

    always @(posedge clk)
    begin
		LED_R <= !P1_out[0];
		LED_G <= !P1_out[1];
		LED_B <= !P1_out[2];
		oled_rst <= P2_out[0];
	end

	//Source = 48MHz, CLKHF_DIV = 2’b00 : 00 = div1, 01 = div2, 10 = div4, 11 = div8 ; Default = “00”
	SB_HFOSC #(.CLKHF_DIV("0b10")) osc (
		.CLKHFPU(1'b1),
		.CLKHFEN(1'b1),
		.CLKHF(clk)
	);

	SB_IO #(
		.PIN_TYPE(6'b 1010_01),
		.PULLUP(1'b 0)
	) i2c_sda_pin (
		.PACKAGE_PIN(i2c_sda),
		.OUTPUT_ENABLE(i2c_sda_oen),
		.D_OUT_0(i2c_sda_out),
		.D_IN_0(i2c_sda_in)
	);

	iceZ0mb1e core (
		.clk		(clk),
		.uart_txd	(uart_txd),
		.uart_rxd	(uart_rxd),
		.i2c_scl	(i2c_scl),
		.i2c_sda_in	(i2c_sda_in),
		.i2c_sda_out	(i2c_sda_out),
		.i2c_sda_oen	(i2c_sda_oen),
    	.spi_sclk	(spi_sclk),
		.spi_mosi	(spi_mosi),
		.spi_miso	(spi_miso),
    	.spi_cs		(spi_cs),
		.P1_out		(P1_out),
		.P1_in		(8'h55),
		.P1_oen		(),
		.P2_out		(P2_out),
		.P2_in		(8'hAA),
		.P2_oen		(),
		.debug		()
	);
	defparam core.RAM_TYPE = 1; // 0 => BRAM, 1 => SPRAM (UltraPlus)

endmodule
module top(
	input clk,
   output D1,
   output D2,
   output D3,
   output D4,
   output D5,
   output D6,
   output D7,
   output D8,
	output uart_txd,
	input uart_rxd,
	output i2c_scl,
	inout i2c_sda,
    output spi_sclk,
	output spi_mosi,
	input  spi_miso,
    output spi_cs
);

	wire[7:0] P1_out;
	wire[7:0] P2_out;

	wire i2c_scl;
	wire i2c_sda_out;
	wire i2c_sda_in;
	wire i2c_sda_oen;

   assign D1 = P1_out[0];
   assign D2 = P1_out[1];
   assign D3 = P1_out[2];
   assign D4 = P1_out[3];
   assign D5 = P1_out[4];
   assign D6 = P1_out[5];
   assign D7 = P1_out[6];
   assign D8 = P1_out[7];

	SB_IO #(
		.PIN_TYPE(6'b 1010_01),
		.PULLUP(1'b 0)
	) i2c_sda_pin (
		.PACKAGE_PIN(i2c_sda),
		.OUTPUT_ENABLE(i2c_sda_oen),
		.D_OUT_0(i2c_sda_out),
		.D_IN_0(i2c_sda_in)
	);

	reg [1:0] clkdiv;

	always @(posedge clk) begin
		clkdiv <= clkdiv + 1;
	end

	wire clk12 = clkdiv[1];

	iceZ0mb1e core (
		.clk		(clk12),
		.uart_txd	(uart_txd),
		.uart_rxd	(uart_rxd),
		.i2c_scl	(i2c_scl),
		.i2c_sda_in	(i2c_sda_in),
		.i2c_sda_out	(i2c_sda_out),
		.i2c_sda_oen	(i2c_sda_oen),
    	.spi_sclk	(spi_sclk),
		.spi_mosi	(spi_mosi),
		.spi_miso	(spi_miso),
    	.spi_cs		(spi_cs),
		.P1_out		(P1_out),
		.P1_in		(8'h55),
		.P1_oen		(),
		.P2_out		(P2_out),
		.P2_in		(8'hAA),
		.P2_oen		(),
		.debug		()
	);

endmodule
module top(
	input clk,
	output D1,
	output D2,
	output D3,
	output D4,
	output D5,
	output D6,
	output D7,
	output D8,
	output uart_txd,
	input uart_rxd,
	output i2c_scl,
	inout  i2c_sda,
    output spi_sclk,
	output spi_mosi,
	output spi_miso,
    output spi_cs
);

	wire[7:0] port_a;
	wire[7:0] port_b;

	assign D1 = port_a[0];
	assign D2 = port_a[1];
	assign D3 = port_a[2];
	assign D4 = port_a[3];
	assign D5 = port_a[4];
	assign D6 = port_a[5];
	assign D7 = port_a[6];
	assign D8 = port_a[7];

	iceZ0mb1e core (
		.clk		(clk),
		.uart_txd	(uart_txd),
		.uart_rxd	(uart_rxd),
		.i2c_scl	(i2c_scl),
		.i2c_sda	(i2c_sda),
    	.spi_sclk	(spi_sclk),
		.spi_mosi	(spi_mosi),
		.spi_miso	(spi_miso),
    	.spi_cs		(spi_cs),
		.port_a		(port_a),
		.port_b		(port_b),
		.debug		()
	);

endmodule
module top(
	input clk,
	output D1,
	output D2,
	output D3,
	output D4,
	output D5,
	output D6,
	output D7,
	output D8,
	output uart_txd,
	input uart_rxd,
	output i2c_scl,
	inout i2c_sda,
    output spi_sclk,
	output spi_mosi,
	input  spi_miso,
    output spi_cs,
    output LED,   // User/boot LED next to power LED
    output USBPU  // USB pull-up resistor
);

	wire[7:0] P1_out;
	wire[7:0] P2_out;

	wire i2c_scl;
	wire i2c_sda_out;
	wire i2c_sda_in;
	wire i2c_sda_oen;

	assign D1 = P1_out[0];
	assign D2 = P1_out[1];
	assign D3 = P1_out[2];
	assign D4 = P1_out[3];
	assign D5 = P1_out[4];
	assign D6 = P1_out[5];
	assign D7 = P1_out[6];
	assign D8 = P1_out[7];

	SB_IO #(
		.PIN_TYPE(6'b 1010_01),
		.PULLUP(1'b 0)
	) i2c_sda_pin (
		.PACKAGE_PIN(i2c_sda),
		.OUTPUT_ENABLE(i2c_sda_oen),
		.D_OUT_0(i2c_sda_out),
		.D_IN_0(i2c_sda_in)
	);

	iceZ0mb1e core (
		.clk		(clk),
		.uart_txd	(uart_txd),
		.uart_rxd	(uart_rxd),
		.i2c_scl	(i2c_scl),
		.i2c_sda_in	(i2c_sda_in),
		.i2c_sda_out	(i2c_sda_out),
		.i2c_sda_oen	(i2c_sda_oen),
    	.spi_sclk	(spi_sclk),
		.spi_mosi	(spi_mosi),
		.spi_miso	(spi_miso),
    	.spi_cs		(spi_cs),
		.P1_out		(P1_out),
		.P1_in		(8'h55),
		.P1_oen		(),
		.P2_out		(P2_out),
		.P2_in		(8'hAA),
		.P2_oen		(),
		.debug		()
	);
	


	
    // ================================================================
    // ================================================================
    // ================================================================

    wire CLK = clk;
    // drive USB pull-up resistor to '0' to disable USB
    assign USBPU = 0;

    // look in pins.pcf for all the pin names on the TinyFPGA BX board
    ////////
    // make a simple blink circuit
    ////////

    // keep track of time and location in blink_pattern
    reg [25:0] blink_counter;

    // pattern that will be flashed over the LED over time
    wire [31:0] blink_pattern = 32'b101010001110111011100010101;

    // increment the blink_counter every clock
    always @(posedge CLK) begin
        blink_counter <= blink_counter + 1;
    end
    
    // light up the LED according to the pattern
//    assign LED = blink_pattern[blink_counter[25:21]];
    assign LED = P1_out[0]; // blink_pattern[blink_counter[25:21]];
endmodule
module top(
	input clk,
	output D1,
	output D2,
	output D3,
	output D4,
	output D5,
	output D6,
	output D7,
	output D8,
	output uart_txd,
	input uart_rxd,
	output i2c_scl,
	inout  i2c_sda,
    output spi_sclk,
	output spi_mosi,
	output  spi_miso,
    output spi_cs
);

	wire[7:0] port_a;
	wire[7:0] port_b;

	assign D1 = port_a[0];
	assign D2 = port_a[1];
	assign D3 = port_a[2];
	assign D4 = port_a[3];
	assign D5 = port_a[4];
	assign D6 = port_a[5];
	assign D7 = port_a[6];
	assign D8 = port_a[7];

	iceZ0mb1e core (
		.clk		(clk),
		.uart_txd	(uart_txd),
		.uart_rxd	(uart_rxd),
		.i2c_scl	(i2c_scl),
		.i2c_sda	(i2c_sda),
    	.spi_sclk	(spi_sclk),
		.spi_mosi	(spi_mosi),
		.spi_miso	(spi_miso),
    	.spi_cs		(spi_cs),
		.port_a		(port_a),
		.port_b		(port_b),
		.debug		()
	);

endmodule
module top(
	input clk,
	output uart_txd,
	input uart_rxd,
	output i2c_scl,
	inout i2c_sda,
    output spi_sclk,
	output spi_mosi,
	input  spi_miso,
    output spi_cs
);

	wire[7:0] P1_out;
	wire[7:0] P2_out;

	wire i2c_scl;
	wire i2c_sda_out;
	wire i2c_sda_in;
	wire i2c_sda_oen;

	SB_IO #(
		.PIN_TYPE(6'b 1010_01),
		.PULLUP(1'b 0)
	) i2c_sda_pin (
		.PACKAGE_PIN(i2c_sda),
		.OUTPUT_ENABLE(i2c_sda_oen),
		.D_OUT_0(i2c_sda_out),
		.D_IN_0(i2c_sda_in)
	);

	reg [1:0] clkdiv;

	always @(posedge clk) begin
		clkdiv <= clkdiv + 1;
	end

	wire clk12 = clkdiv[1];

	iceZ0mb1e core (
		.clk		(clk12),
		.uart_txd	(uart_txd),
		.uart_rxd	(uart_rxd),
		.i2c_scl	(i2c_scl),
		.i2c_sda_in	(i2c_sda_in),
		.i2c_sda_out	(i2c_sda_out),
		.i2c_sda_oen	(i2c_sda_oen),
    	.spi_sclk	(spi_sclk),
		.spi_mosi	(spi_mosi),
		.spi_miso	(spi_miso),
    	.spi_cs		(spi_cs),
		.P1_out		(P1_out),
		.P1_in		(8'h55),
		.P1_oen		(),
		.P2_out		(P2_out),
		.P2_in		(8'hAA),
		.P2_oen		(),
		.debug		()
	);

endmodule
module tb_iceZ0mb1e;

    initial begin
        $dumpfile(`__def_vcd_file);
        $dumpvars(0, tb_iceZ0mb1e);

        //# 15E3 $finish;
        # 250E3 $finish;
        //# 1E6 $finish;
    end

    reg clk = 0;
    always #1 clk = !clk;

    inout [7:0] P1_out;
    inout [7:0] P2_out;
	wire i2c_scl;
	wire i2c_sda_out;
	wire i2c_sda_in;
	wire i2c_sda_oen;
    output sclk, cs, mosi;
    input miso;
    wire rx = 0;
    wire tx;

    iceZ0mb1e t1 (
        .clk        (clk),
        .uart_txd   (tx),
        .uart_rxd   (rx),
		.i2c_scl	(i2c_scl),
		.i2c_sda_in	(i2c_sda_in),
		.i2c_sda_out	(i2c_sda_out),
		.i2c_sda_oen	(i2c_sda_oen),
    	.spi_sclk	(spi_sclk),
		.spi_mosi	(spi_mosi),
		.spi_miso	(spi_miso),
    	.spi_cs		(spi_cs),
		.P1_out		(P1_out),
		.P1_in		(8'h55),
		.P1_oen		(),
		.P2_out		(P2_out),
		.P2_in		(8'hAA),
		.P2_oen		(),
		.debug		()
    );

endmodule
module tb_uart;

    reg clk = 0;
    reg reset = 0;

    wire rx = 0;
    wire tx;

    reg[7:0] wrdata;
    reg transmit;

    wire[7:0] rddata;
    wire received;

    simpleuart uart1 (
        .clk        (clk),
	    .reset      (reset),

        .baud_divider   (16'd 1250),

        .data_write (wrdata),
        .transmit   (transmit),
        .ready (),

        .data_read  (),
        .received   (),

        .tx         (tx),
        .rx         (rx)
    );

    simpleuart uart2 (
        .clk        (clk),
	    .reset      (reset),

        .baud_divider   (16'd 1250),

        .data_write (8'h 00),
        .transmit   (1'b 0),
        .ready (),

        .data_read  (rddata),
        .received   (received),

        .tx         (rx),
        .rx         (tx)
    );

    always #1 clk = !clk;

    initial begin
        $dumpfile(`__def_vcd_file);
        $dumpvars(0, tb_uart);

        # 1 transmit = 0;

        # 5 reset = 0;
        # 5 reset = 1;
        # 5 reset = 0;

        # 20 wrdata = 8'h 81;
        # 5 transmit = 1;
        # 5 transmit = 0;

        // # 400 wrdata = 8'h FF;
        // # 1 transmit = 1;
        // # 1 transmit = 0;

        // # 800 wrdata = 8'h 01;
        // # 1 transmit = 1;
        // # 1 transmit = 0;

        //# 15E3 $finish;
        # 250E3 $finish;
        //# 1E6 $finish;
    end

endmodule
module usb3_descrip_rom(
	input clk,
	input [6:0] adr,
	output reg [31:0] dat_r
);

reg [31:0] mem[0:127];
reg [6:0] memadr;
always @(posedge clk) begin
	memadr <= adr;
	dat_r = mem[memadr];
end

initial begin
	$readmemh("usb3_descrip_rom.init", mem);
end

endmodule
module usb3_crc_cw(

input 	wire	[10:0] 	di,
output 	wire	[4:0] 	crc_out

);

// reverse input
wire	[10:0]	d = { 	di[0], di[1], di[2], di[3], di[4], 
						di[5], di[6], di[7], di[8], di[9], 
						di[10] };
wire	[4:0]	c = 5'h1F;						
wire	[4:0]	q = {	^d[10:9] ^ ^d[6:5] ^ d[3] ^ d[0] ^ c[0] ^ ^c[4:3],
						d[10] ^ ^d[7:6] ^ d[4] ^ d[1] ^ ^c[1:0] ^ c[4],
						^d[10:7] ^ d[6] ^ ^d[3:2] ^ d[0] ^ ^c[4:0],
						^d[10:7] ^^ d[4:3] ^ d[1] ^ ^c[4:1],
						^d[10:8] ^ ^d[5:4] ^ d[2] ^ ^c[4:2]	};
assign	crc_out = ~q;
	
endmodule
module usb3_crc_dpp8 (

input 	wire	[7:0]	di,
input	wire	[31:0]	q,
output	wire	[31:0]	crc_out,
input	wire			rst,
input	wire			clk

);

wire [31:0]	c;
wire [7:0] d = {	di[0 ],di[1 ],di[2 ],di[3 ],di[4 ],di[5 ],di[6 ],di[7]};
						
assign crc_out = ~{	c[0],  c[1],  c[2],  c[3],  c[4],  c[5],  c[6],  c[7], 
					c[8],  c[9],  c[10], c[11], c[12], c[13], c[14], c[15],
					c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23], 
					c[24], c[25], c[26], c[27], c[28], c[29], c[30], c[31]};

assign	c[0] = q[24] ^ q[30] ^ d[0] ^ d[6];
assign	c[1] = q[24] ^ q[25] ^ q[30] ^ q[31] ^ d[0] ^ d[1] ^ d[6] ^ d[7];
assign	c[2] = q[24] ^ q[25] ^ q[26] ^ q[30] ^ q[31] ^ d[0] ^ d[1] ^ d[2] ^ d[6] ^ d[7];
assign	c[3] = q[25] ^ q[26] ^ q[27] ^ q[31] ^ d[1] ^ d[2] ^ d[3] ^ d[7];
assign	c[4] = q[24] ^ q[26] ^ q[27] ^ q[28] ^ q[30] ^ d[0] ^ d[2] ^ d[3] ^ d[4] ^ d[6];
assign	c[5] = q[24] ^ q[25] ^ q[27] ^ q[28] ^ q[29] ^ q[30] ^ q[31] ^ d[0] ^ d[1] ^ d[3] ^ d[4] ^ d[5] ^ d[6] ^ d[7];
assign	c[6] = q[25] ^ q[26] ^ q[28] ^ q[29] ^ q[30] ^ q[31] ^ d[1] ^ d[2] ^ d[4] ^ d[5] ^ d[6] ^ d[7];
assign	c[7] = q[24] ^ q[26] ^ q[27] ^ q[29] ^ q[31] ^ d[0] ^ d[2] ^ d[3] ^ d[5] ^ d[7];
assign	c[8] = q[0] ^ q[24] ^ q[25] ^ q[27] ^ q[28] ^ d[0] ^ d[1] ^ d[3] ^ d[4];
assign	c[9] = q[1] ^ q[25] ^ q[26] ^ q[28] ^ q[29] ^ d[1] ^ d[2] ^ d[4] ^ d[5];
assign	c[10] = q[2] ^ q[24] ^ q[26] ^ q[27] ^ q[29] ^ d[0] ^ d[2] ^ d[3] ^ d[5];
assign	c[11] = q[3] ^ q[24] ^ q[25] ^ q[27] ^ q[28] ^ d[0] ^ d[1] ^ d[3] ^ d[4];
assign	c[12] = q[4] ^ q[24] ^ q[25] ^ q[26] ^ q[28] ^ q[29] ^ q[30] ^ d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[5] ^ d[6];
assign	c[13] = q[5] ^ q[25] ^ q[26] ^ q[27] ^ q[29] ^ q[30] ^ q[31] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[6] ^ d[7];
assign	c[14] = q[6] ^ q[26] ^ q[27] ^ q[28] ^ q[30] ^ q[31] ^ d[2] ^ d[3] ^ d[4] ^ d[6] ^ d[7];
assign	c[15] = q[7] ^ q[27] ^ q[28] ^ q[29] ^ q[31] ^ d[3] ^ d[4] ^ d[5] ^ d[7];
assign	c[16] = q[8] ^ q[24] ^ q[28] ^ q[29] ^ d[0] ^ d[4] ^ d[5];
assign	c[17] = q[9] ^ q[25] ^ q[29] ^ q[30] ^ d[1] ^ d[5] ^ d[6];
assign	c[18] = q[10] ^ q[26] ^ q[30] ^ q[31] ^ d[2] ^ d[6] ^ d[7];
assign	c[19] = q[11] ^ q[27] ^ q[31] ^ d[3] ^ d[7];
assign	c[20] = q[12] ^ q[28] ^ d[4];
assign	c[21] = q[13] ^ q[29] ^ d[5];
assign	c[22] = q[14] ^ q[24] ^ d[0];
assign	c[23] = q[15] ^ q[24] ^ q[25] ^ q[30] ^ d[0] ^ d[1] ^ d[6];
assign	c[24] = q[16] ^ q[25] ^ q[26] ^ q[31] ^ d[1] ^ d[2] ^ d[7];
assign	c[25] = q[17] ^ q[26] ^ q[27] ^ d[2] ^ d[3];
assign	c[26] = q[18] ^ q[24] ^ q[27] ^ q[28] ^ q[30] ^ d[0] ^ d[3] ^ d[4] ^ d[6];
assign	c[27] = q[19] ^ q[25] ^ q[28] ^ q[29] ^ q[31] ^ d[1] ^ d[4] ^ d[5] ^ d[7];
assign	c[28] = q[20] ^ q[26] ^ q[29] ^ q[30] ^ d[2] ^ d[5] ^ d[6];
assign	c[29] = q[21] ^ q[27] ^ q[30] ^ q[31] ^ d[3] ^ d[6] ^ d[7];
assign	c[30] = q[22] ^ q[28] ^ q[31] ^ d[4] ^ d[7];
assign	c[31] = q[23] ^ q[29] ^ d[5];
	
endmodule
module usb3_ep_ram(
	input wr_clk,
	input wr_rst,
	input wr_we,
	input [9:0] wr_adr,
	input [31:0] wr_dat_w,

	input rd_clk,
	input rd_rst,
	input [9:0] rd_adr,
	output reg [31:0] rd_dat_r
);

reg [31:0] mem[0:1023];
reg [9:0] rd_adr_i;
always @(posedge wr_clk) begin
	if (wr_we)
		mem[wr_adr] <= wr_dat_w;
end

always @(posedge rd_clk) begin
	rd_adr_i <= rd_adr;
	rd_dat_r = mem[rd_adr_i];
end

endmodule
module usb3_ep0in_ram(
	input clk,
	input wr_we,
	input [3:0] wr_adr,
	input [31:0] wr_dat_w,
	input [3:0] rd_adr,
	output reg [31:0] rd_dat_r

);

reg [31:0] mem[0:15];
reg [3:0] rd_adr_i;
always @(posedge clk) begin
	if (wr_we)
		mem[wr_adr] <= wr_dat_w;
end

always @(posedge clk) begin
	rd_adr_i <= rd_adr;
	rd_dat_r = mem[rd_adr_i];
end

endmodule
module usb2_ep0in_ram(
	input clk,
	input wr_we,
	input [5:0] wr_adr,
	input [7:0] wr_dat_w,
	input [5:0] rd_adr,
	output reg [7:0] rd_dat_r

);

reg [7:0] mem[0:63];
reg [5:0] rd_adr_i;
always @(posedge clk) begin
	if (wr_we)
		mem[wr_adr] <= wr_dat_w;
end

always @(posedge clk) begin
	rd_adr_i <= rd_adr;
	rd_dat_r = mem[rd_adr_i];
end

endmodule
module usb2_crc5 (

input	wire	[4:0]	c,
input	wire	[10:0]	data,
output	wire	[4:0]	next_crc

);

	// reverse input
	wire	[10:0]	d = { 	data[0], data[1], data[2], data[3], data[4],
							data[5], data[6], data[7], data[8], data[9],
							data[10] };

	wire	[4:0]	q = {
		^d[10:9] ^ ^d[6:5] ^ d[3] ^ d[0] ^ c[0] ^ ^c[4:3],
		d[10] ^ ^d[7:6] ^ d[4] ^ d[1] ^ ^c[1:0] ^ c[4],
		^d[10:7] ^ d[6] ^ ^d[3:2] ^ d[0] ^ ^c[4:0],
		^d[10:7] ^^ d[4:3] ^ d[1] ^ ^c[4:1],
		^d[10:8] ^ ^d[5:4] ^ d[2] ^ ^c[4:2]
	};

	assign	next_crc = ~q;

endmodule
module usb2_crc16 (

input	wire	[15:0]	c,
input	wire	[7:0]	data,
output	wire	[15:0]	next_crc

);

	wire	[7:0]	d = {data[0], data[1], data[2], data[3],
						data[4], data[5], data[6], data[7]};

	assign next_crc = {
		^d[7:0] ^ ^c[15:7],
		c[6],
		c[5],
		c[4],
		c[3],
		c[2],
		d[7] ^ c[1] ^ c[15],
		^d[7:6] ^ ^c[0] ^ ^c[15:14],
		^d[6:5] ^ ^c[14:13],
		^d[5:4] ^ ^c[13:12],
		^d[4:3] ^ ^c[12:11],
		^d[3:2] ^ ^c[11:10],
		^d[2:1] ^ ^c[10:9],
		^d[1:0] ^ ^c[9:8],
		^d[7:1] ^ ^c[15:9],
		^d[7:0] ^ ^c[15:8]
	};

endmodule
module usb2_ep_ram(
	input wr_clk,
	input wr_we,
	input [9:0] wr_adr,
	input [7:0] wr_dat_w,

	input rd_clk,
	input [9:0] rd_adr,
	output [7:0] rd_dat_r
);

reg [7:0] mem[0:1023];
reg [9:0] rd_adr_i;
always @(posedge wr_clk) begin
	if (wr_we)
		mem[wr_adr] <= wr_dat_w;
end

always @(posedge rd_clk) begin
	rd_adr_i <= rd_adr;
end

assign rd_dat_r = mem[rd_adr_i];

endmodule
module usb2_descrip_rom(
	input clk,
	input [7:0] adr,
	output [7:0] dat_r
);

reg [7:0] mem[0:255];
reg [7:0] memadr;
always @(posedge clk) begin
	memadr <= adr;
end

assign dat_r = mem[memadr];

initial begin
	$readmemh("usb2_descrip_rom.init", mem);
end

endmodule
module design_1_wrapper
   (DDR_addr,
    DDR_ba,
    DDR_cas_n,
    DDR_ck_n,
    DDR_ck_p,
    DDR_cke,
    DDR_cs_n,
    DDR_dm,
    DDR_dq,
    DDR_dqs_n,
    DDR_dqs_p,
    DDR_odt,
    DDR_ras_n,
    DDR_reset_n,
    DDR_we_n,
    FIXED_IO_ddr_vrn,
    FIXED_IO_ddr_vrp,
    FIXED_IO_mio,
    FIXED_IO_ps_clk,
    FIXED_IO_ps_porb,
    FIXED_IO_ps_srstb);
  inout [14:0]DDR_addr;
  inout [2:0]DDR_ba;
  inout DDR_cas_n;
  inout DDR_ck_n;
  inout DDR_ck_p;
  inout DDR_cke;
  inout DDR_cs_n;
  inout [3:0]DDR_dm;
  inout [31:0]DDR_dq;
  inout [3:0]DDR_dqs_n;
  inout [3:0]DDR_dqs_p;
  inout DDR_odt;
  inout DDR_ras_n;
  inout DDR_reset_n;
  inout DDR_we_n;
  inout FIXED_IO_ddr_vrn;
  inout FIXED_IO_ddr_vrp;
  inout [53:0]FIXED_IO_mio;
  inout FIXED_IO_ps_clk;
  inout FIXED_IO_ps_porb;
  inout FIXED_IO_ps_srstb;

  wire [14:0]DDR_addr;
  wire [2:0]DDR_ba;
  wire DDR_cas_n;
  wire DDR_ck_n;
  wire DDR_ck_p;
  wire DDR_cke;
  wire DDR_cs_n;
  wire [3:0]DDR_dm;
  wire [31:0]DDR_dq;
  wire [3:0]DDR_dqs_n;
  wire [3:0]DDR_dqs_p;
  wire DDR_odt;
  wire DDR_ras_n;
  wire DDR_reset_n;
  wire DDR_we_n;
  wire FIXED_IO_ddr_vrn;
  wire FIXED_IO_ddr_vrp;
  wire [53:0]FIXED_IO_mio;
  wire FIXED_IO_ps_clk;
  wire FIXED_IO_ps_porb;
  wire FIXED_IO_ps_srstb;

  design_1 design_1_i
       (.DDR_addr(DDR_addr),
        .DDR_ba(DDR_ba),
        .DDR_cas_n(DDR_cas_n),
        .DDR_ck_n(DDR_ck_n),
        .DDR_ck_p(DDR_ck_p),
        .DDR_cke(DDR_cke),
        .DDR_cs_n(DDR_cs_n),
        .DDR_dm(DDR_dm),
        .DDR_dq(DDR_dq),
        .DDR_dqs_n(DDR_dqs_n),
        .DDR_dqs_p(DDR_dqs_p),
        .DDR_odt(DDR_odt),
        .DDR_ras_n(DDR_ras_n),
        .DDR_reset_n(DDR_reset_n),
        .DDR_we_n(DDR_we_n),
        .FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),
        .FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),
        .FIXED_IO_mio(FIXED_IO_mio),
        .FIXED_IO_ps_clk(FIXED_IO_ps_clk),
        .FIXED_IO_ps_porb(FIXED_IO_ps_porb),
        .FIXED_IO_ps_srstb(FIXED_IO_ps_srstb));
endmodule
module conv1_exec(/*autoport*/
//output
			f2_wdata,
//input
			clk,
			rst_n,
			mac_1);
	input  clk;
	input  rst_n;

	input	[137:0] mac_1;		//mac result  mac1_1 ~ mac1_6
	output	[95:0] f2_wdata;	//f2_wdata	  f2_1_wdata ~ f2_6_wdata

//Bias
parameter b_1 = 16'b0000010111101010;
parameter b_2 = 16'b1111101111001000;
parameter b_3 = 16'b0000000000101011;
parameter b_4 = 16'b1111111000100110;
parameter b_5 = 16'b1111100100101110;
parameter b_6 = 16'b0000000001101010;

wire [15:0]  d_out[5:0];
wire [15:0]  b_in [5:0];
wire [22:0]  d_in [5:0];
generate
	genvar i;
	for(i=0;i<6;i=i+1) begin:conv_unit_gen
		conv_unit conv_unit(/*autoinst*/
				.d_out(d_out[i]),
				.clk(clk),
				.rst_n(rst_n),
				.d_in(d_in[i]),
				.b_in(b_in[i]));
		
		assign d_in[i] = mac_1[23*i+22:23*i];
	end
endgenerate

assign f2_wdata = {d_out[5],d_out[4],d_out[3],d_out[2],d_out[1],d_out[0]};

// bias initial
assign b_in[0] = b_1;
assign b_in[1] = b_2;
assign b_in[2] = b_3;
assign b_in[3] = b_4;
assign b_in[4] = b_5;
assign b_in[5] = b_6;
endmodule
module channel_adder(/*autoport*/
//output
			result,
//input
			clk,
			rst_n,
			d1,
			d2,
			d3,
			d4,
			d5,
			d6);
	input clk;
	input rst_n;
	input [22:0] d1;
	input [22:0] d2;
	input [22:0] d3;
	input [22:0] d4;
	input [22:0] d5;
	input [22:0] d6;
	
	output [22:0] result;

//stage1: add
wire [22:0] s1,s2,s3;
adder_23_23 adder1 (
  .A(d1),      // input wire [18 : 0] A
  .B(d2),      // input wire [18 : 0] B
  .CLK(clk),  // input wire CLK
  .S(s1)      // output wire [18 : 0] S
);
adder_23_23 adder2 (
  .A(d3),      // input wire [18 : 0] A
  .B(d4),      // input wire [18 : 0] B
  .CLK(clk),  // input wire CLK
  .S(s2)      // output wire [18 : 0] S
);
adder_23_23 adder3 (
  .A(d5),      // input wire [18 : 0] A
  .B(d6),      // input wire [18 : 0] B
  .CLK(clk),  // input wire CLK
  .S(s3)      // output wire [18 : 0] S
);

//stage2: add
wire [22:0] s2_1;
reg  [22:0] s2_2;
adder_23_23 adder4 (
  .A(s1),      // input wire [18 : 0] A
  .B(s2),      // input wire [18 : 0] B
  .CLK(clk),  // input wire CLK
  .S(s2_1)      // output wire [18 : 0] S
);
always@(posedge clk)begin
  s2_2 <= s3;
end
//stage3: add
adder_23_23 adder5 (
  .A(s2_1),      // input wire [18 : 0] A
  .B(s2_2),      // input wire [18 : 0] B
  .CLK(clk),  // input wire CLK
  .S(result)      // output wire [18 : 0] S
);

endmodule
module conv_unit(/*autoport*/
//output
			d_out,
//input
			clk,
			rst_n,
			d_in,
			b_in);
	input clk;
	input rst_n;
	input [22:0]  d_in;	 //conv result
	input [15:0]  b_in;  //bias
	output[15:0]  d_out; //final output


//--------------------------------
//---stage1: bias add-------------
//--------------------------------
wire [22:0] temp1;
adder_23_16 adder (
  .A(d_in),      // input wire [22 : 0] A
  .B(b_in),      // input wire [15 : 0] B
  .CLK(clk),     // input wire CLK
  .S(temp1)      // output wire [22 : 0] S
);

//--------------------------------
//---stage2: ReLU-----------------
//--------------------------------
wire[15:0] temp2;
assign temp2 = temp1[22]? 0:temp1[22:7];


reg [15:0] temp2_r;
always @(posedge clk or negedge  rst_n) begin
	if (!rst_n) begin
		// reset
		temp2_r <= 0;
	end
	else  begin
		temp2_r <= temp2;
	end
end

assign d_out = temp2_r;

endmodule
module conv2_exec(/*autoport*/
//output
			f4_wdata,
//input
			mac_2,
			clk,
			rst_n);

	input [2207:0] mac_2; //mac result. mac2_1_1 ~ mac2_16_6
	

	input clk;
	input rst_n;

	output [255:0] f4_wdata; //f4_wdata. f4_1_wdata ~ f4_16_wdata

//Bias
parameter b_1 = 16'b0000001100101101;
parameter b_2 = 16'b1111111010111110;
parameter b_3 = 16'b0000000010100000;
parameter b_4 = 16'b1111100101000010;
parameter b_5 = 16'b1111111011101010;
parameter b_6 = 16'b1111011001101101;
parameter b_7 = 16'b1111111111100000;
parameter b_8 = 16'b1111110100101000;
parameter b_9 = 16'b0000000011011001;
parameter b_10 = 16'b1111010010111100;
parameter b_11 = 16'b1111100011001010;
parameter b_12 = 16'b1111011101010010;
parameter b_13 = 16'b1111100100100110;
parameter b_14 = 16'b1111110010101111;
parameter b_15 = 16'b1111110111000000;
parameter b_16 = 16'b1111011100110000;




wire [22:0] mac2[95:0];
wire [22:0] d_in[15:0];
wire [15:0] d_out[15:0];
wire [15:0]  b_in[15:0];
generate
	genvar k,l;
	for(k=0;k<16;k=k+1) begin:loop16
		channel_adder channel_adder(/*autoinst*/
			.result(d_in[k]),
			.clk(clk),
			.rst_n(rst_n),
			.d1(mac2[k*6+0]),
			.d2(mac2[k*6+1]),
			.d3(mac2[k*6+2]),
			.d4(mac2[k*6+3]),
			.d5(mac2[k*6+4]),
			.d6(mac2[k*6+5]));
		conv_unit conv_unit(/*autoinst*/
			.d_out(d_out[k]),
			.clk(clk),
			.rst_n(rst_n),
			.d_in(d_in[k]),
			.b_in(b_in[k]));
	end
	for(l=0;l<96;l=l+1) begin:loop96
		assign mac2[l] = mac_2[23*l+22:23*l];
	end
endgenerate

assign f4_wdata = {d_out[15],d_out[14],d_out[13],d_out[12],
	d_out[11],d_out[10],d_out[9],d_out[8],d_out[7],d_out[6],
	d_out[5],d_out[4],d_out[3],d_out[2],d_out[1],d_out[0]};

//Bias initial
assign b_in[0] = b_1;
assign b_in[1] = b_2;
assign b_in[2] = b_3;
assign b_in[3] = b_4;
assign b_in[4] = b_5;
assign b_in[5] = b_6;
assign b_in[6] = b_7;
assign b_in[7] = b_8;
assign b_in[8] = b_9;
assign b_in[9] = b_10;
assign b_in[10] = b_11;
assign b_in[11] = b_12;
assign b_in[12] = b_13;
assign b_in[13] = b_14;
assign b_in[14] = b_15;
assign b_in[15] = b_16;

endmodule
module f3_ram(/*autoport*/
//output
			f3_rdata,
//input
			clk,
			f3_wdata,
			f3_wr_en,
			f3_waddr,
			f3_raddr);
	input clk;
//write side
	input [95:0] f3_wdata;

	input 		 f3_wr_en;
	input [7:0]  f3_waddr;
//read side
	input [7:0]  f3_raddr;
	output[95:0] f3_rdata;

	blk_mem_gen_f3_ram f3_ram (
	  .clka(clk),    // input clka
	  .wea(f3_wr_en),      // input [0 : 0] wea
	  .addra(f3_waddr),  // input [7 : 0] addra
	  .dina(f3_wdata),    // input [95 : 0] dina
	  .clkb(clk),    // input clkb
	  .addrb(f3_raddr),  // input [7 : 0] addrb
	  .doutb(f3_rdata)  // output [95 : 0] doutb
	);

endmodule
module f1_ram(/*autoport*/
//output
			f1_rdata,
//input
			rclk,
			wclk,
			f1_wr_en,
			f1_waddr,
			f1_wdata,
			ena,
			f1_raddr);
input			rclk;
input			wclk;
input [3:0]    	f1_wr_en;
input [31:0]   	f1_waddr;
input [31:0]   	f1_wdata;
input			ena;
input [9:0]    	f1_raddr;
output[7:0]  	f1_rdata; 



//2 cycles delay
blk_mem_gen_f1_ram f1_ram (
  .clka(wclk),    // input clka
  .ena(ena),  
  .wea(f1_wr_en),      // input [3 : 0] wea
  .addra(f1_waddr),  // input [31 : 0] addra
  .dina(f1_wdata),    // input [31 : 0] dina
  .clkb(rclk),    // input clkb
  .addrb({20'b0,f1_raddr,2'b0}),  // input [31 : 0] addrb
  .doutb(f1_rdata)  // output [31 : 0] doutb
);

endmodule
module w1_rom(/*autoport*/
//output
			w1_rdata,
//input
			clk,
			w1_raddr);
	
	input clk;
	input  [4:0] 	w1_raddr;
	output [47:0]	w1_rdata;

  dist_mem_gen_w1_rom w1_rom (
    .a(w1_raddr),        // input [4 : 0] a
    .clk(clk),    // input clk
    .qspo(w1_rdata)  // output [47 : 0] qspo
  );

endmodule
module w6_rom(/*autoport*/
//output
      w6_rdata,
//input
      clk,
      w6_raddr);

	  input		 clk;
	  input  [6:0] w6_raddr;
    output [671:0] w6_rdata;
   
  blk_mem_gen_w6_rom w6_rom (
    .clka(clk),    // input clka
    .addra(w6_raddr),  // input [6 : 0] addra
    .douta(w6_rdata)  // output [671 : 0] douta
  );

endmodule
module w5_rom(/*autoport*/
//output
      w5_rdata,
//input
      clk,
      w5_raddr);
	
	input clk;
	input [8:0] w5_raddr;
  output[959:0] w5_rdata;

  blk_mem_gen_w5_rom w5_rom (
    .clka(clk),    // input clka
    .addra(w5_raddr),  // input [8 : 0] addra
    .douta(w5_rdata)  // output [959 : 0] douta
  );


endmodule
module f5_ram(/*autoport*/
//output
      f5_rdata,
//input
      clk,
      f5_waddr,
      f5_wdata,
      f5_wr_en,
      f5_sel,
      f5_raddr);

  

	input clk;
	input [4:0]  f5_waddr;
  input [255:0]f5_wdata;
	input        f5_wr_en;
	input [3:0]  f5_sel;
	input [4:0]  f5_raddr;

	output [15:0] f5_rdata;


  wire [15:0] f5_1_rdata;
  wire [15:0] f5_2_rdata;
  wire [15:0] f5_3_rdata;
  wire [15:0] f5_4_rdata;
  wire [15:0] f5_5_rdata;
  wire [15:0] f5_6_rdata;
  wire [15:0] f5_7_rdata;
  wire [15:0] f5_8_rdata;
  wire [15:0] f5_9_rdata;
  wire [15:0] f5_10_rdata;
  wire [15:0] f5_11_rdata;
  wire [15:0] f5_12_rdata;
  wire [15:0] f5_13_rdata;
  wire [15:0] f5_14_rdata;
  wire [15:0] f5_15_rdata;
  wire [15:0] f5_16_rdata;

  wire [255:0] f5_rdata_all;
  dist_mem_gen_f5_ram f5_ram (
    .a(f5_waddr),        // input [4 : 0] a
    .d(f5_wdata),        // input [255 : 0] d
    .dpra(f5_raddr),  // input [4 : 0] dpra
    .clk(clk),    // input clk
    .we(f5_wr_en),      // input we
    .qdpo(f5_rdata_all)  // output [255 : 0] qdpo
  );


  assign f5_1_rdata = f5_rdata_all[15:0];
  assign f5_2_rdata = f5_rdata_all[31:16];
  assign f5_3_rdata = f5_rdata_all[47:32];
  assign f5_4_rdata = f5_rdata_all[63:48];
  assign f5_5_rdata = f5_rdata_all[79:64];
  assign f5_6_rdata = f5_rdata_all[95:80];
  assign f5_7_rdata = f5_rdata_all[111:96];
  assign f5_8_rdata = f5_rdata_all[127:112];
  assign f5_9_rdata = f5_rdata_all[143:128];
  assign f5_10_rdata = f5_rdata_all[159:144];
  assign f5_11_rdata = f5_rdata_all[175:160];
  assign f5_12_rdata = f5_rdata_all[191:176];
  assign f5_13_rdata = f5_rdata_all[207:192];
  assign f5_14_rdata = f5_rdata_all[223:208];
  assign f5_15_rdata = f5_rdata_all[239:224];
  assign f5_16_rdata = f5_rdata_all[255:240];





  reg[3:0] f5_sel_r1,f5_sel_r2;
  always@(posedge clk)begin
    f5_sel_r1 <= f5_sel;
    f5_sel_r2 <= f5_sel_r1;
  end


  reg[15:0] f5_rdata_temp;
  always@(posedge clk)begin
  	case(f5_sel_r2)
      4'd0:f5_rdata_temp = f5_1_rdata;
      4'd1:f5_rdata_temp = f5_2_rdata;
      4'd2:f5_rdata_temp = f5_3_rdata;
      4'd3:f5_rdata_temp = f5_4_rdata;
      4'd4:f5_rdata_temp = f5_5_rdata;
      4'd5:f5_rdata_temp = f5_6_rdata;
      4'd6:f5_rdata_temp = f5_7_rdata;
      4'd7:f5_rdata_temp = f5_8_rdata;
      4'd8:f5_rdata_temp = f5_9_rdata;
      4'd9:f5_rdata_temp = f5_10_rdata;
      4'd10:f5_rdata_temp = f5_11_rdata;
      4'd11:f5_rdata_temp = f5_12_rdata;
      4'd12:f5_rdata_temp = f5_13_rdata;
      4'd13:f5_rdata_temp = f5_14_rdata;
      4'd14:f5_rdata_temp = f5_15_rdata;
      4'd15:f5_rdata_temp = f5_16_rdata;
  	endcase
  end

  assign f5_rdata = f5_rdata_temp;
endmodule
module f4_ram(/*autoport*/
//output
			f4_rdata,
//input
			clk,
			f4_wdata,
			f4_wr_en,
			f4_waddr,
			f4_raddr);
	input clk;
//write side
	input [255:0] f4_wdata;


	input 		  f4_wr_en;
	input [6:0]   f4_waddr;
//read side
	input [6:0]   f4_raddr;
	output[255:0] f4_rdata;


	blk_mem_gen_f4_ram f4_ram (
	  .clka(clk),    // input clka
	  .wea(f4_wr_en),      // input [0 : 0] wea
	  .addra(f4_waddr),  // input [6 : 0] addra
	  .dina(f4_wdata),    // input [255 : 0] dina
	  .clkb(clk),    // input clkb
	  .addrb(f4_raddr),  // input [6 : 0] addrb
	  .doutb(f4_rdata)  // output [255 : 0] doutb
	);

endmodule
module w7_rom(/*autoport*/
//output
      w7_rdata,
//input
      clk,
      w7_raddr);
	input		 clk;
	input  [6:0] w7_raddr;

  output [79:0] w7_rdata;


  blk_mem_gen_w7_rom w7_rom (
    .clka(clk),    // input clka
    .addra(w7_raddr),  // input [6 : 0] addra
    .douta(w7_rdata)  // output [79 : 0] douta
  );


endmodule
module f2_ram(/*autoport*/
//output
			f2_rdata,
//input
			clk,
			f2_wdata,
			f2_wr_en,
			f2_waddr,
			f2_raddr);
	input clk;
//write side
	input [95:0]	f2_wdata;
	input 		  	f2_wr_en;
	input [9:0]  	f2_waddr;
//read side
	input [9:0]  	f2_raddr;
	output [95:0]	f2_rdata;

	blk_mem_gen_f2_ram f2_ram (
	  .clka(clk),    // input clka
	  .wea(f2_wr_en),      // input [0 : 0] wea
	  .addra(f2_waddr),  // input [9 : 0] addra
	  .dina(f2_wdata),    // input [95 : 0] dina
	  .clkb(clk),    // input clkb
	  .addrb(f2_raddr),  // input [9 : 0] addrb
	  .doutb(f2_rdata)  // output [95 : 0] doutb
	);
	
endmodule
module pool2_exec(/*autoport*/
//output
			f5_wdata,
//input
			clk,
			rst_n,
			f4_rdata,
			pool2_clr);
	input  	clk;
	input  	rst_n;

	input	[255:0]	f4_rdata;	//input f4_1 ~ f4_16
	output	[255:0]	f5_wdata;	//output f5_1 ~ f5_16
	input 	pool2_clr;

	wire [15:0] d_in[15:0];
	wire [15:0]	d_out[15:0];
	generate
		genvar i;
		for (i = 0; i < 16; i = i + 1)
		begin:pool_unit_gen
			pool_unit  pool_unit(/*autoinst*/
			.d_out(d_out[i]),
			.clk(clk),
			.rst_n(rst_n),
			.d_in(d_in[i]),
			.pool_clr(pool2_clr));
			assign d_in[i] = f4_rdata[16*i+15:16*i];
		end
	endgenerate
	assign f5_wdata = {d_out[15],d_out[14],d_out[13],d_out[12],d_out[11],d_out[10],
		d_out[9],d_out[8],d_out[7],d_out[6],d_out[5],d_out[4],d_out[3],
		d_out[2],d_out[1],d_out[0]};
endmodule
module pool_unit(/*autoport*/
//output
			d_out,
//input
			clk,
			rst_n,
			d_in,
			pool_clr);
	input  	clk;
	input  	rst_n;

	input 	pool_clr;
	input 	[15:0]	d_in;
	output 	[15:0]	d_out;

//------------------------------
//------stage1: compare---------
//------------------------------
wire [15:0] temp;
assign temp = (temp_r >d_in )? temp_r:d_in;


reg [15:0] temp_r;
always @(posedge clk or negedge rst_n) begin
	if (!rst_n) begin
		// reset
		temp_r <= 0;
	end
	else if (pool_clr) begin
		temp_r <= d_in;
	end
	else begin
		temp_r <= temp;
	end	
end


//------------------------------
//------output to external------
//------------------------------

assign d_out = temp_r;


endmodule
module pool1_exec(/*autoport*/
//output
			f2_rdata,
//input
			clk,
			rst_n,
			f3_wdata,
			pool1_clr);
	input  	clk;
	input  	rst_n;

	output	[95:0]	f3_wdata;	//output f3_1 ~ f3_6
	input	[95:0] 	f2_rdata;	//input  f2_1 ~ f2_6
	input 	pool1_clr;			

	wire [15:0] d_in[5:0];
	wire [15:0]	d_out[5:0];
	generate
		genvar i;
		for (i = 0; i < 6; i = i + 1)
		begin:pool_unit_gen
			pool_unit  pool_unit(/*autoinst*/
			.d_out(d_out[i]),
			.clk(clk),
			.rst_n(rst_n),
			.d_in(d_in[i]),
			.pool_clr(pool1_clr));
		
		assign d_in[i] = f2_rdata[16*i+15:16*i];
		end
	endgenerate
	assign f3_wdata = {d_out[5],d_out[4],d_out[3],d_out[2],d_out[1],d_out[0]};

endmodule
module fc3_ctrl(/*autoport*/
//output
			f7_raddr,
			w7_raddr,
			f8_wr_en,
			fc3_done,
			fc3_clr,
//input
			clk,
			rst_n,
			fc3_start);
	input 	clk;
	input 	rst_n;

	//Input Weight and Feature Read Addr	
	output [6:0]f7_raddr;
	output [6:0]w7_raddr;
	//Output Feature Write Enable
	output      f8_wr_en;
	//Control Signal
	input 	fc3_start;
	output 	fc3_done;
	output 	fc3_clr;

	localparam	IDLE=3'b001;
	localparam  RUN =3'b010;
	localparam  DONE=3'b100;
	reg[2:0] current_state;
	reg[2:0] next_state;

	reg[6:0] cnt0;

	wire add_cnt0,end_cnt0;
	wire IDLE2RUN_start,RUN2DONE_start;

	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			current_state <= IDLE;
		else
			current_state <= next_state;
	end

	always@(*) begin
		case(current_state)
			IDLE:begin
				if(IDLE2RUN_start)
					next_state = RUN;
				else
					next_state = IDLE;
			end
			RUN:begin
				if(RUN2DONE_start)
					next_state = DONE;
				else begin
					next_state = current_state;
				end
			end
			DONE:begin
				next_state = IDLE;
			end
			default: next_state = IDLE;	
		endcase
	end

	assign IDLE2RUN_start = current_state==IDLE && fc3_start == 1'b1;
	assign RUN2DONE_start = current_state==RUN  && end_cnt0;

	always @(posedge clk or negedge  rst_n) begin
		if (!rst_n) begin
			// reset
			cnt0 <= 0;
		end
		else if (add_cnt0) begin
			if(end_cnt0)begin
				cnt0 <= 0;
			end
			else begin
				cnt0 <= cnt0 + 1'b1;
			end
		end
	end

	assign add_cnt0 = current_state==RUN;
	assign end_cnt0 = add_cnt0 && cnt0 == 84-1;


	assign f7_raddr = cnt0;
	assign w7_raddr = cnt0;


	wire f8_wr_en_temp,fc3_clr_temp,fc3_done_temp;
	assign f8_wr_en_temp = end_cnt0;
	assign fc3_clr_temp = cnt0==0 ;
	assign fc3_done_temp = current_state==DONE;
	//add delay
	reg fc3_clr_temp_r1,fc3_clr_temp_r2,fc3_clr_temp_r3;
	reg f8_wr_en_temp_r1,f8_wr_en_temp_r2,f8_wr_en_temp_r3,
			f8_wr_en_temp_r4,f8_wr_en_temp_r5,f8_wr_en_temp_r6,f8_wr_en_temp_r7;
	reg fc3_done_temp_r1,fc3_done_temp_r2,fc3_done_temp_r3,
			fc3_done_temp_r4,fc3_done_temp_r5,fc3_done_temp_r6,fc3_done_temp_r7;

	always@(posedge clk)begin

    	f8_wr_en_temp_r1 <= f8_wr_en_temp ;
    	f8_wr_en_temp_r2 <= f8_wr_en_temp_r1 ;
    	f8_wr_en_temp_r3 <= f8_wr_en_temp_r2 ;
    	f8_wr_en_temp_r4 <= f8_wr_en_temp_r3 ;
    	f8_wr_en_temp_r5 <= f8_wr_en_temp_r4 ;
    	f8_wr_en_temp_r6 <= f8_wr_en_temp_r5 ;
    	f8_wr_en_temp_r7 <= f8_wr_en_temp_r6 ;

   		fc3_done_temp_r1 <= fc3_done_temp;
    	fc3_done_temp_r2 <= fc3_done_temp_r1;
    	fc3_done_temp_r3 <= fc3_done_temp_r2;
    	fc3_done_temp_r4 <= fc3_done_temp_r3;
    	fc3_done_temp_r5 <= fc3_done_temp_r4;
    	fc3_done_temp_r6 <= fc3_done_temp_r5;
    	fc3_done_temp_r7 <= fc3_done_temp_r6;

    	fc3_clr_temp_r1 <= fc3_clr_temp ;
    	fc3_clr_temp_r2 <= fc3_clr_temp_r1 ;
    	fc3_clr_temp_r3 <= fc3_clr_temp_r2 ;

	end

	assign f8_wr_en = f8_wr_en_temp_r7;
	assign fc3_clr = fc3_clr_temp_r3;
	assign fc3_done = fc3_done_temp_r7;


endmodule