dakies/OSS_Verilog huggingface dataset:
module test_bench ();

	reg CLOCK_50;
	reg rst;

	// 50MHz
	initial begin
		CLOCK_50 = 0;
		forever #10 CLOCK_50 = ~CLOCK_50;
	end

	initial begin
		rst = 1;
		#185 rst = 0;
		#2000 $stop;
	end

	riscv_min_sopc riscv_min_sopc0 (
		.clk(CLOCK_50),
		.rst(rst)
	);

endmodule // test_bench
module sim_cpu();
	reg  clk;
	reg  rst;
	wire button = ~rst;
	wire Rx, Tx;

    wire rst_led;
    
	cpu cpu0(clk,button, rst_led, Tx,Rx);
	sim_memory sim_memory0(clk,rst,Rx,Tx);

	initial begin
		clk = 0;
		forever #5 clk = ~clk;
	end

	initial begin
		rst = 1;
		#1000 rst = 0;
		//#10000000 $stop;
		#10000000 $stop;
	end

endmodule
module reg_ex_mem (
	input  wire               clk          ,
	input  wire               rst          ,
	input  wire [`RegAddrBus] ex_reg_waddr ,
	input  wire               ex_we        ,
	input  wire [    `RegBus] ex_reg_wdata ,
	input  wire [        5:0] stall        ,
	input  wire [`MemAddrBus] ex_mem_addr  ,
	input  wire [  `AluOpBus] ex_aluop     ,
	input  wire [    `RegBus] ex_rt_data   ,
	output reg  [`RegAddrBus] mem_reg_waddr,
	output reg                mem_we       ,
	output reg  [    `RegBus] mem_reg_wdata,
	output reg  [`MemAddrBus] mem_mem_addr ,
	output reg  [  `AluOpBus] mem_aluop    ,
	output reg  [    `RegBus] mem_rt_data
);

	always @ (posedge clk) begin
		if(rst || (stall[3] && !stall[4])) begin
			mem_reg_waddr <= 0;
			mem_we        <= 0;
			mem_reg_wdata <= 0;
			mem_mem_addr  <= 0;
			mem_aluop     <= 0;
			mem_rt_data   <= 0;
		end else if (!stall[3]) begin
			mem_reg_waddr <= ex_reg_waddr;
			mem_we        <= ex_we;
			mem_reg_wdata <= ex_reg_wdata;
			mem_mem_addr  <= ex_mem_addr;
			mem_aluop     <= ex_aluop;
			mem_rt_data   <= ex_rt_data;
		end
	end

endmodule // reg_ex_mem
module cpu (
	input  wire EXCLK  ,
	input  wire button ,
	output wire rst_led,
	output wire Tx     ,
	input  wire Rx
);

	reg rst;
	assign rst_led = rst;
	reg rst_delay;

	wire clk;
	clk_wiz_0 clk_wiz_0_0(.clk_out1(clk), .reset(0), .clk_in1(EXCLK));

	always @ (posedge clk or negedge button) begin
		if (!button) begin
			rst       <= 1;
			rst_delay <= 1;
		end else begin
			rst_delay <= 0;
			rst       <= rst_delay;
		end
	end

	wire       UART_send_flag ;
	wire [7:0] UART_send_data ;
	wire       UART_recv_flag ;
	wire [7:0] UART_recv_data ;
	wire       UART_sendable  ;
	wire       UART_receivable;

	uart_trans uart_trans0 (
		clk, rst,
		UART_send_flag, UART_send_data,
		UART_recv_flag, UART_recv_data,
		UART_sendable, UART_receivable,
		Tx, Rx
	);

	localparam CHANNEL_BIT = 1               ;
	localparam MESSAGE_BIT = 72              ;
	localparam CHANNEL     = 1 << CHANNEL_BIT;

	wire                   COMM_read_flag   [CHANNEL-1:0];
	wire [MESSAGE_BIT-1:0] COMM_read_data   [CHANNEL-1:0];
	wire [            4:0] COMM_read_length [CHANNEL-1:0];
	wire                   COMM_write_flag  [CHANNEL-1:0];
	wire [MESSAGE_BIT-1:0] COMM_write_data  [CHANNEL-1:0];
	wire [            4:0] COMM_write_length[CHANNEL-1:0];
	wire                   COMM_readable    [CHANNEL-1:0];
	wire                   COMM_writable    [CHANNEL-1:0];

	multichan_trans #(.MESSAGE_BIT(MESSAGE_BIT), .CHANNEL_BIT(CHANNEL_BIT)) multichan_trans0 (
		clk, rst,
		UART_send_flag, UART_send_data,
		UART_recv_flag, UART_recv_data,
		UART_sendable, UART_receivable,
		{COMM_read_flag[1], COMM_read_flag[0]},
		{COMM_read_length[1], COMM_read_data[1], COMM_read_length[0], COMM_read_data[0]},
		{COMM_write_flag[1], COMM_write_flag[0]},
		{COMM_write_length[1], COMM_write_data[1], COMM_write_length[0], COMM_write_data[0]},
		{COMM_readable[1], COMM_readable[0]},
		{COMM_writable[1], COMM_writable[0]}
	);

	wire [ 2*2-1:0] mem_rwe   ;
	wire [2*32-1:0] mem_addr  ;
	wire [2*32-1:0] mem_r_data;
	wire [2*32-1:0] mem_w_data;
	wire [ 2*4-1:0] mem_sel   ;
	wire [     1:0] mem_busy  ;
	wire [     1:0] mem_done  ;

	mem_ctrl mem_ctrl0 (
		clk, rst,
		COMM_write_flag[0], COMM_write_data[0], COMM_write_length[0],
		COMM_read_flag[0], COMM_read_data[0], COMM_read_length[0],
		COMM_writable[0], COMM_readable[0],
		mem_rwe, mem_addr,
		mem_r_data, mem_w_data, mem_sel,
		mem_busy, mem_done
	);

	riscv_cpu riscv_cpu0 (
		// input
		.clk       (clk       ),
		.rst       (rst       ),
		.mem_data_i(mem_r_data),
		.mem_busy_i(mem_busy  ),
		.mem_done_i(mem_done  ),
		// output
		.mem_rwe_o (mem_rwe   ),
		.mem_addr_o(mem_addr  ),
		.mem_sel_o (mem_sel   ),
		.mem_data_o(mem_w_data)
	);

endmodule // cpu
module ctrl (
	input  wire       rst         ,
	input  wire       stallreq_if ,
	input  wire       stallreq_id ,
	input  wire       stallreq_ex ,
	input  wire       stallreq_mem,
	output reg  [5:0] stall
);

// stall[0] PC
// stall[1] IF
// stall[2] ID
// stall[3] EX
// stall[4] MEM
// stall[5] WB

	always @ (*) begin
		if(rst) begin
			stall <= 6'b000000;
		end else if (stallreq_mem) begin
			stall <= 6'b011111;
		end else if (stallreq_ex) begin
			stall <= 6'b001111;
		end else if (stallreq_id) begin
			stall <= 6'b000111;
		end else if (stallreq_if) begin
			stall <= 6'b000011;
		end else begin
			stall <= 6'b000000;
		end
	end // always @ (*)

endmodule
module reg_mem_wb (
	input  wire               clk          ,
	input  wire               rst          ,
	input  wire [`RegAddrBus] mem_reg_waddr,
	input  wire               mem_we       ,
	input  wire [    `RegBus] mem_reg_wdata,
	input  wire [5:0]         stall        ,
	output reg  [`RegAddrBus] wb_reg_waddr ,
	output reg                wb_we        ,
	output reg  [    `RegBus] wb_reg_wdata
);

	always @ (posedge clk) begin
		if(rst || (stall[4] && !stall[5])) begin
			wb_reg_waddr <= 0;
			wb_we        <= 0;
			wb_reg_wdata <= 0;
		end else if (!stall[4]) begin
			wb_reg_waddr <= mem_reg_waddr;
			wb_we        <= mem_we;
			wb_reg_wdata <= mem_reg_wdata;
		end
	end

endmodule // reg_mem_wb
module stage_if (
	input  wire               rst       ,
	input  wire [`MemAddrBus] pc_i      ,
	input  wire [    `RegBus] mem_data_i,
	input  wire               mem_busy  ,
	input  wire               mem_done  ,
	input  wire               br        ,
	input  wire               right_one ,
	output reg                mem_re    ,
	output reg  [`MemAddrBus] mem_addr_o,
	output reg  [`MemAddrBus] pc_o      ,
	output reg  [   `InstBus] inst_o    ,
	output reg                stallreq
);

	reg mem_taking;
	reg waiting_one;

	always @ (*) begin
		if (right_one) begin
			waiting_one = 0;
			//$display("Right one is here, %h", pc_i);
		end
		if (rst) begin
			stallreq    = 0;
			mem_taking  = 0;
			pc_o        = 0;
			inst_o      = 0;
			mem_re      = 0;
			mem_addr_o  = 0;
			waiting_one = 0;
		end else if (br) begin
			//$display("br");
			pc_o        = 0;
			inst_o      = 0;
			mem_taking  = 0;
			stallreq    = 0;
			waiting_one = 1;
		end else if (!waiting_one && !mem_busy && !mem_taking) begin
			//$display("!mem_busy && !mem_taking");
			stallreq   = 1;
			mem_taking = 1;
			mem_re     = 1;
			mem_addr_o = pc_i;
		end else if (!waiting_one && !mem_busy && mem_taking) begin
			//$display("!mem_busy && mem_taking");
			stallreq   = 0;
			mem_taking = 0;
			pc_o       = pc_i;
			inst_o     = mem_data_i;
			//$display("IF Get Inst: %h\n", inst_o);
		end else if (!waiting_one && mem_busy) begin
			//$display("mem_busy, %h", pc_i);
			stallreq = 1;
		end else if (!waiting_one) begin
			stallreq    = 0;
			mem_taking  = 0;
			pc_o        = 0;
			inst_o      = 0;
			mem_re      = 0;
			mem_addr_o  = 0;
			waiting_one = 0;
		end
	end

endmodule // stage_if
module reg_pc (
	input  wire                clk        ,
	input  wire                rst        ,
	input  wire [         5:0] stall      ,
	input  wire                br         ,
	input  wire [`InstAddrBus] br_addr    ,
	output reg  [`InstAddrBus] pc_o       ,
	output reg                 right_one_o
);

	reg [`InstAddrBus] pc       ;
	reg                right_one;

	always @ (posedge clk) begin
		if (!rst && br) begin
			pc <= br_addr;
			right_one <= 1;
		end else if (!rst && !stall[0]) begin
			pc <= pc + 4;
			right_one <= 0;
		end
		if (rst) begin
			pc_o      <= 0;
			right_one <= 0;
			pc        <= 4;
		end else if (!stall[0]) begin
			//$display("PC now: %h", pc);
			pc_o <= pc;
			right_one_o <= right_one;
		end
	end

	/*always @ (posedge clk) begin
		if (rst) begin
			pc_o <= 0;
		end else if (!stall[0]) begin
			if (br) pc_o <= br_addr;
			else pc_o <= pc_o + 4;
		end
	end*/

endmodule // reg_pc
module simple_ram #(
	parameter AddrBusWidth     = 16,
	parameter DataBusByteWidth = 4
) (
	input  wire                          clk   ,
	input  wire                          rst   ,
	input  wire                          re    ,
	input  wire [      AddrBusWidth-1:0] r_addr,
	input  wire                          we    ,
	input  wire [8*DataBusByteWidth-1:0] w_data,
	input  wire [      AddrBusWidth-1:0] w_addr,
	input  wire [  DataBusByteWidth-1:0] w_sel ,
	output reg  [8*DataBusByteWidth-1:0] r_data
);

	reg [8*DataBusByteWidth-1:0] data[(1<<AddrBusWidth)-1:0];

	always @ (posedge clk) begin
		if (!rst && we) begin
			if(w_sel[0]) data[w_addr][7:0] <= w_data[7:0];
			if(w_sel[1]) data[w_addr][15:8] <= w_data[15:8];
			if(w_sel[2]) data[w_addr][23:16] <= w_data[23:16];
			if(w_sel[3]) data[w_addr][31:24] <= w_data[31:24];
		end
	end

	always @ (posedge clk) begin
		if (rst) begin
			r_data <= 0;
		end else if (re) begin
			r_data <= data[r_addr];
		end else begin
			r_data <= 0;
		end
	end

endmodule // simple_ram
module regfile (
	input  wire               clk   ,
	input  wire               rst   ,
	input  wire               we    ,
	input  wire [`RegAddrBus] waddr ,
	input  wire [    `RegBus] wdata ,
	input  wire               re1   ,
	input  wire [`RegAddrBus] raddr1,
	output reg  [    `RegBus] rdata1,
	input  wire               re2   ,
	input  wire [`RegAddrBus] raddr2,
	output reg  [    `RegBus] rdata2
);

	reg[`RegBus]  regs[0:`RegNum-1];

	// write
	always @ (posedge clk) begin
		if (!rst) begin
			// x0 cannot be written
			if (we && waddr != 0) begin
				//$display("WRITE REGISTER FILE: x%d = %h", waddr, wdata);
				regs[waddr] <= wdata;
			end
		end
	end

	// read 1
	always @ (*) begin
		if (rst || !re1 || raddr1 == 0) begin
			rdata1 <= 0;
		end else if (we && raddr1 == waddr) begin
			rdata1 <= wdata;
		end else begin
			rdata1 <= regs[raddr1];
		end
	end

	// read 2
	always @ (*) begin
		if (rst || !re2 || raddr2 == 0) begin
			rdata2 <= 0;
		end else if (we && raddr2 == waddr) begin
			rdata2 <= wdata;
		end else begin
			rdata2 <= regs[raddr2];
		end
	end

endmodule // regfile
module reg_id_ex (
	input  wire                clk          ,
	input  wire                rst          ,
	input  wire [   `AluOpBus] id_aluop     ,
	input  wire [  `AluSelBus] id_alusel    ,
	input  wire [     `RegBus] id_opv1      ,
	input  wire [     `RegBus] id_opv2      ,
	input  wire [ `RegAddrBus] id_reg_waddr ,
	input  wire                id_we        ,
	input  wire [         5:0] stall        ,
	input  wire [`InstAddrBus] id_link_addr ,
	input  wire [     `RegBus] id_mem_offset,
	output reg  [   `AluOpBus] ex_aluop     ,
	output reg  [  `AluSelBus] ex_alusel    ,
	output reg  [     `RegBus] ex_opv1      ,
	output reg  [     `RegBus] ex_opv2      ,
	output reg  [ `RegAddrBus] ex_reg_waddr ,
	output reg                 ex_we        ,
	output reg  [`InstAddrBus] ex_link_addr ,
	output reg  [     `RegBus] ex_mem_offset
);

	always @ (posedge clk) begin
		if (rst || (stall[2] && !stall[3])) begin
			ex_aluop      <= `EXE_NOP_OP;
			ex_alusel     <= `EXE_RES_NOP;
			ex_opv1       <= 0;
			ex_opv2       <= 0;
			ex_reg_waddr  <= 0;
			ex_we         <= 0;
			ex_link_addr  <= 0;
			ex_mem_offset <= 0;
		end else if (!stall[2]) begin
			ex_aluop      <= id_aluop;
			ex_alusel     <= id_alusel;
			ex_opv1       <= id_opv1;
			ex_opv2       <= id_opv2;
			ex_reg_waddr  <= id_reg_waddr;
			ex_we         <= id_we;
			ex_link_addr  <= id_link_addr;
			ex_mem_offset <= id_mem_offset;
		end
	end

endmodule // reg_id_ex
module reg_if_id (
	input  wire                clk    ,
	input  wire                rst    ,
	input  wire [`InstAddrBus] if_pc  ,
	input  wire [    `InstBus] if_inst,
	input  wire [         5:0] stall  ,
	input  wire                br     ,
	output reg  [`InstAddrBus] id_pc  ,
	output reg  [    `InstBus] id_inst
);

	always @ (posedge clk) begin
		if (rst || br || (stall[1] && !stall[2])) begin
			id_pc   <= 0;
			id_inst <= 0;
		end else if (!stall[1]) begin
			id_pc   <= if_pc;
			id_inst <= if_inst;
		end
	end

endmodule // reg_if_id
module fifo
	#(
	parameter SIZE_BIT	= 3,
	parameter WIDTH 	= 8
	)
	(
	input CLK,
	input RST,
	input read_flag,
	output [WIDTH-1:0] read_data,
	input write_flag,
	input [WIDTH-1:0] write_data,
	output empty,
	output full
    );
    
    localparam SIZE = 1 << SIZE_BIT;
    reg [WIDTH-1:0] buffer[SIZE-1:0];
    reg [SIZE_BIT-1:0] read_ptr;
    reg [SIZE_BIT-1:0] write_ptr;
    reg [SIZE_BIT:0] buffer_size;
    
    assign empty = buffer_size == 0;
    assign full  = buffer_size == SIZE;
    
    wire read, write;
    assign read  = read_flag && !empty;
    assign write = write_flag && !full;
    
    assign read_data = buffer[read_ptr];
    
    integer i;
    always @(negedge CLK or posedge RST) begin
    	if(RST) begin
    		read_ptr <= 0;
    		write_ptr <= 0;
    		buffer_size <= 0;
    		for(i=0; i<SIZE; i=i+1)
    			buffer[i] <= 0;
    	end else begin
    		if(read && write) begin
    			buffer[write_ptr] <= write_data;
    			read_ptr <= read_ptr + 1;
    			write_ptr <= write_ptr + 1;
    		end else if(read) begin
    			read_ptr <= read_ptr + 1;
    			buffer_size <= buffer_size - 1;
    		end else if(write) begin
    			buffer[write_ptr] <= write_data;
    			write_ptr <= write_ptr + 1;
    			buffer_size <= buffer_size + 1;
    		end
    	end
    end
endmodule
module simo_fifo
	#(
	parameter CHANNEL_BIT = 1,
	parameter SIZE_BIT = 3,
	parameter WIDTH = 8
	)
	(
	input CLK,
	input RST,
	
	input [(1<<CHANNEL_BIT)-1:0] read_flags,
	output [(1<<CHANNEL_BIT)*WIDTH-1:0] read_datas,
	
	input write_flag,
	input [CHANNEL_BIT-1:0] write_select,
	input [WIDTH-1:0] write_data,
	
	output [(1<<CHANNEL_BIT)-1:0] empty,
	output [(1<<CHANNEL_BIT)-1:0] full
    );
    
    localparam CHANNEL = 1 << CHANNEL_BIT;
	genvar i;
	generate 
		for(i=0; i < CHANNEL; i=i+1) begin
			wire write_current;
			assign write_current = write_select == i ? write_flag : 0; 
			fifo #(.SIZE_BIT(SIZE_BIT), .WIDTH(WIDTH)) buffer(CLK, RST, read_flags[i], read_datas[(i+1)*WIDTH-1:i*WIDTH], write_current, write_data, empty[i], full[i]); 
		end
	endgenerate
	
endmodule
module miso_fifo
	#(
	parameter CHANNEL_BIT = 1,
	parameter SIZE_BIT = 3,
	parameter WIDTH = 8
	)
	(
	input CLK,
	input RST,
	
	input read_flag,
	input [CHANNEL_BIT-1:0] read_select,
	output [WIDTH-1:0] read_data,
	
	input [(1<<CHANNEL_BIT)-1:0] write_flags,
	input [(1<<CHANNEL_BIT)*WIDTH-1:0] write_datas,
	
	output [(1<<CHANNEL_BIT)-1:0] empty,
	output [(1<<CHANNEL_BIT)-1:0] full
	);
	
	localparam CHANNEL = 1 << CHANNEL_BIT;
	wire [WIDTH-1:0] read_datas[CHANNEL-1:0];
	
	genvar i;
	generate
		for(i=0; i < CHANNEL; i=i+1) begin
			wire read_current;
			assign read_current = read_select == i ? read_flag : 0;
			fifo #(.SIZE_BIT(SIZE_BIT), .WIDTH(WIDTH)) buffer(CLK, RST, read_current, read_datas[i], write_flags[i], write_datas[(i+1)*WIDTH-1:i*WIDTH], empty[i], full[i]);
		end
	endgenerate
	
	assign read_data = read_datas[read_select];
endmodule
module tb_unsigned_sqrt_multicycle();
    localparam RATE    = 1000.0/200.0;
    
    initial begin
        $dumpfile("tb_unsigned_sqrt_multicycle.vcd");
        $dumpvars(0, tb_unsigned_sqrt_multicycle);
        
        #100000;
            $finish;
    end
    
    reg     clk = 1'b1;
    always #(RATE/2.0)  clk = ~clk;
    
    reg     reset = 1'b1;
    initial #(RATE*100.5)   reset = 1'b0;
    
    parameter   DATA_WIDTH = 32;
    
    wire                        cke = 1'b1;
    
    reg     [2*DATA_WIDTH-1:0]  s_data  = 0;
    reg                         s_valid = 1;
    wire                        s_ready;
    
    wire    [DATA_WIDTH-1:0]    m_data;
    wire                        m_valid;
    wire                        m_ready = 1'b1;
    
    integer                     n = 0;
    always @(posedge clk) begin
        if ( s_valid & s_ready ) begin
            s_data <= n * n;
            n <= n+1;
        end
        
        if ( m_valid & m_ready ) begin
            $display("%d", m_data);
        end
    end
    
    // }`TCN½ûª
    jelly_unsigned_sqrt_multicycle
            #(
                .DATA_WIDTH     (DATA_WIDTH)
            )
        i_unsigned_sqrt_multicycle
            (
                .reset          (reset),
                .clk            (clk),
                .cke            (cke),
                                 
                .s_data         (s_data),
                .s_valid        (s_valid),
                .s_ready        (s_ready),
                                 
                .m_data         (m_data),
                .m_valid        (m_valid),
                .m_ready        (m_ready)
            );
    
    
endmodule
module tb_counter_async();
    localparam S_RATE = 1000.0/20.0;
    localparam M_RATE = 1000.0/210.7;
    
    initial begin
        $dumpfile("tb_counter_async.vcd");
        $dumpvars(0, tb_counter_async);
        
        #100000;
            $finish;
    end
    
    reg     s_clk = 1'b1;
    always #(S_RATE/2.0)    s_clk = ~s_clk;
    
    reg     m_clk = 1'b1;
    always #(M_RATE/2.0)    m_clk = ~m_clk;
    
    reg     reset = 1'b1;
    initial #(S_RATE*100)   reset = 1'b0;
    
    
    localparam  COUNTER_WIDTH = 16;
    
    reg     [COUNTER_WIDTH-1:0] s_add   = 1;
    reg                         s_valid = 0;
    
    wire    [COUNTER_WIDTH-1:0] m_counter;
    wire                        m_valid;
    
    initial begin
        #(S_RATE*200)   s_valid = 1'b1;
        #(S_RATE*300)   s_valid = 1'b0;
    end
    
    integer s_c = 0;
    always @(posedge s_clk) begin
        if ( s_valid  ) begin
            s_c <= s_c + s_add;
        end
    end
    
    integer m_c = 0;
    always @(posedge m_clk) begin
        if ( !reset ) begin
            if ( m_valid ) begin
                m_c <= m_c + m_counter;
            end
        end
    end
    
    jelly_counter_async
            #(
                .ASYNC          (1),
                .COUNTER_WIDTH  (COUNTER_WIDTH)
            )
        i_count_async
            (
                .s_reset        (reset),
                .s_clk          (s_clk),
                .s_add          (s_add),
                .s_valid        (s_valid),
                
                .m_reset        (reset),
                .m_clk          (m_clk),
                .m_counter      (m_counter),
                .m_valid        (m_valid)
            );
    
    
endmodule
module tb_data_async();
    localparam S_RATE    = 1000.0/200.0;
    localparam M_RATE    = 1000.0/21.7;
    
    initial begin
        $dumpfile("tb_data_async.vcd");
        $dumpvars(0, tb_data_async);
        
        #100000;
            $finish;
    end
    
    reg     s_clk = 1'b1;
    always #(S_RATE/2.0)    s_clk = ~s_clk;
    
    reg     m_clk = 1'b1;
    always #(M_RATE/2.0)    m_clk = ~m_clk;
    
    reg     reset = 1'b1;
    initial #(S_RATE*100)   reset = 1'b0;
    
    
    localparam  DATA_WIDTH = 16;
    
    wire    [DATA_WIDTH-1:0]    s_data;
    wire                        s_valid;
    wire                        s_ready;
    
    wire    [DATA_WIDTH-1:0]    m_data;
    wire                        m_valid;
    wire                        m_ready;
    
    jelly_data_async
            #(
                .DATA_WIDTH     (DATA_WIDTH)
            )
        i_data_async
            (
                .s_reset        (reset),
                .s_clk          (s_clk),
                .s_data         (s_data),
                .s_valid        (s_valid),
                .s_ready        (s_ready),
                
                .m_reset        (reset),
                .m_clk          (m_clk),
                .m_data         (m_data),
                .m_valid        (m_valid),
                .m_ready        (m_ready)
            );
    
    
    // write
    reg     [DATA_WIDTH-1:0]    reg_data;
    reg                         reg_valid;
    always @(posedge s_clk) begin
        if ( reset ) begin
            reg_data  <= 0;
            reg_valid <= 1'b0;
        end
        else begin
            if ( !(s_valid && !s_ready) ) begin
                reg_valid <= {$random};
            end
            
            if ( s_valid && s_ready ) begin
                reg_data <= reg_data + 1'b1;
            end
        end
    end
    assign s_data  = reg_data;
    assign s_valid = reg_valid;
    
    
    // read
    reg     [DATA_WIDTH-1:0]    reg_expectation_value;
    reg                         reg_ready;
    always @(posedge m_clk) begin
        if ( reset ) begin
            reg_expectation_value  <= 0;
            reg_ready              <= 1'b0;
        end
        else begin
            reg_ready <= {$random};
            
            if ( m_valid && m_ready ) begin
                if ( m_data != reg_expectation_value ) begin
                    $display("error!");
                end
                
                reg_expectation_value <= reg_expectation_value + 1'b1;
            end
        end
    end
    assign m_ready = reg_ready;
    
    
    
    
    
    reg     [7:0]       reg_puls_count = 0;
    always @(posedge s_clk) begin
        reg_puls_count <= reg_puls_count + 1;
    end
    
    wire                pulse_async;
    
    jelly_pulse_async
        i_pulse_async
            (
                .s_reset    (reset),
                .s_clk      (s_clk),
                .s_pulse    (1), // reg_puls_count == 0),
                
                .m_reset    (reset),
                .m_clk      (m_clk),
                .m_pulse    (pulse_async)
            );
    
    
    
    
    
endmodule
module tb_fifo_async_fwft();
    localparam S_RATE    = 1000.0/200.0;
    localparam M_RATE    = 1000.0/201.7;
    
    initial begin
        $dumpfile("tb_fifo_async_fwft.vcd");
        $dumpvars(0, tb_fifo_async_fwft);
        
        #100000;
            $finish;
    end
    
    reg     s_clk = 1'b1;
    always #(S_RATE/2.0)    s_clk = ~s_clk;
    
    reg     m_clk = 1'b1;
    always #(M_RATE/2.0)    m_clk = ~m_clk;
    
    reg     reset = 1'b1;
    initial #(S_RATE*100)   reset = 1'b0;
    
    
    localparam  DATA_WIDTH = 16;
    localparam  PTR_WIDTH  = 2;
    
    wire    [DATA_WIDTH-1:0]    s_data;
    wire                        s_valid;
    wire                        s_ready;
    wire    [PTR_WIDTH:0]       s_free_count;
    
    wire    [DATA_WIDTH-1:0]    m_data;
    wire                        m_valid;
    wire                        m_ready;
    wire    [PTR_WIDTH:0]       m_data_count;
    
    jelly_fifo_async_fwtf
            #(
                .DATA_WIDTH     (DATA_WIDTH),
                .PTR_WIDTH      (PTR_WIDTH),
                .DOUT_REGS      (1)
            )
        i_fifo_async_fwtf
            (
                .s_reset        (reset),
                .s_clk          (s_clk),
                .s_data         (s_data),
                .s_valid        (s_valid),
                .s_ready        (s_ready),
                .s_free_count   (s_free_count),
                
                .m_reset        (reset),
                .m_clk          (m_clk),
                .m_data         (m_data),
                .m_valid        (m_valid),
                .m_ready        (m_ready),
                .m_data_count   (m_data_count)
            );
    
    
    // write
    reg     [DATA_WIDTH-1:0]    reg_data;
    reg                         reg_valid;
    always @(posedge s_clk) begin
        if ( reset ) begin
            reg_data  <= 0;
            reg_valid <= 1'b0;
        end
        else begin
            if ( !(s_valid && !s_ready) ) begin
                reg_valid <= {$random};
            end
            
            if ( s_valid && s_ready ) begin
                reg_data <= reg_data + 1'b1;
            end
        end
    end
    assign s_data  = reg_data;
    assign s_valid = reg_valid;
    
    
    // read
    reg     [DATA_WIDTH-1:0]    reg_expectation_value;
    reg                         reg_ready;
    always @(posedge m_clk) begin
        if ( reset ) begin
            reg_expectation_value  <= 0;
            reg_ready              <= 1'b0;
        end
        else begin
            reg_ready <= {$random};
            
            if ( m_valid && m_ready ) begin
                if ( m_data != reg_expectation_value ) begin
                    $display("error!");
                end
                
                reg_expectation_value <= reg_expectation_value + 1'b1;
            end
        end
    end
    assign m_ready = reg_ready;
    
endmodule
module tb_data_multiplexer();
    localparam RATE    = 10.0;
    
    initial begin
        $dumpfile("tb_data_multiplexer.vcd");
        $dumpvars(0, tb_data_multiplexer);
    end
    
    reg     clk = 1'b1;
    always #(RATE/2.0)  clk = ~clk;
    
    reg     reset = 1'b1;
    always #(RATE*100)  reset = 1'b0;
    
    parameter   NUM        = 5;
    parameter   DATA_WIDTH = 8;
    
    reg     [DATA_WIDTH-1:0]            src_data;
    reg                                 src_valid;
    wire                                src_ready;
    
    wire    [NUM*DATA_WIDTH-1:0]        port_data;
    wire                                port_valid;
    wire                                port_ready;
    
    wire    [DATA_WIDTH-1:0]            sink_data;
    wire                                sink_valid;
    reg                                 sink_ready = 1;
    
    always @(posedge clk) begin
        sink_ready <= {$random};
    end
    
    jelly_data_demultiplexer
            #(
                .NUM            (NUM),
                .DATA_WIDTH     (DATA_WIDTH)
            )
        i_data_demultiplexer
            (
                .reset          (reset),
                .clk            (clk),
                .cke            (1),
                
                .endian         (0),
                
                .s_data         (src_data),
                .s_valid        (src_valid),
                .s_ready        (src_ready),
                
                .m_data         (port_data),
                .m_valid        (port_valid),
                .m_ready        (port_ready)
            );
    
    jelly_data_multiplexer
            #(
                .NUM            (NUM),
                .DATA_WIDTH     (DATA_WIDTH)
            )
        i_data_multiplexer
            (
                .reset          (reset),
                .clk            (clk),
                .cke            (1),
                
                .endian         (0),
                
                .s_data         (port_data),
                .s_valid        (port_valid),
                .s_ready        (port_ready),
                
                .m_data         (sink_data),
                .m_valid        (sink_valid),
                .m_ready        (sink_ready)
            );
    
    
    
    always @(posedge clk) begin
        if ( reset ) begin
            src_data  <= 0;
            src_valid <= 0;
        end
        else begin
            if ( src_valid && src_ready ) begin
                src_data <= src_data + 1;
            end
            
            if ( !src_valid || src_ready ) begin
                src_valid <= {$random};
            end
        end
    end
    
    
    reg     [DATA_WIDTH-1:0]    exp_data;
    always @(posedge clk) begin
        if ( reset ) begin
            exp_data <= 0;
        end
        else begin
            if ( sink_valid && sink_ready ) begin
                if ( sink_data != exp_data ) begin
                    $display("Error!");
                end
    //          $display("%h", sink_data);
                exp_data <= exp_data + 1;
            end
        end
    end
    
    
endmodule
module tb_bit_encoder();
    localparam RATE = 1000.0/100.0;
    
    initial begin
        $dumpfile("tb_bit_encoder.vcd");
        $dumpvars(1, tb_bit_encoder);
        
        #100000;
            $finish;
    end
    
    reg     clk = 1'b1;
    always #(RATE/2.0)  clk = ~clk;
    
    reg     reset = 1'b1;
    initial #(RATE*100) reset = 1'b0;
    
    
    parameter   DATA_WIDTH = 24;
    parameter   SEL_WIDTH  = DATA_WIDTH <     2 ?  1 :
                             DATA_WIDTH <     4 ?  2 :
                             DATA_WIDTH <     8 ?  3 :
                             DATA_WIDTH <    16 ?  4 :
                             DATA_WIDTH <    32 ?  5 :
                             DATA_WIDTH <    64 ?  6 :
                             DATA_WIDTH <   128 ?  7 :
                             DATA_WIDTH <   256 ?  8 :
                             DATA_WIDTH <   512 ?  9 :
                             DATA_WIDTH <  1024 ? 10 :
                             DATA_WIDTH <  2048 ? 11 :
                             DATA_WIDTH <  4096 ? 12 :
                             DATA_WIDTH <  8192 ? 13 :
                             DATA_WIDTH < 16384 ? 14 :
                             DATA_WIDTH < 32768 ? 15 : 16;
    
    
    reg     [DATA_WIDTH-1:0]    in_data = 1;
    wire    [SEL_WIDTH-1:0]     out_sel_onehot;
    wire    [SEL_WIDTH-1:0]     out_sel_msb;
    wire    [SEL_WIDTH-1:0]     out_sel_lsb;
    
    always @(posedge clk) begin
        in_data <= {in_data[DATA_WIDTH-2:0], in_data[DATA_WIDTH-1]};
    end
    
    jelly_bit_encoder
            #(
                .DATA_WIDTH     (DATA_WIDTH),
                .PRIORITYT      (0),
                .LSB_FIRST      (0)
            )
        i_bit_encoder_onehot
            (
                .in_data        (in_data),
                .out_sel        (out_sel_onehot)
            );
    
    jelly_bit_encoder
            #(
                .DATA_WIDTH     (DATA_WIDTH),
                .PRIORITYT      (1),
                .LSB_FIRST      (0)
            )
        i_bit_encoder_msb
            (
                .in_data        (in_data),
                .out_sel        (out_sel_msb)
            );
    
    jelly_bit_encoder
            #(
                .DATA_WIDTH     (DATA_WIDTH),
                .PRIORITYT      (1),
                .LSB_FIRST      (1)
            )
        i_bit_encoder_lsb
            (
                .in_data        (in_data),
                .out_sel        (out_sel_lsb)
            );
    
    
    
endmodule
module dummy_proc
        #(
            parameter   DATA_WIDTH = 16
        )
        (
            input   wire                        reset,
            input   wire                        clk,
            
            input   wire    [DATA_WIDTH-1:0]    s_data,
            input   wire                        s_valid,
            output  wire                        s_ready,
            
            output  wire    [DATA_WIDTH-1:0]    m_data,
            output  wire                        m_valid,
            input   wire                        m_ready
        );
    
    reg     [1:0]   reg_busy = 0;
    always @(posedge clk) begin
//      reg_busy <= {$random()};
        reg_busy <= reg_busy + 1;
    end
    wire            busy = (reg_busy != 0);
    
    assign m_data  = s_data;
    assign m_valid = s_valid && !busy;
    assign s_ready = m_ready && !busy;
    
endmodule
module tb_pipeline_insert_ff();
    localparam RATE    = 1000.0/200.0;
    
    initial begin
        $dumpfile("tb_pipeline_insert_ff.vcd");
        $dumpvars(0, tb_pipeline_insert_ff);
        
        #10000;
            $finish;
    end
    
    reg     clk = 1'b1;
    always #(RATE/2.0)  clk = ~clk;
    
    reg     reset = 1'b1;
    initial #(RATE*100) reset = 1'b0;
    
    localparam  DATA_WIDTH = 16;
    
    wire    [DATA_WIDTH-1:0]    s_data;
    wire                        s_valid;
    wire                        s_ready;
    
    wire    [DATA_WIDTH-1:0]    m_data;
    wire                        m_valid;
    wire                        m_ready;
    
    wire                        buffered;
    
    jelly_pipeline_insert_ff
            #(
                .DATA_WIDTH     (DATA_WIDTH),
                .SLAVE_REGS     (1),
                .MASTER_REGS    (1)
            )
        i_pipeline_insert_ff
            (
                .reset          (reset),
                .clk            (clk),
                .cke            (1'b1),
                
                .s_data         (s_data),
                .s_valid        (s_valid),
                .s_ready        (s_ready),
                
                .m_data         (m_data),
                .m_valid        (m_valid),
                .m_ready        (m_ready),
                
                .buffered       (buffered)
            );
    
    // write
    reg     [DATA_WIDTH-1:0]    reg_data;
    reg                         reg_valid;
    always @(posedge clk) begin
        if ( reset ) begin
            reg_data  <= 0;
            reg_valid <= 1'b0;
        end
        else begin
            if ( !(s_valid && !s_ready) ) begin
                reg_valid <= {$random};
            end
            
            if ( s_valid && s_ready ) begin
                reg_data <= reg_data + 1'b1;
            end
        end
    end
    assign s_data  = reg_data;
    assign s_valid = reg_valid;
    
    
    // read
    integer     fp;
    initial begin
        fp = $fopen("log.txt", "w");
    end
    
    reg     [DATA_WIDTH-1:0]    reg_expectation_value;
    reg                         reg_ready;
    always @(posedge clk) begin
        if ( reset ) begin
            reg_expectation_value  <= 0;
            reg_ready              <= 1'b0;
        end
        else begin
            reg_ready <= {$random};
            
            if ( m_valid && m_ready ) begin
                $fdisplay(fp, "%h %h", m_data, reg_expectation_value);
                if ( m_data != reg_expectation_value ) begin
                    $display("error!");
                end
                
                reg_expectation_value <= reg_expectation_value + 1'b1;
            end
        end
    end
    assign m_ready = reg_ready;
    
endmodule
module tang_nano_9k_blinking_led
        (
            input   clk,
            output  led
        );

    reg     [23:0]  counter;
    always @(posedge clk) begin
        counter <= counter + 1;
    end
    
    assign led = counter[23];

endmodule
module OSER10
    (
        output  wire    Q    ,
        input   wire    D0   ,
        input   wire    D1   ,
        input   wire    D2   ,
        input   wire    D3   ,
        input   wire    D4   ,
        input   wire    D5   ,
        input   wire    D6   ,
        input   wire    D7   ,
        input   wire    D8   ,
        input   wire    D9   ,
        input   wire    PCLK ,
        input   wire    FCLK ,
        input   wire    RESET
    );

endmodule
module ELVDS_OBUF(
            input   wire    I,
            output  wire    O,
            output  wire    OB
        );

    assign O  = I;
    assign OB = ~I;

endmodule
module video_filter_0
        (
            input   wire            ap_clk,
            input   wire            ap_rst_n,
            input   wire            ap_start,
            output  wire            ap_done,
            output  wire            ap_idle,
            output  wire            ap_ready,

            input   wire            s_axi4s_TVALID,
            output  wire            s_axi4s_TREADY,
            input   wire [23 : 0]   s_axi4s_TDATA,
            input   wire [0 : 0]    s_axi4s_TDEST,
            input   wire [2 : 0]    s_axi4s_TKEEP,
            input   wire [2 : 0]    s_axi4s_TSTRB,
            input   wire [0 : 0]    s_axi4s_TUSER,
            input   wire [0 : 0]    s_axi4s_TLAST,
            input   wire [0 : 0]    s_axi4s_TID,

            output  wire            m_axi4s_TVALID,
            input   wire            m_axi4s_TREADY,
            output  wire [23 : 0]   m_axi4s_TDATA,
            output  wire [0 : 0]    m_axi4s_TDEST,
            output  wire [2 : 0]    m_axi4s_TKEEP,
            output  wire [2 : 0]    m_axi4s_TSTRB,
            output  wire [0 : 0]    m_axi4s_TUSER,
            output  wire [0 : 0]    m_axi4s_TLAST,
            output  wire [0 : 0]    m_axi4s_TID,

            input   wire [15 : 0]   width,
            input   wire [15 : 0]   height,
            input   wire            inverse
        );


    assign m_axi4s_TVALID = s_axi4s_TVALID;
    assign m_axi4s_TDATA  = s_axi4s_TDATA;
    assign m_axi4s_TUSER  = s_axi4s_TUSER;
    assign m_axi4s_TLAST  = s_axi4s_TLAST;
    assign s_axi4s_TREADY = m_axi4s_TREADY;
    
endmodule
module IOBUF
        (
            input   wire    I,
            output  wire    O,
            input   wire    T,
            inout   wire    IO
        );

    assign IO = T ? 1'bz : I;
    assign O  = IO;

endmodule
module design_1
   (m_axi4l_aclk,
    m_axi4l_araddr,
    m_axi4l_aresetn,
    m_axi4l_arprot,
    m_axi4l_arready,
    m_axi4l_arvalid,
    m_axi4l_awaddr,
    m_axi4l_awprot,
    m_axi4l_awready,
    m_axi4l_awvalid,
    m_axi4l_bready,
    m_axi4l_bresp,
    m_axi4l_bvalid,
    m_axi4l_rdata,
    m_axi4l_rready,
    m_axi4l_rresp,
    m_axi4l_rvalid,
    m_axi4l_wdata,
    m_axi4l_wready,
    m_axi4l_wstrb,
    m_axi4l_wvalid,
    fan_en);
  output m_axi4l_aclk;
  output [39:0]m_axi4l_araddr;
  output [0:0]m_axi4l_aresetn;
  output [2:0]m_axi4l_arprot;
  input m_axi4l_arready;
  output m_axi4l_arvalid;
  output [39:0]m_axi4l_awaddr;
  output [2:0]m_axi4l_awprot;
  input m_axi4l_awready;
  output m_axi4l_awvalid;
  output m_axi4l_bready;
  input [1:0]m_axi4l_bresp;
  input m_axi4l_bvalid;
  input [31:0]m_axi4l_rdata;
  output m_axi4l_rready;
  input [1:0]m_axi4l_rresp;
  input m_axi4l_rvalid;
  output [31:0]m_axi4l_wdata;
  input m_axi4l_wready;
  output [3:0]m_axi4l_wstrb;
  output m_axi4l_wvalid;
  output fan_en;

  wire m_axi4l_aclk;
  wire [39:0]m_axi4l_araddr;
  wire [0:0]m_axi4l_aresetn;
  wire [2:0]m_axi4l_arprot;
  wire m_axi4l_arready;
  wire m_axi4l_arvalid;
  wire [39:0]m_axi4l_awaddr;
  wire [2:0]m_axi4l_awprot;
  wire m_axi4l_awready;
  wire m_axi4l_awvalid;
  wire m_axi4l_bready;
  wire [1:0]m_axi4l_bresp;
  wire m_axi4l_bvalid;
  wire [31:0]m_axi4l_rdata;
  wire m_axi4l_rready;
  wire [1:0]m_axi4l_rresp;
  wire m_axi4l_rvalid;
  wire [31:0]m_axi4l_wdata;
  wire m_axi4l_wready;
  wire [3:0]m_axi4l_wstrb;
  wire m_axi4l_wvalid;
  wire fan_en;

  assign fan_en = 1'b0;

endmodule
module bb_lut
        #(
            parameter                   DEVICE = "RTL",
            parameter                   N      = 6,
            parameter   [(1<<N)-1:0]    INIT   = {(1<<N){1'b0}}
        )
        (
            input	wire	[N-1:0]		in_data,
            output	wire				out_data
        );
    
    generate
    if (  N == 6 && (
            DEVICE == "SPARTAN6" ||
            DEVICE == "VIRTEX6" ||
            DEVICE == "7SERIES"  ||
            DEVICE == "ULTRASCALE" ||
            DEVICE == "ULTRASCALE_PLUS" ||
            DEVICE == "ULTRASCALE_PLUS_ES1" ||
            DEVICE == "ULTRASCALE_PLUS_ES2") ) begin
        LUT6
                #(
                    .INIT	(INIT)
                )
            i_lut6
                (
                    .O		(out_data),
                    .I0		(in_data[0]),
                    .I1		(in_data[1]),
                    .I2		(in_data[2]),
                    .I3		(in_data[3]),
                    .I4		(in_data[4]),
                    .I5		(in_data[5])
                );
    end
    else begin : rtl
        wire	[(1<<N)-1:0]	lut_table = INIT;
        assign out_data = lut_table[in_data];
    end
    endgenerate
    
endmodule
module clkgen
		(
			input		in_reset,
			input		in_clk,
			
			output		out_clk,
			output		out_clk_x2,
			output		out_clk_uart,
			output		out_reset,

			output		locked
		);

	
	// clk_in
	wire		in_clk_ibufg;
	IBUFG
		i_ibufg_clkin
			(
				.I		(in_clk), 
				.O		(in_clk_ibufg)
			);
	
	// clk0
	wire		clk0;
	wire		clk0_bufg;
	BUFG
		i_bufg_clk0
			(
				.I		(clk0), 
				.O		(clk0_bufg)
			);
	
	// clkdv
	wire		clkdv;
	wire		clkdv_bufg;
	BUFG
		i_bufg_clkdv
			(
				.I		(clkdv), 
				.O		(clkdv_bufg)
			);

	// clk2x
	wire		clk2x;
	wire		clk2x_bufg;
	BUFG
		i_bufg_clk2x
			(
				.I		(clk2x), 
				.O		(clk2x_bufg)
			);
	
	// DCM
	DCM
			#(
				.CLK_FEEDBACK			("1X"),
				.CLKDV_DIVIDE			(2.0),
				.CLKFX_DIVIDE			(1),
				.CLKFX_MULTIPLY			(4),
				.CLKIN_DIVIDE_BY_2		("FALSE"),
				.CLKIN_PERIOD			(20.000),
				.CLKOUT_PHASE_SHIFT		("NONE"),
				.DESKEW_ADJUST			("SYSTEM_SYNCHRONOUS"),
				.DFS_FREQUENCY_MODE		("LOW"),
				.DLL_FREQUENCY_MODE		("LOW"),
				.DUTY_CYCLE_CORRECTION	("TRUE"),
				.FACTORY_JF				(16'h8080),
				.PHASE_SHIFT			( 0),
				.STARTUP_WAIT			("FALSE")
			)
		i_dcm
			(
				.CLKFB					(clk0_bufg), 
				.CLKIN					(in_clk_ibufg), 
				.DSSEN					(1'b0),
				.PSCLK					(1'b0), 
				.PSEN					(1'b0), 
				.PSINCDEC				(1'b0), 
				.RST					(in_reset),
				.CLKDV					(clkdv),
				.CLKFX					(), 
				.CLKFX180				(), 
				.CLK0					(clk0), 
				.CLK2X					(clk2x), 
				.CLK2X180				(), 
				.CLK90					(), 
				.CLK180					(), 
				.CLK270					(), 
				.LOCKED					(locked), 
				.PSDONE					(), 
				.STATUS					()
			);
	
	
	// -------------------------
	//  reset
	// -------------------------
	
	reg		[1:0]	reg_reset;
	always @( posedge clkdv_bufg or posedge in_reset ) begin
		if ( in_reset ) begin
			reg_reset <= 2'b11;
		end
		else begin
			if ( !locked ) begin
				reg_reset <= 2'b11;
			end
			else begin
				reg_reset <= {1'b0, reg_reset[1]};
			end
		end
	end
	
	
		
	// -------------------------
	//  uart clock divider
	// -------------------------
	
	reg							uart_clk_dv;
	reg		[7:0]				dv_counter;
	always @ ( posedge clk2x_bufg or posedge in_reset ) begin
		if ( in_reset ) begin
			dv_counter  <= 0;
			uart_clk_dv <= 1'b0;
		end
		else begin
			if ( dv_counter == (54 - 1) ) begin		// 115200 bps
				dv_counter  <= 0;
				uart_clk_dv <= ~uart_clk_dv;
			end
			else begin
				dv_counter  <= dv_counter + 1;
			end
		end
	end

	assign out_clk      = clkdv_bufg;
	assign out_clk_x2   = clk0_bufg;
	assign out_clk_uart = uart_clk_dv;
	assign out_reset    = reg_reset[0];
	
endmodule
module clkgen
		(
			input	wire	in_reset, 
			input	wire	in_clk, 
			
			output	wire	out_clk,
			output	wire	out_clk_x2,
			output	wire	out_clk_uart,
			output	wire	out_reset,
			
			output	wire	locked
		);

	
	// -------------------------
	//  Input Clock
	// -------------------------
	
	// clk_in
	wire		in_clk_ibufg;
	IBUFG
		i_ibufg_clkin
			(
				.I		(in_clk), 
				.O		(in_clk_ibufg)
			);
	
	
	
	// -------------------------
	//  System Clock
	// -------------------------
	
	// clk0
	wire		clk0;
	wire		clk0_bufg;
	BUFG
		i_bufg_clk0
			(
				.I		(clk0), 
				.O		(clk0_bufg)
			);
	
	// clkdv
	wire		clkdv;
	wire		clkdv_bufg;
	BUFG
		i_bufg_clkdv
			(
				.I		(clkdv), 
				.O		(clkdv_bufg)
			);

	// clk2x
	wire		clk2x;
	wire		clk2x_bufg;
	BUFG
		i_bufg_clk2x
			(
				.I		(clk2x), 
				.O		(clk2x_bufg)
			);
	
	// DCM
	wire		dcm_locked;
	DCM
			#(
				.CLK_FEEDBACK			("1X"),
				.CLKDV_DIVIDE			(2.0),
				.CLKFX_DIVIDE			(1),
				.CLKFX_MULTIPLY			(4),
				.CLKIN_DIVIDE_BY_2		("FALSE"),
				.CLKIN_PERIOD			(20.000),
				.CLKOUT_PHASE_SHIFT		("NONE"),
				.DESKEW_ADJUST			("SYSTEM_SYNCHRONOUS"),
				.DFS_FREQUENCY_MODE		("LOW"),
				.DLL_FREQUENCY_MODE		("LOW"),
				.DUTY_CYCLE_CORRECTION	("TRUE"),
				.FACTORY_JF				(16'h8080),
				.PHASE_SHIFT			(0),
				.STARTUP_WAIT			("FALSE")
			)
		i_dcm
			(
				.CLKFB					(clk0_bufg), 
				.CLKIN					(in_clk_ibufg), 
				.DSSEN					(1'b0),
				.PSCLK					(1'b0), 
				.PSEN					(1'b0), 
				.PSINCDEC				(1'b0), 
				.RST					(in_reset),
				.CLKDV					(clkdv),
				.CLKFX					(), 
				.CLKFX180				(), 
				.CLK0					(clk0), 
				.CLK2X					(clk2x), 
				.CLK2X180				(), 
				.CLK90					(), 
				.CLK180					(), 
				.CLK270					(), 
				.LOCKED					(dcm_locked), 
				.PSDONE					(), 
				.STATUS					()
			);

	// -------------------------
	//  reset
	// -------------------------
	
	reg		[1:0]		reg_reset;
	always @ ( posedge clk0_bufg or posedge in_reset ) begin
		if ( in_reset ) begin
			reg_reset <= 2'b11;
		end
		else begin
			if ( !dcm_locked ) begin
				reg_reset <= 2'b11;
			end
			else begin
				reg_reset <= {1'b0, reg_reset[1]};
			end
		end
	end
	
	
	// -------------------------
	//  uart clock divider
	// -------------------------
	
	reg							uart_clk_dv;
	reg		[7:0]				dv_counter;
	always @ ( posedge clk2x_bufg or posedge in_reset ) begin
		if ( in_reset ) begin
			dv_counter  <= 0;
			uart_clk_dv <= 1'b0;
		end
		else begin
			if ( dv_counter == (54 - 1) ) begin		// 115200 bps
				dv_counter  <= 0;
				uart_clk_dv <= ~uart_clk_dv;
			end
			else begin
				dv_counter  <= dv_counter + 1;
			end
		end
	end
	
	
	
	assign out_clk      = clk0_bufg;
	assign out_clk_x2   = clk2x_bufg;
	assign out_clk_uart = uart_clk_dv;
	assign out_reset    = reg_reset[0];
	
	assign locked       = dcm_locked;

	
endmodule
module tb_top;
	parameter	SIMULATION = 1'b1;

	parameter	RATE       = 20;
	parameter	UART_RATE  = (1000000000 / 115200);
	
	
	initial begin
		$dumpfile("tb_top.vcd");
		$dumpvars(0, tb_top);
	end
	
	// reset
	reg		reset;
	initial begin
		#0			reset = 1'b1;
		#(RATE*10)	reset = 1'b0;
	end
	
	// clock
	reg		clk;
	initial begin
		clk    = 1'b1;
	end
	always #(RATE/2) begin
		clk = ~clk;
	end
	
	top
			#(
				.SIMULATION			(SIMULATION)
			)
		i_top
			(
				.in_clk				(clk),
				.in_reset_n			(!reset),
				
				.uart0_tx			(),
				.uart0_rx			(1'b1),
				
				.uart1_tx			(),
				.uart1_rx			(1'b1),
				
				.led				()
			);
	
	
	initial begin
				$display("--- START ---");
	#(RATE*100000);
				$finish;
	end	
	
endmodule
module bb_lut
        #(
            parameter                   DEVICE = "RTL",
            parameter                   N      = 6,
            parameter   [(1<<N)-1:0]    INIT   = {(1<<N){1'b0}}
        )
        (
            input   wire    [N-1:0]     in_data,
            output  wire                out_data
        );
    
    generate
    if ( N == 6
            && (DEVICE == "SPARTAN6"
             || DEVICE == "VIRTEX6"
             || DEVICE == "7SERIES"
             || DEVICE == "ULTRASCALE"
             || DEVICE == "ULTRASCALE_PLUS"
             || DEVICE == "ULTRASCALE_PLUS_ES1"
             || DEVICE == "ULTRASCALE_PLUS_ES2") ) begin : xilinx_lut6
        LUT6
                #(
                    .INIT   (INIT)
                )
            i_lut6
                (
                    .O      (out_data),
                    .I0     (in_data[0]),
                    .I1     (in_data[1]),
                    .I2     (in_data[2]),
                    .I3     (in_data[3]),
                    .I4     (in_data[4]),
                    .I5     (in_data[5])
                );
    end
    else begin : rtl
        wire    [(1<<N)-1:0]    lut_table = INIT;
        assign out_data = lut_table[in_data];
    end
    endgenerate
    
    
endmodule
module IOBUF
        (
            inout   wire    IO, 
            input   wire    I,
            output  wire    O,
            input   wire    T
        );

    assign O = T ? 1'bz : I;

endmodule