dakies/OSS_Verilog huggingface dataset:
module sm3_cmprss_ceil_comb(
    input                   cmprss_round_sm_16_i,
    input [31:0]            tj_i,

    input [31:0]            reg_a_i,
    input [31:0]            reg_b_i,
    input [31:0]            reg_c_i,
    input [31:0]            reg_d_i,
    input [31:0]            reg_e_i,
    input [31:0]            reg_f_i,
    input [31:0]            reg_g_i,
    input [31:0]            reg_h_i,

    input [31:0]            wj_i,
    input [31:0]            wjj_i,

    output [31:0]           reg_a_o,
    output [31:0]           reg_b_o,
    output [31:0]           reg_c_o,
    output [31:0]           reg_d_o,
    output [31:0]           reg_e_o,
    output [31:0]           reg_f_o,
    output [31:0]           reg_g_o,
    output [31:0]           reg_h_o
    );


//wire
wire [31:0]	tmp_for_ss1_0	;
wire [31:0]	tmp_for_ss1_2	;
wire [31:0]	ss1				;
wire [31:0]	ss2				;
wire [31:0]	tmp_for_tt1_0	;
wire [31:0]	tmp_for_tt1_1	;
wire [31:0]	tt1				;
wire [31:0]	tmp_for_tt2_0	;
wire [31:0]	tmp_for_tt2_1	;
wire [31:0]	tt2				;
wire [31:0]	tt2_after_p0	;

wire [31:0]	TJ				=	tj_i;

//加法器0
assign  tmp_for_ss1_0	=	{reg_a_i[31-12:0], reg_a_i[31:31-12+1]} + reg_e_i;
assign  tmp_for_ss1_2	=	tmp_for_ss1_0 + TJ;

assign      ss1				=	{tmp_for_ss1_2[31 - 7 : 0], tmp_for_ss1_2[31 : 31 - 7 + 1]};
assign  	ss2				=	ss1 ^ {reg_a_i[31 - 12 : 0], reg_a_i[31 : 31 - 12 + 1]};

//加法器1
assign  	tmp_for_tt1_0	=	cmprss_round_sm_16_i? reg_a_i ^ reg_b_i ^ reg_c_i : (reg_a_i & reg_b_i | reg_a_i & reg_c_i | reg_b_i & reg_c_i);
assign  	tmp_for_tt1_1	=	reg_d_i + ss2 + wjj_i;
assign  	tt1				=	tmp_for_tt1_0 + tmp_for_tt1_1;


//加法器2
assign  	tmp_for_tt2_0	=	cmprss_round_sm_16_i? reg_e_i ^ reg_f_i ^ reg_g_i : (reg_e_i & reg_f_i | ~reg_e_i & reg_g_i);
assign  	tmp_for_tt2_1	=	reg_h_i + ss1 + wj_i;
assign  	tt2				=	tmp_for_tt2_0 + tmp_for_tt2_1;

assign  	tt2_after_p0	=	tt2 ^ {tt2[31-9:0], tt2[31:31-9+1]} ^ {tt2[31-17:0], tt2[31:31-17+1]};

assign  reg_a_o             =   tt1;
assign  reg_b_o             =   reg_a_i;
assign  reg_c_o             =   {reg_b_i[31 - 9 : 0], reg_b_i[31 : 31 - 9 + 1]};
assign  reg_d_o             =   reg_c_i;
assign  reg_e_o             =   tt2_after_p0;
assign  reg_f_o             =   reg_e_i;
assign  reg_g_o             =   {reg_f_i[31 - 19 : 0], reg_f_i[31 : 31 - 19 + 1]};
assign  reg_h_o             =   reg_g_i;

endmodule
module gpio (
    input wire clk,
    input wire rst_n,

    input wire[7:0] waddr_i,
    input wire[`MemBus] data_i,
    input wire[3:0] sel_i,
    input wire we_i,
    input wire[7:0] raddr_i,
    input wire rd_i,
    output reg[`MemBus] data_o,

	output reg [31:0]gpio_oe,//输出使能
	output reg [31:0]gpio_out,//输出数据
    input wire [31:0]gpio_in//输入数据
);

// 寄存器(偏移)地址
localparam GPIO_DIN = 8'h0;//输入数据
localparam GPIO_OPT = 8'h4;//输出数据
localparam GPIO_OEC = 8'h8;//输出使能
localparam GPIO_ODC = 8'hc;//开漏模式

// 输入数据，只读
// [31:0]对应GPIO0-31的当前的高低电平
reg [31:0] gpio_din;

// 输出数据，读写
// [31:0]对应GPIO0-31的输出值
reg [31:0] gpio_opt;

/* 端口模式，读写
 * GPIO_OEC与GPIO_ODC共同决定GPIOx端口模式
 * | GPIO_OEC  | GPIO_ODC  | GPIOx  
 * |-----------|-----------|---------------
 * |     0     |     0     | 高阻输入
 * |     0     |     1     | 高阻输入且锁存
 * |     1     |     0     | 推挽输出
 * |     1     |     1     | 开漏输出
 * |-----------|-----------|---------------*/
reg [31:0] gpio_oec;
reg [31:0] gpio_odc;


// 总线接口 写
always @ (posedge clk) begin
        if (we_i == 1'b1) begin
            case (waddr_i)
                GPIO_DIN: ;
                GPIO_OPT: gpio_opt <= data_i;
                GPIO_OEC: gpio_oec <= data_i;
                GPIO_ODC: gpio_odc <= data_i;
                default: ;
            endcase
        end 
        else begin
        end
//    end
end

// 总线接口 读
always @ (posedge clk) begin
    if (rd_i == 1'b1) begin
        case (raddr_i)
                GPIO_DIN: data_o <= gpio_din;
                GPIO_OPT: data_o <= gpio_opt;
                GPIO_OEC: data_o <= gpio_oec;
                GPIO_ODC: data_o <= gpio_odc;
            default: begin
                data_o <= 32'h0;
            end
        endcase
    end
    else begin
        data_o <= data_o;
    end
end

//输入打拍
reg [31:0] gpio_in_r;
always @(posedge clk) begin
	gpio_in_r <= gpio_in;
    gpio_din <= gpio_in_r;
end

//输出模式、使能
genvar i;
generate
for (i=0; i<32; i=i+1) begin
    always @(*) begin
        case ({gpio_oec[i], gpio_odc[i]})
            2'b00: begin
                gpio_oe [i] = 1'b0;
                gpio_out[i] = 1'bx;
            end
            2'b01: begin
                gpio_oe [i] = 1'b0;
                gpio_out[i] = 1'bx;
            end
            2'b10: begin
                gpio_oe [i] = 1'b1;
                gpio_out[i] = gpio_opt[i];
            end
            2'b11: begin
                gpio_oe [i] = ~gpio_opt[i];
                gpio_out[i] = 1'b0;
            end
        endcase
    end
end
endgenerate


endmodule
module top_microblaze
    #(
      parameter BIT_LEN       = `BIT_LEN,
      parameter CONV_LEN      = `CONV_LEN,
      parameter CONV_LPOS     = `CONV_LPOS,
      parameter M_LEN         = `M_LEN,
      parameter NB_ADDRESS    = `NB_ADDRESS,
      parameter RAM_WIDTH     = `RAM_WIDTH,
      parameter GPIO_D        = `GPIO_D,
      parameter N = 4,
      parameter BITS_IMAGEN = 8,
      parameter BITS_DATA = 13
      )(
        output [3:0] o_led,
        output       uart_rxd_out,
        //input [3:0]  i_sw,
        input [3:0]  btn,
        input        CLK100MHZ,
        input        uart_txd_in ,
        input        ck_rst
    );


    wire [GPIO_D-1:0] gpio_i_data_tri_i;
    wire [GPIO_D-1:0] gpio_o_data_tri_o;
    
    //reste del micro 
    wire reset;
    //clock de entrada al micro
    wire sys_clock;
    //clock de salida del micro
    wire clk_o;
    wire eop,sop,iload;
    
    // Microconotrolador
    assign reset        = ck_rst;//i_sw[0];
    assign sys_clock    = CLK100MHZ;
    
    // instacia del Microcontrolador
    design_1
        u_desing_1
            (
             .clock100(clk_o),
             .gpio_rtl_tri_i(gpio_i_data_tri_i),
             .gpio_rtl_tri_o(gpio_o_data_tri_o),
             .o_lock_clock(o_led[3]),
             .reset(reset),
             .sys_clock(sys_clock),
             .usb_uart_rxd(uart_txd_in),
             .usb_uart_txd(uart_rxd_out)
             );
    micro_sim#(
        .N(N))
        u_ALL
            (
             .gpio_i_data_tri_i(gpio_i_data_tri_i),
             .o_led(o_led[2:0]),
             .CLK100MHZ(clk_o),
             .gpio_o_data_tri_o(gpio_o_data_tri_o)
             
             );
endmodule
module tb_FSM();	

	parameter NB_ADDRESS= 10;
	//Para ver mas rapido si llega a completarse
    parameter NB_IMAGE  = 10;
	//Todo puerto de salida del modulo es un cable.
	//Todo puerto de estímulo o generación de entrada es un registro.
	//Definición de puertos
    reg                    	CLK;
    reg                    	reset;
    reg                    	SOP;
    reg [NB_IMAGE-1:0]     	imgLength;
    reg                    	valid;
    reg 					load; 
    wire [NB_ADDRESS-1:0]  	writeAddress;
    wire [NB_ADDRESS-1:0]  	readAddress;
    wire                   	EOP;
    wire                   	chblock;
    wire 					vld;
    integer i;
	initial	begin
		CLK       = 1'b0;
		SOP       = 1'b0;	
		imgLength = 10'hf;
		valid     = 1'b0;
		load 	  = 1'b0;
		reset     = 1'b1;		
		#10 reset = 1'b0;
		// etapa de carga 
		#5 load = 1'b1; 
		
		for(i=0; i<= imgLength; i=i+1)begin
			#5 valid = 1'b1;
			#5 valid = 1'b0;
		end
		load = 1'b0;	

		//Carga/lectura --> testeo del valid.
		//Emulo arranque de sistema, deberían cargarse los parametros correspondientes
		
		#30 SOP = 1'b1;
		#20 SOP = 1'b0;

		#200 $finish;
	end
	always #2.5 CLK=~CLK;
	//Módulo para pasarle los estímulos del banco de pruebas.
	Fsmv#(  
		.NB_ADDRESS(NB_ADDRESS),
		.NB_IMAGE (NB_IMAGE),
		.N_CONV (4))
		u_Fsmv(
			.o_readAdd(readAddress),
			.o_writeAdd(writeAddress),
			.o_EoP(EOP),
			.o_changeBlock(chblock),
			.o_fms2conVld(vld),
			.i_CLK(CLK),
			.i_reset(reset),
			.i_SoP(SOP),
			.i_imgLength(imgLength),
			.i_valid(valid),
			.i_load(load));


endmodule
module tb_memory();	
	
	parameter RAM_WIDTH = `RAM_WIDTH;    // Specify RAM data width    
    parameter NB_ADDRESS= `NB_ADDRESS;    
	
	//Todo puerto de salida del modulo es un cable.
	//Todo puerto de estímulo o generación de entrada es un registro.
	
	wire[RAM_WIDTH-1:0] output_data;
	
	reg[NB_ADDRESS-1:0] write_address;
	reg[NB_ADDRESS-1:0] read_address;
	reg	input_CLK;
	reg writeEnable;
	reg [RAM_WIDTH-1:0] input_data;
	
	
	
	
	initial	begin
		write_address =10'd0;
		read_address  =10'd0;
		writeEnable   =1'b0;
		input_data    =8'h0;				
		//inicializo clock (si o si)
		input_CLK= 1'b0;			
		#10 writeEnable=1'b1;
		#10 writeEnable = 1'b0;
		
		
		
		#50 input_data=8'hFF;
		#50 write_address = write_address + 1;
		#50 read_address = read_address + 1;
		#20 writeEnable = 1'b1;
		#20 writeEnable = 1'b0;
		
		
        #50 input_data=8'b10000001;
        #50 write_address = write_address + 1;
        #50 read_address = read_address + 1;
        #20 writeEnable = 1'b1;
        #20 writeEnable = 1'b0;
        

        #50 input_data=8'b11100111;
        #20 writeEnable = 1'b1;
        #20 writeEnable = 1'b0;
        
		
		     
        
                
		
		#10000000000 $finish;
	end
	
	always #2.5 input_CLK=~input_CLK;
	
//Módulo para pasarle los estímulos del banco de pruebas.

memory
	#(  
	    .NB_ADDRESS(NB_ADDRESS),
		.RAM_WIDTH (RAM_WIDTH)
		)
	u_bram
		(
		.i_data(input_data),
		.i_writeAdd(write_address),
		.i_readAdd(read_address),
		.i_CLK(input_CLK),
		.i_wrEnable(writeEnable),
		.o_data(output_data)
		);
endmodule
module tb_topmicro#(
	parameter BIT_LEN       = `BIT_LEN,
    parameter CONV_LEN      = `CONV_LEN,
    parameter CONV_LPOS     = `CONV_LPOS,
    parameter M_LEN         = `M_LEN,
    parameter NB_ADDRESS    = `NB_ADDRESS,
    parameter RAM_WIDTH     = `RAM_WIDTH,
    parameter GPIO_D        = `GPIO_D
    )();

    wire [GPIO_D-1:0] gpio_i_data_tri_i;
    reg  [GPIO_D-1:0] gpio_o_data_tri_o;
    wire o_led;
    reg CLK100MHZ;
    initial begin
    	CLK100MHZ = 1'b0;
    	gpio_o_data_tri_o = 32'h9;// reste

    	#20 gpio_o_data_tri_o = 32'h1E;
    	
    	#3210 gpio_o_data_tri_o = 32'h0;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#5   gpio_o_data_tri_o = gpio_o_data_tri_o + 32'h100;
    	#20 $finish;

    end

    always #2.5 CLK100MHZ = ~CLK100MHZ;
    micro_sim
    	u_micro_sim(.gpio_i_data_tri_i(gpio_i_data_tri_i),
		   	.o_led(o_led),
			.CLK100MHZ(CLK100MHZ),
			.gpio_o_data_tri_o(gpio_o_data_tri_o));
endmodule
module tb_MCU();

    parameter N = 2;
    parameter STATES = 3;
    parameter BITS_IMAGEN = 8;
    parameter BITS_DATA = 13;
    parameter BITS_ADDR = 10;
    
    reg [N*BITS_DATA-1:0]      i_DataConv;
    reg [BITS_IMAGEN-1:0]          i_Data;
    reg [(N+2)*BITS_DATA-1:0]  i_MemData;
    reg [BITS_ADDR-1:0]          i_WAddr, i_RAddr;
    reg                          i_chblk, i_sop, i_eop, rst, clk;

    wire [3*N*BITS_IMAGEN-1:0]   o_DataConv;
    wire [BITS_DATA-1:0]         o_Data;
    wire [N+1:0]                 o_we;
    wire [BITS_ADDR-1:0]         o_WAddr, o_RAddr;
    wire [(N+2)*BITS_DATA-1:0] o_MemData;
    
    
    initial begin
        
        i_Data     = {BITS_IMAGEN/2{1'b1,1'b0}};
        i_MemData  = {13'h3,13'h2,13'h1,13'h0};
        i_DataConv = {13'hc1,13'hc0};
        i_WAddr = 1;
        i_RAddr = 1;
        
        
        i_sop   = 1'b0;
        i_eop   = 1'b0;
        rst     = 1'b0;
        i_chblk = 1'b0;
        clk     = 1'b0;
        
        #10 rst = 1'b1;
        #20 rst = 1'b0;
        
        #100 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #200 i_sop = 1'b1;
        
        #300 i_sop = 1'b0;
        i_eop = 1'b1;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #100 i_sop = 1'b0;
        i_eop = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #200 i_sop = 1'b1;
        
        #300 i_sop = 1'b0;
        i_eop = 1'b1;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        
        #500 $finish;
    end
    
    always #2.5 clk = ~clk;

    MCU
        #(
          .N(N),
          .STATES(STATES),
          .BITS_IMAGEN(BITS_IMAGEN),
          .BITS_DATA(BITS_DATA),
          .BITS_ADDR(BITS_ADDR)
          )

    u_MCU
        (
         .i_DataConv(i_DataConv),
         .i_Data(i_Data),
         .i_MemData(i_MemData),
         .i_WAddr(i_WAddr),
         .i_RAddr(i_RAddr),
         .i_chblk(i_chblk),
         .i_sop(i_sop),
         .i_eop(i_eop),
         .rst(rst),
         .clk(clk),

         .o_DataConv(o_DataConv),
         .o_Data(o_Data),
         .o_we(o_we),
         .o_WAddr(o_WAddr),
         .o_RAddr(o_RAddr),
         .o_MemData(o_MemData)
         );
    
endmodule
module top_microblaze
    #(
      parameter BIT_LEN       = `BIT_LEN,
      parameter CONV_LEN      = `CONV_LEN,
      parameter CONV_LPOS     = `CONV_LPOS,
      parameter M_LEN         = `M_LEN,
      parameter NB_ADDRESS    = `NB_ADDRESS,
      parameter RAM_WIDTH     = `RAM_WIDTH,
      parameter GPIO_D        = `GPIO_D,
      parameter N = 2,
      parameter BITS_IMAGEN = 8,
      parameter BITS_DATA = 13
      )(
        output [3:0] o_led,
        output       uart_rxd_out,
        input        ck_rst,
        input        CLK100MHZ,
        input        uart_txd_in 
    );


    wire [GPIO_D-1:0] gpio_i_data_tri_i;
    wire [GPIO_D-1:0] gpio_o_data_tri_o;
    
    //reste del micro 
    wire reset;
    //clock de entrada al micro
    wire sys_clock;
    //clock de salida del micro
    wire clk_o;
    wire [2:0] leds;
    
    
    // Microconotrolador
    assign reset        = ck_rst;
    assign sys_clock    = CLK100MHZ;
    
    assign o_led[2:0] = leds;



    // instacia del Microcontrolador
    design_1
        u_desing_1
            (
             .clock100(clk_o),
             .gpio_rtl_tri_i(gpio_i_data_tri_i),
             .gpio_rtl_tri_o(gpio_o_data_tri_o),
             //.gpio_rtl_tri_t,
             .o_lock_clock(o_led[3]),
             .reset(reset),
             .sys_clock(sys_clock),
             .usb_uart_rxd(uart_txd_in),
             .usb_uart_txd(uart_rxd_out)
             );
    top_module
        u_ALL
            (
             .gpio_i_data_tri_i(gpio_i_data_tri_i),
             .o_led(leds),

             .CLK100MHZ(clk_o),
             .gpio_o_data_tri_o(gpio_o_data_tri_o)
             
             );
endmodule
module BRAM( i_wrEnable, i_CLK, i_writeAdd, i_readAdd, i_data, o_data );
    
    parameter RAM_WIDTH = `RAM_WIDTH;    
    parameter NB_ADDRESS= 10;
    parameter INIT_FILE = "";
    localparam RAM_DEPTH=(2**NB_ADDRESS)-1;
    
    
//Definición de puertos
    input                    i_wrEnable;
    input                i_CLK;
    input [NB_ADDRESS-1:0] i_writeAdd;
    input [NB_ADDRESS-1:0] i_readAdd;
    input [RAM_WIDTH - 1:0] i_data;
    
    output [RAM_WIDTH-1:0] o_data;


    
    reg [RAM_WIDTH-1:0]  BRAM [RAM_DEPTH:0];
    reg [RAM_WIDTH-1:0] dout_reg;
    integer        ram_index;
    
    generate
        if (INIT_FILE != "") begin: use_init_file
            initial
                $readmemh(INIT_FILE, BRAM, 0, RAM_DEPTH);
        end else begin: init_bram_to_zero
            integer ram_index;
            initial
                for (ram_index = 0; ram_index < RAM_DEPTH; ram_index = ram_index + 1)
                    BRAM[ram_index] = {RAM_WIDTH{1'b0}};
        end
    endgenerate

    always @(posedge i_CLK) begin
	      dout_reg<=BRAM[i_readAdd];
	      if(i_wrEnable) begin
			      BRAM[i_writeAdd]<=i_data;			
	      end
    end

    assign{o_data}=dout_reg;
    
endmodule
module MCU
    #(
      parameter N = 16,
      parameter STATES = 3,
      parameter BITS_IMAGEN = 8,
      parameter BITS_DATA = 13,
      parameter BITS_ADDR = 10
      )(
        input [N*BITS_DATA-1:0]        i_DataConv,
        input [BITS_IMAGEN-1:0]        i_Data,
        input [(N+2)*BITS_DATA-1:0]    i_MemData,
        input [BITS_ADDR-1:0]          i_WAddr, i_RAddr,
        input                          i_chblk, i_sop, i_eop, rst, clk,

        output [3*N*BITS_IMAGEN-1:0]   o_DataConv,
        output [BITS_DATA-1:0]         o_Data,
        output [N+1:0]                 o_we,
        output [BITS_ADDR-1:0]         o_WAddr, o_RAddr,
        output [(N+2)*BITS_DATA-1:0] o_MemData
        );

    wire [clog2(STATES-1)-1:0]         state;
    wire [clog2(N/2)-1: 0]             substate;
    wire [clog2(N+1)-1:0]              memSelect;
    
    assign o_WAddr = i_WAddr;  //Direcciones van derecho, replicarlas en caso de problemas con fanout
    assign o_RAddr = i_RAddr;
    
    MUX_ARRAY
        #(
          .N(N),
          .BITS_IMAGEN(BITS_IMAGEN),
          .BITS_DATA(BITS_DATA),
          .STATES(STATES)
          )
    
    u_MUX_ARRAY
        (
         .i_DataConv(i_DataConv),
         .i_MemData(i_MemData),
         .i_Data(i_Data),
         .i_state(state),
         .i_substate(substate),
         .i_memSelect(memSelect),
         .o_DataConv(o_DataConv),
         .o_MemData(o_MemData),
         .o_Data(o_Data)
         );

    MCU_CTRL
        #(
          .N(N),
          .STATES(STATES)
          )

    u_MCU_CTRL
        (
         .i_sop(i_sop),
         .i_eop(i_eop),
         .i_chblk(i_chblk),
         .clk(clk),
         .rst(rst),

         .o_we(o_we),
         .o_state(state),
         .o_substate(substate),
         .o_memSelect(memSelect)
         );

    function integer clog2;
        input integer                  depth;
        for (clog2=0; depth>0; clog2=clog2+1)
            depth = depth >> 1;
    endfunction

endmodule
module tb_MCU_CTRL();

    parameter N = 2;
    parameter STATES = 3;
    
    reg                          i_sop, i_eop, clk, rst, i_chblk;

    wire [N+1:0]                 o_we;
    wire [$clog2(STATES)-1:0]    o_state;
    wire [$clog2(N/2+1) - 1:0]     o_substate;
    wire [$clog2(N+2) - 1:0]     o_memSelect;
    
    initial begin

        i_sop   = 1'b0;
        i_eop   = 1'b0;
        rst     = 1'b0;
        i_chblk = 1'b0;
        clk     = 1'b0;

        #10 rst = 1'b1;
        #20 rst = 1'b0;

        #100 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;

        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;

        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;

        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;

        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;

        #200 i_sop = 1'b1;

        #300 i_sop = 1'b0;
             i_eop = 1'b1;

        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;

        #100 i_sop = 1'b0;
        i_eop = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;

        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;

        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;

        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;

        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;

        #200 i_sop = 1'b1;

        #300 i_sop = 1'b0;
        i_eop = 1'b1;

        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;
        
        #10 i_chblk = 1'b1;
        #10 i_chblk = 1'b0;


        #500 $finish;
    end

    always #2.5 clk = ~clk;


    MCU_CTRL
        #(
          .N(N),
          .STATES(STATES)
          )

    u_MCU_CTRL
        (
         .i_sop(i_sop),
         .i_eop(i_eop),
         .i_chblk(i_chblk),
         .clk(clk),
         .rst(rst),

         .o_we(o_we),
         .o_state(o_state),
         .o_substate(o_substate),
         .o_memSelect(o_memSelect)
         );
    
endmodule
module tb_MUX_ARRAY();
    
    parameter N = 4;
    parameter BITS_IMAGEN = 8;
    parameter STATES = 3;
    parameter BITS_DATA = 13;

    
    reg [N*BITS_DATA-1:0]          i_DataConv;
    reg [(N+2)*BITS_DATA-1:0]      i_MemData;
    reg [BITS_IMAGEN-1:0]              i_Data;

    reg [clog2(STATES-1)-1:0]         i_state;
    reg [clog2(N/2) - 1:0]     i_substate; //PARA N PAR
    
    reg [clog2(N+1)-1:0]            i_memSelect;

    wire [3*N*BITS_IMAGEN-1:0]       o_DataConv;
    wire [(N+2)*BITS_DATA-1:0]     o_MemData;
    wire [BITS_DATA-1:0]               o_Data;
    

    initial begin
    
        $display("%d", 2**clog2(N/2));
        i_Data     = {BITS_IMAGEN{1'b1,1'b0}};
        i_MemData  = {13'b0, 13'b1, 13'b0, 13'b1};
        i_DataConv = {13'h3,13'h2,13'h1,13'h0};
        
        i_state     = 0;
        i_substate  = 0;
        i_memSelect = 0;
        
        #100 i_memSelect = 1;
        #200 i_memSelect = 2;
        #300 i_memSelect = 3;
        
        #350 i_state = 1;
        #500 i_substate = 1;
        
        #600 i_state  = 2;
             i_memSelect = 0;
        #650 i_memSelect = 1;
        #700 i_memSelect = 2;
        
        #800 $finish;

    end

    MUX_ARRAY
        #(
          .N(N),
          .BITS_IMAGEN(BITS_IMAGEN),
          .BITS_DATA(BITS_DATA),
          .STATES(STATES)
          )
    
    u_MUX_ARRAY
        (
         .i_DataConv(i_DataConv),
         .i_MemData(i_MemData),
         .i_Data(i_Data),
         .i_state(i_state),
         .i_substate(i_substate),
         .i_memSelect(i_memSelect),
         .o_DataConv(o_DataConv),
         .o_MemData(o_MemData),
         .o_Data(o_Data)
         );
             
             
        function integer clog2;
             input integer depth;
             for (clog2=0; depth>0; clog2=clog2+1)
                 depth = depth >> 1;
         endfunction
         
endmodule
module top_microblaze
    #(
      parameter BIT_LEN       = `BIT_LEN,
      parameter CONV_LEN      = `CONV_LEN,
      parameter CONV_LPOS     = `CONV_LPOS,
      parameter M_LEN         = `M_LEN,
      parameter NB_ADDRESS    = `NB_ADDRESS,
      parameter RAM_WIDTH     = `RAM_WIDTH,
      parameter GPIO_D        = `GPIO_D,
      parameter N = 2,
      parameter BITS_IMAGEN = 8,
      parameter BITS_DATA = 13
      )(
        output [3:0] o_led,
        output       uart_rxd_out,
        input        ck_rst,
        input        CLK100MHZ,
        input        uart_txd_in 
    );


    wire [GPIO_D-1:0] gpio_i_data_tri_i;
    wire [GPIO_D-1:0] gpio_o_data_tri_o;
    
    //reste del micro 
    wire reset;
    //clock de entrada al micro
    wire sys_clock;
    //clock de salida del micro
    wire clk_o;
    wire [2:0] leds;
    
    
    // Microconotrolador
    assign reset        = ck_rst;
    assign sys_clock    = CLK100MHZ;
    
    assign o_led[2:0] = leds;



    // instacia del Microcontrolador
    design_1
        u_desing_1
            (
             .clock100(clk_o),
             .gpio_rtl_tri_i(gpio_i_data_tri_i),
             .gpio_rtl_tri_o(gpio_o_data_tri_o),
             //.gpio_rtl_tri_t,
             .o_lock_clock(o_led[3]),
             .reset(reset),
             .sys_clock(sys_clock),
             .usb_uart_rxd(uart_txd_in),
             .usb_uart_txd(uart_rxd_out)
             );
    micro_sim
        u_ALL
            (
             .gpio_i_data_tri_i(gpio_i_data_tri_i),
             .o_led(leds),

             .CLK100MHZ(clk_o),
             .gpio_o_data_tri_o(gpio_o_data_tri_o)
             
             );
endmodule
module top_microblaze_all
    (
        input           	 i_CLK,
        input 	[3:0]        sw,
        input 	[3:0]        btn,
        output 	[3:0]        o_led,
        output          	 uart_rxd_out,
        input           	 uart_txd_in, 
        input                ck_rst
    );
        
        parameter BITS_ADDRESS= `NB_ADDRESS;
        parameter BITS_IMAGE  = `NB_IMAGE;
        
        wire [31:0]gpio_i_data_tri_i;
        wire [31:0]gpio_o_data_tri_o;
        wire rst;
        wire sys_clock;
        wire uart_rtl_rxd;
        wire uart_rtl_txd;
        wire [2:0] ledstates;
        
        //Senales nuevas
        wire led_warning;
        wire valid;
        wire reset_sw;
        wire clock1;
        wire clock2;
       
    
        //Assigns:
        assign  rst                         = ck_rst;
        assign  sys_clock                   = i_CLK;
        assign  uart_rtl_rxd                = uart_txd_in;
        assign  uart_rxd_out                = uart_rtl_txd;
        assign  o_led[3]                    = led_warning;
        assign  o_led[2:0]                  = ledstates;
        
        

//MICRO NUEVO
  design_1
        u_microblaze
           (.clock100(clock2),
            .gpio_rtl_tri_i(gpio_i_data_tri_i),
            .gpio_rtl_tri_o(gpio_o_data_tri_o),
            .o_lock_clock(led_warning),
            .reset(rst),
            .sys_clock(sys_clock),
            .usb_uart_rxd(uart_rtl_rxd),
            .usb_uart_txd(uart_rtl_txd)
            );
    

    micro_all
        u_topMicro(
            .gpio_i_data_tri_i(gpio_i_data_tri_i),
            .o_led(ledstates),
            .i_CLK(clock2),
            .gpio_o_data_tri_o(gpio_o_data_tri_o)
            );
  

endmodule
module Convolutor#(
    parameter BIT_LEN =`BIT_LEN,
    parameter CONV_LEN =`CONV_LEN,
    parameter CONV_LPOS = `CONV_LPOS,
    parameter M_LEN = `M_LEN
    )(
    output [CONV_LPOS-1:0] o_data,
    input [BIT_LEN-1:0] i_dato0,
    input [BIT_LEN-1:0] i_dato1,
    input [BIT_LEN-1:0] i_dato2,
    input i_selecK_I,
    input i_reset,
    input i_valid,
    input i_CLK
    );
    // registros del kernel
    // [j][i] Primero columnas luego filas
    reg signed [3*BIT_LEN-1:0] kernel [0:M_LEN-1];    
    // registros de la imagen
    reg signed [3*BIT_LEN-1:0] imagen [0:M_LEN-1];

    // resultado
    reg [CONV_LEN-1:0]  conv_reg;

    // reg de la convolucion
    reg signed [CONV_LEN-1:0] resultado;
    
    //  el resto de los cables    
    wire clk, selecK_I, rst, valid;

    integer ptr_row;
    integer ptr_column;

    assign clk = i_CLK;
    assign selecK_I = i_selecK_I; //KI=0 modo kernle k=1 modo imagen
    assign rst = i_reset;
    assign valid = i_valid;

    //Asigancion de Convolucion a la salida
    assign {o_data[CONV_LPOS-1],o_data[CONV_LPOS-2:0]}= {~conv_reg[CONV_LEN-1], conv_reg[CONV_LEN-2 : CONV_LEN-CONV_LPOS]};

    always @( posedge clk) begin
        if(rst) begin
            //reset valores de imagen
            imagen[0]<=24'h0;
            imagen[1]<=24'h0;
            imagen[2]<=24'h0;
            //reser valores de kernel
            kernel[0]<=24'h0;
            kernel[1]<=24'h0;
            kernel[2]<=24'h0;
            //regitro de la convolucion
            conv_reg<=0;
        end
        else if(valid)begin
            case (selecK_I)
                1'b1: begin
                    // imagen
                    imagen[0]<=imagen[1];
                    imagen[1]<=imagen[2];
                    imagen[2]<={i_dato2,i_dato1,i_dato0};
                    //latcheo de la salida 
                    conv_reg<= resultado;
                    //conv_reg<= resultado;
                end
                1'b0: begin
                    //kernel
                    kernel[0]<=kernel[1];
                    kernel[1]<=kernel[2];
                    kernel[2]<={i_dato2,i_dato1,i_dato0};
                    //salida
                    conv_reg<=conv_reg;

                end
            endcase
        end
        else begin 
            //imagen 
            imagen[0]<=imagen[0];
            imagen[1]<=imagen[1];
            imagen[2]<=imagen[2];
            //kernel
            kernel[0]<=kernel[0];
            kernel[1]<=kernel[1];
            kernel[2]<=kernel[2];
            //matengo el lacheo
            conv_reg<=conv_reg;
        end
    end
    
    //Arbol de Suma
    always @(*) begin

        resultado = 20'h0;
        for(ptr_row = 0 ; ptr_row < 3 ; ptr_row=ptr_row+1) 
        begin : SumaYMult
            for (ptr_column = 0 ; ptr_column < 3; ptr_column=ptr_column+1) 
            begin: SumaTop
                resultado = resultado + $signed(kernel[ptr_row][(ptr_column+1)*BIT_LEN-1 -: BIT_LEN])*
                                        $signed(imagen[ptr_row][(ptr_column+1)*BIT_LEN-1 -: BIT_LEN]);
            end
        end
        
    end
endmodule
module Conv #(
    parameter BIT_LEN =`BIT_LEN,
    parameter CONV_LEN =`CONV_LEN,
    parameter CONV_LPOS = `CONV_LPOS,
    parameter M_LEN = `M_LEN
    )(
    output [CONV_LPOS-1:0] o_data,
    input [BIT_LEN-1:0] i_dato0,
    input [BIT_LEN-1:0] i_dato1,
    input [BIT_LEN-1:0] i_dato2,
    input i_selecK_I,
    input i_reset,
    input i_valid,
    input CLK100MHZ
    );
    // registros del kernel
    // [j][i] Primero columnas luego filas
    reg signed [3*BIT_LEN-1:0] kernel [0:M_LEN-1];    
    // registros de la imagen
    reg signed [3*BIT_LEN-1:0] imagen [0:M_LEN-1];

    // resultado
    reg [CONV_LEN-1:0]  conv_reg;

    // reg de la convolucion
    reg signed [CONV_LEN-1:0] resultado;
    
    //  el resto de los cables    
    wire clk, selecK_I, rst, valid;

    integer ptr_row;
    integer ptr_column;

    assign clk = CLK100MHZ;
    assign selecK_I = i_selecK_I; //KI=0 modo kernle k=1 modo imagen
    assign rst = i_reset;
    assign valid = i_valid;

    //Asigancion de Convolucion a la salida
    assign {o_data[CONV_LPOS-1],o_data[CONV_LPOS-2:0]}= {~conv_reg[CONV_LEN-1], conv_reg[CONV_LEN-2 : CONV_LEN-CONV_LPOS]};

    always @( posedge clk) begin
        if(rst) begin
            //reset valores de imagen
            imagen[0]<=24'h0;
            imagen[1]<=24'h0;
            imagen[2]<=24'h0;
            //reser valores de kernel . modif
            kernel[0]<=24'h002000;
            kernel[1]<=24'h208020;
            kernel[2]<=24'h002000;
            //regitro de la convolucion
            conv_reg<=0;
        end
        else if(valid)begin
            case (selecK_I)
                1'b1: begin
                    // imagen
                    imagen[0]<=imagen[1];
                    imagen[1]<=imagen[2];
                    imagen[2]<={i_dato2,i_dato1,i_dato0};
                    //latcheo de la salida 
                    conv_reg<= resultado;
                    //conv_reg<= resultado;
                end
                1'b0: begin
                    //kernel
                    kernel[0]<=kernel[1];
                    kernel[1]<=kernel[2];
                    kernel[2]<={i_dato2,i_dato1,i_dato0};
                    //salida
                    conv_reg<=conv_reg;

                end
            endcase
        end
        else begin 
            //imagen 
            imagen[0]<=imagen[0];
            imagen[1]<=imagen[1];
            imagen[2]<=imagen[2];
            //kernel
            kernel[0]<=kernel[0];
            kernel[1]<=kernel[1];
            kernel[2]<=kernel[2];
            //matengo el lacheo
            conv_reg<=conv_reg;
        end
    end
    
    //Arbol de Suma
    always @(*) begin
        resultado = 20'h0;
        for(ptr_row = 0 ; ptr_row < M_LEN ; ptr_row=ptr_row+1) 
        begin : SumaYMult
            for (ptr_column = 0 ; ptr_column < M_LEN ; ptr_column=ptr_column+1) 
            begin: SumaTop
                resultado = resultado + $signed(kernel[ptr_row][(ptr_column+1)*BIT_LEN-1 -: BIT_LEN])*
                                        $signed(imagen[ptr_row][(ptr_column+1)*BIT_LEN-1 -: BIT_LEN]);
            end
        end
    end
endmodule
module MCU
    #(
      parameter N = 2,
      parameter STATES = 3,
      parameter BITS_IMAGEN = 8,
      parameter BITS_DATA = 13,
      parameter BITS_ADDR = 10
      )(
        input [N*BITS_DATA-1:0]        i_DataConv,
        input [BITS_IMAGEN-1:0]        i_Data,
        input [(N+2)*BITS_DATA-1:0]    i_MemData,
        input [BITS_ADDR-1:0]          i_WAddr, i_RAddr,
        input                          i_chblk, i_sop, i_eop, rst, clk,

        output [3*N*BITS_IMAGEN-1:0]   o_DataConv,
        output [BITS_DATA-1:0]         o_Data,
        output [N+1:0]                 o_we,
        output [BITS_ADDR-1:0]         o_WAddr, o_RAddr,
        output [(N+2)*BITS_DATA-1:0] o_MemData
        );

    wire [clog2(STATES-1)-1:0]         state;
    wire [clog2(N/2)-1: 0]             substate;
    wire [clog2(N+1)-1:0]              memSelect;
    
    assign o_WAddr = i_WAddr;  //Direcciones van derecho, replicarlas en caso de problemas con fanout
    assign o_RAddr = i_RAddr;
    
    MUX_ARRAY
        #(
          .N(N),
          .BITS_IMAGEN(BITS_IMAGEN),
          .BITS_DATA(BITS_DATA),
          .STATES(STATES)
          )
    
    u_MUX_ARRAY
        (
         .i_DataConv(i_DataConv),
         .i_MemData(i_MemData),
         .i_Data(i_Data),
         .i_state(state),
         .i_substate(substate),
         .i_memSelect(memSelect),
         .o_DataConv(o_DataConv),
         .o_MemData(o_MemData),
         .o_Data(o_Data)
         );

    MCU_CTRL
        #(
          .N(N),
          .STATES(STATES)
          )

    u_MCU_CTRL
        (
         .i_sop(i_sop),
         .i_eop(i_eop),
         .i_chblk(i_chblk),
         .clk(clk),
         .rst(rst),

         .o_we(o_we),
         .o_state(state),
         .o_substate(substate),
         .o_memSelect(memSelect)
         );

    function integer clog2;
        input integer                  depth;
        for (clog2=0; depth>0; clog2=clog2+1)
            depth = depth >> 1;
    endfunction

endmodule
module BRAM( i_wrEnable, 
                  i_CLK, 
             i_writeAdd,
              i_readAdd, 
                 i_data,
                 o_data );
    
    parameter RAM_WIDTH = `RAM_WIDTH;    
    parameter NB_ADDRESS= 10;
    parameter INIT_FILE = "";
    localparam RAM_DEPTH=(2**NB_ADDRESS)-1;
    
    
//Definición de puertos
    input                    i_wrEnable;
    input                i_CLK;
    input [NB_ADDRESS-1:0] i_writeAdd;
    input [NB_ADDRESS-1:0] i_readAdd;
    input [RAM_WIDTH - 1:0] i_data;
    
    output [RAM_WIDTH-1:0] o_data;


    
    reg [RAM_WIDTH-1:0]  BRAM [RAM_DEPTH:0];
    reg [RAM_WIDTH-1:0] dout_reg;
    integer        ram_index;
    
    generate
        if (INIT_FILE != "") begin: use_init_file
            initial
                $readmemh(INIT_FILE, BRAM, 0, RAM_DEPTH);
        end else begin: init_bram_to_zero
            integer ram_index;
            initial
                for (ram_index = 0; ram_index < RAM_DEPTH; ram_index = ram_index + 1)
                    BRAM[ram_index] = {RAM_WIDTH{1'b0}};
        end
    endgenerate

    always @(posedge i_CLK) begin
	      dout_reg<=BRAM[i_readAdd];
	      if(i_wrEnable) begin
			      BRAM[i_writeAdd]<=i_data;			
	      end
    end

    assign{o_data}=dout_reg;
    
endmodule
module top_microblaze
    #(
      parameter BIT_LEN       = `BIT_LEN,
      parameter CONV_LEN      = `CONV_LEN,
      parameter CONV_LPOS     = `CONV_LPOS,
      parameter M_LEN         = `M_LEN,
      parameter NB_ADDRESS    = `NB_ADDRESS,
      parameter RAM_WIDTH     = `RAM_WIDTH,
      parameter GPIO_D        = `GPIO_D,
      parameter N = 2,
      parameter BITS_IMAGEN = 8,
      parameter BITS_DATA = 13
      )(
        output [3:0] o_led,
        output       uart_rxd_out,
        input        i_CLK,
        input        ck_rst,
        input        uart_txd_in 
    );


    wire [GPIO_D-1:0] gpio_i_data_tri_i;
    wire [GPIO_D-1:0] gpio_o_data_tri_o;
    
    //reste del micro 
    wire reset;
    //clock de entrada al micro
    wire sys_clock;
    //clock de salida del micro
    wire clk_o;
    wire [2:0] ledStates;
    wire led_clock;
    
    // Microconotrolador
    assign reset        = ck_rst;
    assign sys_clock    = i_CLK;
    assign  o_led[3]    = led_clock;
    assign  o_led[2:0]  = ledStates;



    // instacia del Microcontrolador
    design_1
        u_desing_1
            (
             .clock100(clk_o),
             .gpio_rtl_tri_i(gpio_i_data_tri_i),
             .gpio_rtl_tri_o(gpio_o_data_tri_o),
             //.gpio_rtl_tri_t,
             .o_lock_clock(led_clock),
             .reset(reset),
             .sys_clock(sys_clock),
             .usb_uart_rxd(uart_txd_in),
             .usb_uart_txd(uart_rxd_out)
             );
    top_module
        u_ALL
            (
             .gpio_i_data_tri_i(gpio_i_data_tri_i),
             .o_led(ledStates),
             .CLK100MHZ(clk_o),
             .gpio_o_data_tri_o(gpio_o_data_tri_o)
             
             );
endmodule
module uart_baud_gen(
  ctrl_baud_gen_divisor,
  ctrl_baud_gen_set_dllh_vld,
  receive_clk_en,
  rst_b,
  sys_clk,
  trans_clk_en
);


input   [15:0]  ctrl_baud_gen_divisor;     
input           ctrl_baud_gen_set_dllh_vld; 
input           rst_b;                     
input           sys_clk;                   
output          receive_clk_en;            
output          trans_clk_en;              


reg     [15:0]  clk_counter;               
reg             receive_clk_en;            
reg     [3 :0]  trans_clk_counter;         


wire            clk_divisor_start_en;      
wire            clk_negedge_en;            
wire    [15:0]  ctrl_baud_gen_divisor;     
wire            ctrl_baud_gen_set_dllh_vld; 
wire            divisor_more_then_3;       
wire            rst_b;                     
wire            sys_clk;                   
wire            trans_clk_en;              
wire            trans_clk_posedge_en;      
























assign clk_divisor_start_en = |ctrl_baud_gen_divisor[15:0];

assign clk_negedge_en  = (clk_counter[15:0] == ctrl_baud_gen_divisor[15:0]) ? 1 : 0 ;
 
always@(posedge sys_clk or negedge rst_b) 
begin 
  if(!rst_b) 
    clk_counter[15:0] <= 16'b1;
  else if(ctrl_baud_gen_set_dllh_vld)
    clk_counter[15:0] <= 16'b1;
  else if(clk_negedge_en)
    clk_counter[15:0] <= 1'b1; 
  else if(clk_divisor_start_en)
    clk_counter[15:0] <= clk_counter[15:0]+1;
  else
    clk_counter[15:0] <= clk_counter[15:0];
end
















assign divisor_more_then_3 = |ctrl_baud_gen_divisor[15:2];


always @( ctrl_baud_gen_divisor[1:0]
       or clk_negedge_en
       or divisor_more_then_3)
begin
casez({divisor_more_then_3,ctrl_baud_gen_divisor[1:0]})
  3'b000: receive_clk_en = 1'b0;
  3'b001: receive_clk_en = 1'b1;
  3'b010: receive_clk_en = clk_negedge_en;
  3'b011,
  3'b1??: receive_clk_en = clk_negedge_en;
  default: receive_clk_en = 1'b0;
endcase

end






always@(posedge sys_clk or negedge rst_b)
begin
  if(!rst_b)
   trans_clk_counter[3:0] <= 4'b0;
  else if(receive_clk_en) 
   trans_clk_counter[3:0] <= trans_clk_counter[3:0] + 1'b1;
  else 
   trans_clk_counter[3:0] <= trans_clk_counter[3:0];
end

assign trans_clk_posedge_en = (trans_clk_counter[3:0] == 4'b1111) ? 1 : 0;

assign trans_clk_en  = receive_clk_en && trans_clk_posedge_en;
















endmodule
module ram(
  PortAClk,
  PortAAddr,
  PortADataIn,
  PortAWriteEnable,

  PortADataOut
);

parameter  DATAWIDTH = 2;
parameter  ADDRWIDTH = 2;

input                     PortAClk;
input   [(ADDRWIDTH-1):0] PortAAddr;
input   [(DATAWIDTH-1):0] PortADataIn;
input                     PortAWriteEnable;

output  [(DATAWIDTH-1):0] PortADataOut; 

parameter  MEMDEPTH = 2**(ADDRWIDTH);

reg [(DATAWIDTH-1):0] mem [(MEMDEPTH-1):0];
reg [(DATAWIDTH-1):0] PortADataOut;

always @(posedge PortAClk)
begin
  if(PortAWriteEnable)
  begin
    mem[PortAAddr]  <= PortADataIn;
  end
  else
  begin
    PortADataOut    <= mem[PortAAddr];
  end
end

endmodule
module fpga_clk_gen(
  clk_en,
  clkrst_b,
  i_pad_clk,
  pad_biu_clkratio,
  penable,
  per_clk,
  prdata,
  psel,
  pwdata,
  pwrite
);


input           clkrst_b;        
input           i_pad_clk;       
input           penable;         
input           psel;            
input   [2 :0]  pwdata;          
input           pwrite;          
output          clk_en;          
output  [2 :0]  pad_biu_clkratio; 
output          per_clk;         
output  [31:0]  prdata;          


reg     [2 :0]  input_clkratio;  
reg     [31:0]  prdata;          


wire            clk_en;          
wire            clkrst_b;        
wire            i_pad_clk;       
wire    [2 :0]  pad_biu_clkratio; 
wire            penable;         
wire            per_clk;         
wire            psel;            
wire    [2 :0]  pwdata;          
wire            pwrite;          


always@(posedge per_clk or negedge clkrst_b)
begin
  if (!clkrst_b)
    input_clkratio[2:0] <= 3'b0;
  else if(psel && pwrite && penable)
    input_clkratio[2:0] <= pwdata[2:0]; 
end


always @( input_clkratio[2:0]
       or psel
       or pwrite)
begin
if(psel && !pwrite)
begin
  prdata[31:0] <= {29'b0,input_clkratio[2:0]};
end

end

assign per_clk = i_pad_clk;

assign clk_en = 1'b1;
assign pad_biu_clkratio[2:0] = input_clkratio[2:0];





endmodule
module counter(
  interrupt,
  pclk,
  presetn,
  timer_current_value,
  timer_enable,
  timer_load_count,
  timer_mode
);


input           pclk;               
input           presetn;            
input           timer_enable;       
input   [31:0]  timer_load_count;   
input           timer_mode;         
output          interrupt;          
output  [31:0]  timer_current_value; 


reg     [31:0]  counter;            
reg             interrupt;          
reg             timer_enable_flop;  


wire            load_cnt_en;        
wire            pclk;               
wire            presetn;            
wire    [31:0]  timer_current_value; 
wire            timer_enable;       
wire    [31:0]  timer_load_count;   
wire            timer_mode;         





always @(posedge pclk or negedge presetn)
begin
  if(!presetn)
  begin
      timer_enable_flop <=0;
  end
  else
  begin
      timer_enable_flop <=timer_enable ;
  end
end

assign load_cnt_en= (timer_enable && !timer_enable_flop)
                    || !(|counter[31:0]);

always @(posedge pclk or negedge presetn)
begin
  if(!presetn)
  begin
      counter[31:0] <=32'hffffffff;
  end
  else if(load_cnt_en)
  begin
    if(timer_mode)
    begin
      counter[31:0]<=timer_load_count[31:0];
    end
    else 
    begin
      counter[31:0]<=32'hffffffff;
    end
  end
  else if (timer_enable)
  begin
    counter[31:0]<=counter[31:0]-1'b1;
  end
  else
  begin
    counter[31:0]<=counter[31:0];
  end
end

assign timer_current_value[31:0]=counter[31:0];




always @(posedge pclk or negedge presetn)
begin
  if(!presetn)
  begin
    interrupt <=1'b0;
  end
  else if(!{|counter[31:0]})
  begin
    interrupt <=1'b1;
  end
  else
  begin
    interrupt<=1'b0 ;
  end
end


endmodule
module fifo_counter(
  counter_done,
  counter_en,
  counter_load,
  cpu_clk,
  cpu_rst_b
);


input           counter_en;   
input   [31:0]  counter_load; 
input           cpu_clk;      
input           cpu_rst_b;    
output          counter_done; 


reg     [31:0]  counter;      
reg             counter_en_ff; 


wire            counter_done; 
wire            counter_en;   
wire    [31:0]  counter_load; 
wire            cpu_clk;      
wire            cpu_rst_b;    
wire            load_cnt_en;  


always @(posedge cpu_clk or negedge cpu_rst_b)
begin
  if(!cpu_rst_b)
  begin
    counter_en_ff <= 1'b0;
  end
  else
  begin
    counter_en_ff <=counter_en ;
  end
end

assign load_cnt_en= (counter_en && !counter_en_ff);


always @(posedge cpu_clk or negedge cpu_rst_b)
begin
  if(!cpu_rst_b)
  begin
    counter[31:0] <= 32'hc8;
  end
  else if (load_cnt_en)
  begin
    counter[31:0] <= counter_load[31:0];
  end
  else if (counter_done)
    counter[31:0] <= 32'hc8;
  else 
    counter[31:0] <= counter[31:0] -1'b1;
 end

assign counter_done = (counter[31:0] == 32'b0) ;


endmodule
module wid_entry(
  biu_pad_awid,
  pad_cpu_rst_b,
  per_clk,
  wid,
  wid_entry_push
);


input   [7:0]  biu_pad_awid;  
input          pad_cpu_rst_b; 
input          per_clk;       
input          wid_entry_push; 
output  [7:0]  wid;           


reg     [7:0]  wid_f;         


wire    [7:0]  biu_pad_awid;  
wire           pad_cpu_rst_b; 
wire           per_clk;       
wire    [7:0]  wid;           
wire           wid_entry_push; 


always@(posedge per_clk or negedge pad_cpu_rst_b)
begin
  if (!pad_cpu_rst_b)
    wid_f[7:0] <= 8'b0;
  else if (wid_entry_push)
    wid_f[7:0] <= biu_pad_awid[7:0];
end

assign wid[7:0] = wid_entry_push ? biu_pad_awid[7:0] : wid_f[7:0];


endmodule
module err_gen(
  hburst_s3,
  hmastlock,
  hprot_s3,
  hrdata_s3,
  hready_s3,
  hresp_s3,
  hsel_s3,
  hsize_s3,
  htrans_s3,
  hwdata_s3,
  hwrite_s3,
  pad_cpu_rst_b,
  pll_core_cpuclk
);


input   [2  :0]  hburst_s3;      
input            hmastlock;      
input   [3  :0]  hprot_s3;       
input            hsel_s3;        
input   [2  :0]  hsize_s3;       
input   [1  :0]  htrans_s3;      
input   [127:0]  hwdata_s3;      
input            hwrite_s3;      
input            pad_cpu_rst_b;  
input            pll_core_cpuclk; 
output  [127:0]  hrdata_s3;      
output           hready_s3;      
output  [1  :0]  hresp_s3;       


reg              hready_s3;      


wire    [127:0]  hrdata_s3;      
wire    [1  :0]  hresp_s3;       
wire             hsel_s3;        
wire             pad_cpu_rst_b;  
wire             pll_core_cpuclk; 




















assign hresp_s3[1:0]  =  2'b01 ;

always @(posedge pll_core_cpuclk or negedge pad_cpu_rst_b)
begin
  if(!pad_cpu_rst_b)
    begin
      hready_s3 <= 1'b0;
    end
  else if(hsel_s3)
    begin
      hready_s3 <= 1'b0;
    end
  else
    begin
      hready_s3 <= 1'b1;     
    end
end






assign hrdata_s3[127:0] = 128'b0;

endmodule