dakies/OSS_Verilog huggingface dataset:
module tcam #(
	parameter ADDR_WIDTH = 4,
	parameter KEY_WIDTH = 4,
	parameter DATA_WIDTH = 4,
	parameter MASK_DISABLE = 0,
	parameter RAM_STYLE_DATA = "block"
)
(
	input wire clk,
	input wire rst,
	/* Set */
	input wire [ADDR_WIDTH-1:0]set_addr,
	input wire [DATA_WIDTH-1:0]set_data,
	input wire [KEY_WIDTH-1:0]set_key,
	input wire [KEY_WIDTH-1:0]set_xmask,
	input wire set_clr,
	input wire set_valid,
	/* Request */
	input wire [KEY_WIDTH-1:0]req_key,
	input wire req_valid,
	output wire req_ready,
	/* Response */
	output wire [ADDR_WIDTH-1:0]res_addr,
	output wire [DATA_WIDTH-1:0]res_data,
	output wire res_valid,
	output wire res_null
);

reg line_valid;
wire [2**ADDR_WIDTH-1:0]line_match;
wire [ADDR_WIDTH-1:0]enc_addr;
wire enc_valid;
wire enc_null;

reg [ADDR_WIDTH-1:0]res_addr_out;
reg res_valid_out;
reg res_null_out;

genvar g;

assign req_ready = (rst == 1'b1) ? 1'b0 : ~(line_valid | enc_valid | res_valid_out);
assign res_addr = res_addr_out;
assign res_valid = res_valid_out;
assign res_null = res_null_out;

always @(posedge clk) begin
	if (rst == 1'b1) begin
		line_valid <= 1'b0;
		res_addr_out <= 0;
		res_valid_out <= 1'b0;
		res_null_out <= 1'b0;
	end else begin
		line_valid <= req_valid;
		res_addr_out <= enc_addr;
		res_valid_out <= enc_valid;
		res_null_out <= enc_null;
	end
end

tcam_line_array #(
	.ADDR_WIDTH(ADDR_WIDTH),
	.KEY_WIDTH(KEY_WIDTH),
	.MASK_DISABLE(MASK_DISABLE)
) tcam_line_array_inst (
	.clk(clk),
	.rst(rst),
	.set_addr(set_addr),
	.set_key(set_key),
	.set_xmask(set_xmask),
	.set_clr(set_clr),
	.set_valid(set_valid),
	.req_key(req_key),
	.req_valid(req_valid & req_ready),
	.line_match(line_match)
);

tcam_line_encoder #(
	.ADDR_WIDTH(ADDR_WIDTH)
) tcam_line_encoder_inst (
	.clk(clk),
	.rst(rst),
	.line_match(line_match),
	.line_valid(line_valid),
	.addr(enc_addr),
	.addr_valid(enc_valid),
	.addr_null(enc_null)
);

tcam_sdpram #(
	.ADDR_WIDTH(ADDR_WIDTH),
	.DATA_WIDTH(DATA_WIDTH),
	.RAM_STYLE(RAM_STYLE_DATA)
) tcam_sdpram_inst (
	.clk(clk),
	.rst(rst),
	.dina(set_data),
	.addra(set_addr),
	.addrb(enc_addr),
	.wea(set_valid),
	.doutb(res_data)
);

endmodule
module tcam_line_array #(
	parameter ADDR_WIDTH = 8,
	parameter KEY_WIDTH = 8,
	parameter MASK_DISABLE = 0
)
(
	input wire clk,
	input wire rst,
	input wire [ADDR_WIDTH-1:0]set_addr,
	input wire [KEY_WIDTH-1:0]set_key,
	input wire [KEY_WIDTH-1:0]set_xmask,
	input wire set_clr,
	input wire set_valid,
	input wire [KEY_WIDTH-1:0]req_key,
	input wire req_valid,
	output wire [2**ADDR_WIDTH-1:0]line_match
);

localparam MEM_WIDTH = (MASK_DISABLE) ? KEY_WIDTH : KEY_WIDTH*2;

reg [MEM_WIDTH-1:0]mem[2**ADDR_WIDTH-1:0];
reg [2**ADDR_WIDTH-1:0]active;
reg [2**ADDR_WIDTH-1:0]match;
wire [KEY_WIDTH-1:0]key[2**ADDR_WIDTH-1:0];
wire [KEY_WIDTH-1:0]xmask[2**ADDR_WIDTH-1:0];

integer i;
genvar g;

generate for (g = 0; g < 2**ADDR_WIDTH; g = g + 1) begin
	wire [MEM_WIDTH-1:0]mem_tmp;
	assign mem_tmp = mem[g];
	if (MASK_DISABLE) begin
		assign key[g] = mem_tmp;
		assign xmask[g] = {KEY_WIDTH{1'b0}};
	end else begin
		assign key[g] = mem_tmp[KEY_WIDTH-1-:KEY_WIDTH];
		assign xmask[g] = mem_tmp[KEY_WIDTH*2-1-:KEY_WIDTH];
	end
end endgenerate

assign line_match = match;

/* Initial */
initial begin
	for (i = 0; i < 2**ADDR_WIDTH; i = i + 1) begin
		mem[i] = 0;
	end
end

/* Set */
always @(posedge clk) begin
	if (rst == 1'b1) begin
		active = {KEY_WIDTH{1'b0}};
	end else begin
		if (set_valid == 1'b1) begin
			for (i = 0; i < 2**ADDR_WIDTH; i = i + 1) begin
				if (set_addr == i) begin
					if (MASK_DISABLE) begin
						mem[i] <= set_key;
					end else begin
						mem[i] <= {set_xmask, set_key};
					end
					active[i] <= ~set_clr;
				end
			end
		end
	end
end

/* Request */
always @(posedge clk) begin
	if (rst == 1'b1) begin
		match <= {2**ADDR_WIDTH{1'b0}};
	end else begin
		if (req_valid == 1'b1) begin
			for (i = 0; i < 2**ADDR_WIDTH; i = i + 1) begin
				if (MASK_DISABLE) begin
					match[i] <= ((key[i] ^ req_key) == 0) & active[i];
				end else begin
					match[i] <= ((key[i] ^ req_key & ~xmask[i]) == 0) & active[i];
				end
			end
		end
	end
end

endmodule
module lms_ctr (
	clk_clk,
	dac_spi_ext_MISO,
	dac_spi_ext_MOSI,
	dac_spi_ext_SCLK,
	dac_spi_ext_SS_n,
	exfifo_if_d_export,
	exfifo_if_rd_export,
	exfifo_if_rdempty_export,
	exfifo_of_d_export,
	exfifo_of_wr_export,
	exfifo_of_wrfull_export,
	exfifo_rst_export,
	flash_spi_MISO,
	flash_spi_MOSI,
	flash_spi_SCLK,
	flash_spi_SS_n,
	fpga_spi_ext_MISO,
	fpga_spi_ext_MOSI,
	fpga_spi_ext_SCLK,
	fpga_spi_ext_SS_n,
	i2c_scl_export,
	i2c_sda_export,
	leds_external_connection_export,
	lms_ctr_gpio_external_connection_export,
	switch_external_connection_export,
	uart_external_connection_rxd,
	uart_external_connection_txd);	

	input		clk_clk;
	input		dac_spi_ext_MISO;
	output		dac_spi_ext_MOSI;
	output		dac_spi_ext_SCLK;
	output		dac_spi_ext_SS_n;
	input	[31:0]	exfifo_if_d_export;
	output		exfifo_if_rd_export;
	input		exfifo_if_rdempty_export;
	output	[31:0]	exfifo_of_d_export;
	output		exfifo_of_wr_export;
	input		exfifo_of_wrfull_export;
	output		exfifo_rst_export;
	input		flash_spi_MISO;
	output		flash_spi_MOSI;
	output		flash_spi_SCLK;
	output		flash_spi_SS_n;
	input		fpga_spi_ext_MISO;
	output		fpga_spi_ext_MOSI;
	output		fpga_spi_ext_SCLK;
	output	[1:0]	fpga_spi_ext_SS_n;
	inout		i2c_scl_export;
	inout		i2c_sda_export;
	output	[7:0]	leds_external_connection_export;
	output	[3:0]	lms_ctr_gpio_external_connection_export;
	input	[7:0]	switch_external_connection_export;
	input		uart_external_connection_rxd;
	output		uart_external_connection_txd;
endmodule
module lms_ctr_onchip_memory2_0 (
                                  // inputs:
                                   address,
                                   byteenable,
                                   chipselect,
                                   clk,
                                   clken,
                                   reset,
                                   reset_req,
                                   write,
                                   writedata,

                                  // outputs:
                                   readdata
                                )
;

  output  [ 31: 0] readdata;
  input   [  9: 0] address;
  input   [  3: 0] byteenable;
  input            chipselect;
  input            clk;
  input            clken;
  input            reset;
  input            reset_req;
  input            write;
  input   [ 31: 0] writedata;

  wire             clocken0;
  wire    [ 31: 0] readdata;
  wire             wren;
  assign wren = chipselect & write;
  assign clocken0 = clken & ~reset_req;
  altsyncram the_altsyncram
    (
      .address_a (address),
      .byteena_a (byteenable),
      .clock0 (clk),
      .clocken0 (clocken0),
      .data_a (writedata),
      .q_a (readdata),
      .wren_a (wren)
    );

  defparam the_altsyncram.byte_size = 8,
           the_altsyncram.init_file = "UNUSED",
           the_altsyncram.lpm_type = "altsyncram",
           the_altsyncram.maximum_depth = 1024,
           the_altsyncram.numwords_a = 1024,
           the_altsyncram.operation_mode = "SINGLE_PORT",
           the_altsyncram.outdata_reg_a = "UNREGISTERED",
           the_altsyncram.ram_block_type = "AUTO",
           the_altsyncram.read_during_write_mode_mixed_ports = "DONT_CARE",
           the_altsyncram.width_a = 32,
           the_altsyncram.width_byteena_a = 4,
           the_altsyncram.widthad_a = 10;

  //s1, which is an e_avalon_slave
  //s2, which is an e_avalon_slave

endmodule
module altera_onchip_flash_address_range_check (
    address,
    is_addr_within_valid_range
);

    parameter FLASH_ADDR_WIDTH = 23;
    parameter MIN_VALID_ADDR = 1;
    parameter MAX_VALID_ADDR = 1;

    input [FLASH_ADDR_WIDTH-1:0] address;
    output is_addr_within_valid_range;
    
    assign is_addr_within_valid_range = (address >= MIN_VALID_ADDR) && (address <= MAX_VALID_ADDR);

endmodule
module altera_onchip_flash_address_write_protection_check (
    use_sector_addr,
    address,
    write_protection_mode,
    is_addr_writable
);

    parameter FLASH_ADDR_WIDTH = 23;
    parameter SECTOR1_START_ADDR = 1;
    parameter SECTOR1_END_ADDR = 1;
    parameter SECTOR2_START_ADDR = 1;
    parameter SECTOR2_END_ADDR = 1;
    parameter SECTOR3_START_ADDR = 1;
    parameter SECTOR3_END_ADDR = 1;
    parameter SECTOR4_START_ADDR = 1;
    parameter SECTOR4_END_ADDR = 1;
    parameter SECTOR5_START_ADDR = 1;
    parameter SECTOR5_END_ADDR = 1;
    parameter SECTOR_READ_PROTECTION_MODE = 5'b11111;

    input use_sector_addr;
    input [FLASH_ADDR_WIDTH-1:0] address;
    input [4:0] write_protection_mode;
    output is_addr_writable;

    wire is_sector1_addr;
    wire is_sector2_addr;
    wire is_sector3_addr;
    wire is_sector4_addr;
    wire is_sector5_addr;    
    wire is_sector1_writable;
    wire is_sector2_writable;
    wire is_sector3_writable;
    wire is_sector4_writable;
    wire is_sector5_writable;
    
    assign is_sector1_addr = (use_sector_addr) ? (address == 1) : ((address >= SECTOR1_START_ADDR) && (address <= SECTOR1_END_ADDR));
    assign is_sector2_addr = (use_sector_addr) ? (address == 2) : ((address >= SECTOR2_START_ADDR) && (address <= SECTOR2_END_ADDR));
    assign is_sector3_addr = (use_sector_addr) ? (address == 3) : ((address >= SECTOR3_START_ADDR) && (address <= SECTOR3_END_ADDR));
    assign is_sector4_addr = (use_sector_addr) ? (address == 4) : ((address >= SECTOR4_START_ADDR) && (address <= SECTOR4_END_ADDR));
    assign is_sector5_addr = (use_sector_addr) ? (address == 5) : ((address >= SECTOR5_START_ADDR) && (address <= SECTOR5_END_ADDR));
    assign is_sector1_writable = ~(write_protection_mode[0] || SECTOR_READ_PROTECTION_MODE[0]);
    assign is_sector2_writable = ~(write_protection_mode[1] || SECTOR_READ_PROTECTION_MODE[1]);
    assign is_sector3_writable = ~(write_protection_mode[2] || SECTOR_READ_PROTECTION_MODE[2]);
    assign is_sector4_writable = ~(write_protection_mode[3] || SECTOR_READ_PROTECTION_MODE[3]);
    assign is_sector5_writable = ~(write_protection_mode[4] || SECTOR_READ_PROTECTION_MODE[4]);
    assign is_addr_writable = ((is_sector1_writable && is_sector1_addr) ||
                               (is_sector2_writable && is_sector2_addr) ||
                               (is_sector3_writable && is_sector3_addr) ||
                               (is_sector4_writable && is_sector4_addr) ||
                               (is_sector5_writable && is_sector5_addr));

endmodule
module altera_onchip_flash_s_address_write_protection_check (
    address,
    is_sector1_writable,
    is_sector2_writable,
    is_sector3_writable,
    is_sector4_writable,
    is_sector5_writable,
    is_addr_writable
);

    input [2:0] address;
    input is_sector1_writable;
    input is_sector2_writable;
    input is_sector3_writable;
    input is_sector4_writable;
    input is_sector5_writable;
    output is_addr_writable;

    wire is_sector1_addr;
    wire is_sector2_addr;
    wire is_sector3_addr;
    wire is_sector4_addr;
    wire is_sector5_addr;

    assign is_sector1_addr = (address == 1);
    assign is_sector2_addr = (address == 2);
    assign is_sector3_addr = (address == 3);
    assign is_sector4_addr = (address == 4);
    assign is_sector5_addr = (address == 5);

    assign is_addr_writable = ((is_sector1_writable && is_sector1_addr) ||
                               (is_sector2_writable && is_sector2_addr) ||
                               (is_sector3_writable && is_sector3_addr) ||
                               (is_sector4_writable && is_sector4_addr) ||
                               (is_sector5_writable && is_sector5_addr));

endmodule
module altera_onchip_flash_a_address_write_protection_check (
    address,
    is_sector1_writable,
    is_sector2_writable,
    is_sector3_writable,
    is_sector4_writable,
    is_sector5_writable,
    is_addr_writable
);

    parameter FLASH_ADDR_WIDTH = 23;
    parameter SECTOR1_START_ADDR = 1;
    parameter SECTOR1_END_ADDR = 1;
    parameter SECTOR2_START_ADDR = 1;
    parameter SECTOR2_END_ADDR = 1;
    parameter SECTOR3_START_ADDR = 1;
    parameter SECTOR3_END_ADDR = 1;
    parameter SECTOR4_START_ADDR = 1;
    parameter SECTOR4_END_ADDR = 1;
    parameter SECTOR5_START_ADDR = 1;
    parameter SECTOR5_END_ADDR = 1;

    input [FLASH_ADDR_WIDTH-1:0] address;
    input is_sector1_writable;
    input is_sector2_writable;
    input is_sector3_writable;
    input is_sector4_writable;
    input is_sector5_writable;
    output is_addr_writable;

    wire is_sector1_addr;
    wire is_sector2_addr;
    wire is_sector3_addr;
    wire is_sector4_addr;
    wire is_sector5_addr;

    assign is_sector1_addr = ((address >= SECTOR1_START_ADDR) && (address <= SECTOR1_END_ADDR));
    assign is_sector2_addr = ((address >= SECTOR2_START_ADDR) && (address <= SECTOR2_END_ADDR));
    assign is_sector3_addr = ((address >= SECTOR3_START_ADDR) && (address <= SECTOR3_END_ADDR));
    assign is_sector4_addr = ((address >= SECTOR4_START_ADDR) && (address <= SECTOR4_END_ADDR));
    assign is_sector5_addr = ((address >= SECTOR5_START_ADDR) && (address <= SECTOR5_END_ADDR));

    assign is_addr_writable = ((is_sector1_writable && is_sector1_addr) ||
                               (is_sector2_writable && is_sector2_addr) ||
                               (is_sector3_writable && is_sector3_addr) ||
                               (is_sector4_writable && is_sector4_addr) ||
                               (is_sector5_writable && is_sector5_addr));

endmodule
module altera_onchip_flash_convert_address (
    address,
    flash_addr
);

    parameter FLASH_ADDR_WIDTH = 23;
    parameter ADDR_RANGE1_END_ADDR = 1;
    parameter ADDR_RANGE1_OFFSET = 1;
    parameter ADDR_RANGE2_OFFSET = 1;

    input [FLASH_ADDR_WIDTH-1:0] address;
    output [FLASH_ADDR_WIDTH-1:0] flash_addr;

    assign flash_addr = (address <= ADDR_RANGE1_END_ADDR[FLASH_ADDR_WIDTH-1:0]) ? 
        (address + ADDR_RANGE1_OFFSET[FLASH_ADDR_WIDTH-1:0]) : 
        (address + ADDR_RANGE2_OFFSET[FLASH_ADDR_WIDTH-1:0]);
    
endmodule
module altera_onchip_flash_convert_sector (
    sector,
    flash_sector
);

    parameter SECTOR1_MAP = 1;
    parameter SECTOR2_MAP = 1;
    parameter SECTOR3_MAP = 1;
    parameter SECTOR4_MAP = 1;
    parameter SECTOR5_MAP = 1;

    input [2:0] sector;
    output [2:0] flash_sector;

    assign flash_sector = 
        (sector == 1) ? SECTOR1_MAP[2:0] :
        (sector == 2) ? SECTOR2_MAP[2:0] :
        (sector == 3) ? SECTOR3_MAP[2:0] :
        (sector == 4) ? SECTOR4_MAP[2:0] :
        (sector == 5) ? SECTOR5_MAP[2:0] :
        3'd0; // Set to 0 for invalid sector ID

endmodule
module altera_onchip_flash_counter (
    clock,
    reset,
    count
);
    input clock;
    input reset;
    output [4:0] count;
    
    reg [4:0] count_reg;
    
    assign count = count_reg;

    initial begin
        count_reg = 0;
    end
    
    always @ (posedge reset or posedge clock) begin
        if (reset) begin
            count_reg <= 0;
        end
        else begin
            count_reg <= count_reg + 5'd1;
        end
    end

endmodule
module lms_ctr_sysid_qsys_0 (
               // inputs:
                address,
                clock,
                reset_n,

               // outputs:
                readdata
             )
;

  output  [ 31: 0] readdata;
  input            address;
  input            clock;
  input            reset_n;

  wire    [ 31: 0] readdata;
  //control_slave, which is an e_avalon_slave
  assign readdata = address ? 1661603672 : 4920;

endmodule
module lms_ctr_leds (
                      // inputs:
                       address,
                       chipselect,
                       clk,
                       reset_n,
                       write_n,
                       writedata,

                      // outputs:
                       out_port,
                       readdata
                    )
;

  output  [  7: 0] out_port;
  output  [ 31: 0] readdata;
  input   [  1: 0] address;
  input            chipselect;
  input            clk;
  input            reset_n;
  input            write_n;
  input   [ 31: 0] writedata;

  wire             clk_en;
  reg     [  7: 0] data_out;
  wire    [  7: 0] out_port;
  wire    [  7: 0] read_mux_out;
  wire    [ 31: 0] readdata;
  assign clk_en = 1;
  //s1, which is an e_avalon_slave
  assign read_mux_out = {8 {(address == 0)}} & data_out;
  always @(posedge clk or negedge reset_n)
    begin
      if (reset_n == 0)
          data_out <= 0;
      else if (chipselect && ~write_n && (address == 0))
          data_out <= writedata[7 : 0];
    end


  assign readdata = {32'b0 | read_mux_out};
  assign out_port = data_out;

endmodule
module altera_dual_boot
(
	clk,
	nreset,
	avmm_rcv_address,
	avmm_rcv_writedata,
	avmm_rcv_write,
	avmm_rcv_read,
	avmm_rcv_readdata
);
	parameter LPM_TYPE = "ALTERA_DUAL_BOOT";
	parameter INTENDED_DEVICE_FAMILY = "MAX 10 FPGA";
	parameter A_WIDTH = 3;
	parameter WD_WIDTH = 4;
	parameter RD_WIDTH = 17;
	parameter MAX_DATA_WIDTH = 32;
	parameter CONFIG_CYCLE = 28;	
	parameter RESET_TIMER_CYCLE = 40;
	
	input clk;
	input nreset;
	input [A_WIDTH-1:0] avmm_rcv_address;
	input [MAX_DATA_WIDTH-1:0] avmm_rcv_writedata;
	input avmm_rcv_write;
	input avmm_rcv_read;
	output [MAX_DATA_WIDTH-1:0] avmm_rcv_readdata;
	
	alt_dual_boot_avmm alt_dual_boot_avmm_comp
	(
		.clk(clk),
		.nreset(nreset),
		.avmm_rcv_address(avmm_rcv_address),
		.avmm_rcv_writedata(avmm_rcv_writedata),
		.avmm_rcv_write(avmm_rcv_write),
		.avmm_rcv_read(avmm_rcv_read),
		.avmm_rcv_readdata(avmm_rcv_readdata)
	);
	defparam
		alt_dual_boot_avmm_comp.LPM_TYPE = LPM_TYPE,
		alt_dual_boot_avmm_comp.INTENDED_DEVICE_FAMILY = INTENDED_DEVICE_FAMILY,
		alt_dual_boot_avmm_comp.A_WIDTH = A_WIDTH,
		alt_dual_boot_avmm_comp.MAX_DATA_WIDTH = MAX_DATA_WIDTH,
		alt_dual_boot_avmm_comp.WD_WIDTH = WD_WIDTH,
		alt_dual_boot_avmm_comp.RD_WIDTH = RD_WIDTH,
		alt_dual_boot_avmm_comp.CONFIG_CYCLE = CONFIG_CYCLE,
		alt_dual_boot_avmm_comp.RESET_TIMER_CYCLE = RESET_TIMER_CYCLE;
	
endmodule
module lms_ctr_switch (
                        // inputs:
                         address,
                         clk,
                         in_port,
                         reset_n,

                        // outputs:
                         readdata
                      )
;

  output  [ 31: 0] readdata;
  input   [  1: 0] address;
  input            clk;
  input   [  7: 0] in_port;
  input            reset_n;

  wire             clk_en;
  wire    [  7: 0] data_in;
  wire    [  7: 0] read_mux_out;
  reg     [ 31: 0] readdata;
  assign clk_en = 1;
  //s1, which is an e_avalon_slave
  assign read_mux_out = {8 {(address == 0)}} & data_in;
  always @(posedge clk or negedge reset_n)
    begin
      if (reset_n == 0)
          readdata <= 0;
      else if (clk_en)
          readdata <= {32'b0 | read_mux_out};
    end


  assign data_in = in_port;

endmodule
module bitswap_qsys (
                      // inputs:
                       dataa,
                       datab,

                      // outputs:
                       result
                    )
;

  output  [ 31: 0] result;
  input   [ 31: 0] dataa;
  input   [ 31: 0] datab;

  wire    [ 31: 0] result;
  //s1, which is an e_custom_instruction_slave
  assign result[31] = dataa[0];
  assign result[30] = dataa[1];
  assign result[29] = dataa[2];
  assign result[28] = dataa[3];
  assign result[27] = dataa[4];
  assign result[26] = dataa[5];
  assign result[25] = dataa[6];
  assign result[24] = dataa[7];
  assign result[23] = dataa[8];
  assign result[22] = dataa[9];
  assign result[21] = dataa[10];
  assign result[20] = dataa[11];
  assign result[19] = dataa[12];
  assign result[18] = dataa[13];
  assign result[17] = dataa[14];
  assign result[16] = dataa[15];
  assign result[15] = dataa[16];
  assign result[14] = dataa[17];
  assign result[13] = dataa[18];
  assign result[12] = dataa[19];
  assign result[11] = dataa[20];
  assign result[10] = dataa[21];
  assign result[9] = dataa[22];
  assign result[8] = dataa[23];
  assign result[7] = dataa[24];
  assign result[6] = dataa[25];
  assign result[5] = dataa[26];
  assign result[4] = dataa[27];
  assign result[3] = dataa[28];
  assign result[2] = dataa[29];
  assign result[1] = dataa[30];
  assign result[0] = dataa[31];

endmodule
module i2c_opencores
(
	wb_clk_i, wb_rst_i, wb_adr_i, wb_dat_i, wb_dat_o,
	wb_we_i, wb_stb_i, /*wb_cyc_i,*/ wb_ack_o, wb_inta_o,
	scl_pad_io, sda_pad_io
);


// Common bus signals
input        wb_clk_i;		// WISHBONE clock
input        wb_rst_i;		// WISHBONE reset

// Slave signals
input  [2:0] wb_adr_i;		// WISHBONE address input
input  [7:0] wb_dat_i;		// WISHBONE data input
output [7:0] wb_dat_o;		// WISHBONE data output
input        wb_we_i;		// WISHBONE write enable input
input        wb_stb_i;		// WISHBONE strobe input
//input        wb_cyc_i;		// WISHBONE cycle input
output       wb_ack_o;		// WISHBONE acknowledge output
output       wb_inta_o; 	// WISHBONE interrupt output

// I2C signals
inout        scl_pad_io;	// I2C clock io
inout        sda_pad_io;	// I2C data io

wire        wb_cyc_i;		// WISHBONE cycle input
// Wire tri-state scl/sda
wire scl_pad_i;
wire scl_pad_o;
wire scl_pad_io;
wire scl_padoen_o;

assign wb_cyc_i = wb_stb_i;
assign scl_pad_i = scl_pad_io;
assign scl_pad_io = scl_padoen_o ? 1'bZ : scl_pad_o;

wire sda_pad_i;
wire sda_pad_o;
wire sda_pad_io;
wire sda_padoen_o;

assign sda_pad_i = sda_pad_io;
assign sda_pad_io = sda_padoen_o ? 1'bZ : sda_pad_o;

// Avalon doesn't have an asynchronous reset
//  set it to be inactive and just use synchronous reset
//  reset level is a parameter, 0 is the default (active-low reset)
wire arst_i;

assign arst_i = 1'b1;

// Connect the top level I2C core
i2c_master_top i2c_master_top_inst
(
	.wb_clk_i(wb_clk_i), .wb_rst_i(wb_rst_i), .arst_i(arst_i),
	
	.wb_adr_i(wb_adr_i), .wb_dat_i(wb_dat_i), .wb_dat_o(wb_dat_o),
	.wb_we_i(wb_we_i), .wb_stb_i(wb_stb_i), .wb_cyc_i(wb_cyc_i),
	.wb_ack_o(wb_ack_o), .wb_inta_o(wb_inta_o),
	
	.scl_pad_i(scl_pad_i), .scl_pad_o(scl_pad_o), .scl_padoen_o(scl_padoen_o),
	.sda_pad_i(sda_pad_i), .sda_pad_o(sda_pad_o), .sda_padoen_o(sda_padoen_o)
);

endmodule
module lms_ctr_uart_rx_stimulus_source (
                                         // inputs:
                                          baud_divisor,
                                          clk,
                                          clk_en,
                                          reset_n,
                                          rx_char_ready,
                                          rxd,

                                         // outputs:
                                          source_rxd
                                       )
;

  output           source_rxd;
  input   [  8: 0] baud_divisor;
  input            clk;
  input            clk_en;
  input            reset_n;
  input            rx_char_ready;
  input            rxd;

  reg     [  7: 0] d1_stim_data;
  reg              delayed_unxrx_char_readyxx0;
  wire             do_send_stim_data;
  wire             pickup_pulse;
  wire             source_rxd;
  wire    [  7: 0] stim_data;
  wire             unused_empty;
  wire             unused_overrun;
  wire             unused_ready;

//synthesis translate_off
//////////////// SIMULATION-ONLY CONTENTS
  //stimulus_transmitter, which is an e_instance
  lms_ctr_uart_tx stimulus_transmitter
    (
      .baud_divisor     (baud_divisor),
      .begintransfer    (do_send_stim_data),
      .clk              (clk),
      .clk_en           (clk_en),
      .do_force_break   (1'b0),
      .reset_n          (reset_n),
      .status_wr_strobe (1'b0),
      .tx_data          (d1_stim_data),
      .tx_overrun       (unused_overrun),
      .tx_ready         (unused_ready),
      .tx_shift_empty   (unused_empty),
      .tx_wr_strobe     (1'b1),
      .txd              (source_rxd)
    );

  always @(posedge clk or negedge reset_n)
    begin
      if (reset_n == 0)
          d1_stim_data <= 0;
      else if (do_send_stim_data)
          d1_stim_data <= stim_data;
    end


  assign stim_data = 8'b0;
  //delayed_unxrx_char_readyxx0, which is an e_register
  always @(posedge clk or negedge reset_n)
    begin
      if (reset_n == 0)
          delayed_unxrx_char_readyxx0 <= 0;
      else if (clk_en)
          delayed_unxrx_char_readyxx0 <= rx_char_ready;
    end


  assign pickup_pulse = ~(rx_char_ready) &  (delayed_unxrx_char_readyxx0);
  assign do_send_stim_data = (pickup_pulse || 1'b0) && 1'b0;

//////////////// END SIMULATION-ONLY CONTENTS

//synthesis translate_on
//synthesis read_comments_as_HDL on
//  assign source_rxd = rxd;
//synthesis read_comments_as_HDL off

endmodule
module lms_ctr_lms_ctr_gpio (
                              // inputs:
                               address,
                               chipselect,
                               clk,
                               reset_n,
                               write_n,
                               writedata,

                              // outputs:
                               out_port,
                               readdata
                            )
;

  output  [  3: 0] out_port;
  output  [ 31: 0] readdata;
  input   [  2: 0] address;
  input            chipselect;
  input            clk;
  input            reset_n;
  input            write_n;
  input   [ 31: 0] writedata;

  wire             clk_en;
  reg     [  3: 0] data_out;
  wire    [  3: 0] out_port;
  wire    [  3: 0] read_mux_out;
  wire    [ 31: 0] readdata;
  wire             wr_strobe;
  assign clk_en = 1;
  //s1, which is an e_avalon_slave
  assign read_mux_out = {4 {(address == 0)}} & data_out;
  assign wr_strobe = chipselect && ~write_n;
  always @(posedge clk or negedge reset_n)
    begin
      if (reset_n == 0)
          data_out <= 3;
      else if (clk_en)
          if (wr_strobe)
              data_out <= (address == 5)? data_out & ~writedata[3 : 0]: (address == 4)? data_out | writedata[3 : 0]: (address == 0)? writedata[3 : 0]: data_out;
    end


  assign readdata = {32'b0 | read_mux_out};
  assign out_port = data_out;

endmodule
module  clkctrl_altclkctrl_0_sub
	( 
	ena,
	inclk,
	outclk) /* synthesis synthesis_clearbox=1 */;
	input   ena;
	input   [3:0]  inclk;
	output   outclk;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1   ena;
	tri0   [3:0]  inclk;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire  wire_clkctrl1_outclk;
	wire [1:0]  clkselect;
	wire  [1:0]  clkselect_wire;
	wire  [3:0]  inclk_wire;

	fiftyfivenm_clkctrl   clkctrl1
	( 
	.clkselect(clkselect_wire),
	.ena(ena),
	.inclk(inclk_wire),
	.outclk(wire_clkctrl1_outclk)
	// synopsys translate_off
	,
	.devclrn(1'b1),
	.devpor(1'b1)
	// synopsys translate_on
	);
	defparam
		clkctrl1.clock_type = "Global Clock",
		clkctrl1.ena_register_mode = "falling edge",
		clkctrl1.lpm_type = "fiftyfivenm_clkctrl";
	assign
		clkselect = {2{1'b0}},
		clkselect_wire = {clkselect},
		inclk_wire = {inclk},
		outclk = wire_clkctrl1_outclk;
endmodule //clkctrl_altclkctrl_0_sub
module  clkctrl_altclkctrl_0  (
    ena,
    inclk,
    outclk);

    input    ena;
    input    inclk;
    output   outclk;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
    tri1     ena;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

    wire  sub_wire0;
    wire  outclk;
    wire  sub_wire1;
    wire [3:0] sub_wire2;
    wire [2:0] sub_wire3;

    assign  outclk = sub_wire0;
    assign  sub_wire1 = inclk;
    assign sub_wire2[3:0] = {sub_wire3, sub_wire1};
    assign sub_wire3[2:0] = 3'h0;

    clkctrl_altclkctrl_0_sub  clkctrl_altclkctrl_0_sub_component (
                .ena (ena),
                .inclk (sub_wire2),
                .outclk (sub_wire0));

endmodule
module factory (
	bridge_0_address,
	bridge_0_byte_enable,
	bridge_0_read,
	bridge_0_write,
	bridge_0_write_data,
	bridge_0_acknowledge,
	bridge_0_read_data,
	clk_clk,
	extfifo_of_d,
	extfifo_of_wr,
	extfifo_of_wrfull,
	extfifo_if_d,
	extfifo_if_rd,
	extfifo_if_rdempty,
	extfifo_fifo_rst,
	pio_0_export,
	reset_reset_n,
	scl_export,
	sda_export);	

	input	[20:0]	bridge_0_address;
	input	[3:0]	bridge_0_byte_enable;
	input		bridge_0_read;
	input		bridge_0_write;
	input	[31:0]	bridge_0_write_data;
	output		bridge_0_acknowledge;
	output	[31:0]	bridge_0_read_data;
	input		clk_clk;
	output	[31:0]	extfifo_of_d;
	output		extfifo_of_wr;
	input		extfifo_of_wrfull;
	input	[31:0]	extfifo_if_d;
	output		extfifo_if_rd;
	input		extfifo_if_rdempty;
	output		extfifo_fifo_rst;
	output	[7:0]	pio_0_export;
	input		reset_reset_n;
	inout		scl_export;
	inout		sda_export;
endmodule
module factory_pio_0 (
                       // inputs:
                        address,
                        chipselect,
                        clk,
                        reset_n,
                        write_n,
                        writedata,

                       // outputs:
                        out_port,
                        readdata
                     )
;

  output  [  7: 0] out_port;
  output  [ 31: 0] readdata;
  input   [  2: 0] address;
  input            chipselect;
  input            clk;
  input            reset_n;
  input            write_n;
  input   [ 31: 0] writedata;


wire             clk_en;
reg     [  7: 0] data_out;
wire    [  7: 0] out_port;
wire    [  7: 0] read_mux_out;
wire    [ 31: 0] readdata;
wire             wr_strobe;
  assign clk_en = 1;
  //s1, which is an e_avalon_slave
  assign read_mux_out = {8 {(address == 0)}} & data_out;
  assign wr_strobe = chipselect && ~write_n;
  always @(posedge clk or negedge reset_n)
    begin
      if (reset_n == 0)
          data_out <= 0;
      else if (clk_en)
          if (wr_strobe)
              data_out <= (address == 5)? data_out & ~writedata[7 : 0]: (address == 4)? data_out | writedata[7 : 0]: (address == 0)? writedata[7 : 0]: data_out;
    end


  assign readdata = {32'b0 | read_mux_out};
  assign out_port = data_out;

endmodule
module addsub8 (
   a,
   b,
   q,
   sub,
   cin,
   cout
);
 

input   [7:0] a; 
input   [7:0] b; 
output  [7:0] q; 
input   sub; 
input   cin; 
output  cout; 

wire    [7:0] q; 
wire    cout; 
wire    [8:0] A_i; 
wire    [8:0] B_i; 
wire    [8:0] Full_Carry; 
wire    [8:0] Res_i; 

assign B_i[8] = 1'b 0; 
assign B_i[7:0] = sub === 1'b 1 ? ~b : b; 
assign A_i[8] = 1'b 0; 
assign A_i[7:0] = a; 
assign Full_Carry[8:1] = 8'b 00000000; 
assign Full_Carry[0] = cin; 
assign Res_i = A_i + B_i + Full_Carry; 
assign cout = Res_i[8]; 
assign q = Res_i[7:0]; 

endmodule // module addsub8
module tb (
`ifdef VERILATOR
	input clk
`endif
);
`ifndef VERILATOR
	reg clk = 1;
	always #10 clk = ~clk;
`endif

	reg resetn = 0;
	integer resetn_cnt = 0;

	reg uresetn = 0;
	integer uresetn_cnt = 0;

	integer cycle = 0;

	wire trap;

	initial begin
		$write("\nRISC-V Soft CPU Contest 2018\n");
		$write("Engine-V Contest entry by MicroFPGA UG\n");
		$write("Verilator testbench: MF8A18 booting from SPI Flash\n\n");

		$write("[TESTBENCH_BEGIN]\n");
	end

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

	always @(posedge clk) begin
		if (resetn_cnt < 200)
			resetn_cnt <= resetn_cnt + 1;
		else
			resetn <= 1;
	end

	wire UART_RX_wire;
	wire [7:0] UART_rx_byte;
	wire UART_rx_rdy;
	wire uart_baud_4x;

	wire 	FLASH_MISO;
	wire 	FLASH_MOSI;
	wire 	FLASH_SCK;
	wire 	FLASH_CS;

	MF8A18_SoC soc (
		.clk		(clk),
		.resetn		(resetn),
		.FLASH_MISO	(FLASH_MISO),
		.FLASH_MOSI	(FLASH_MOSI),
		.FLASH_SCK	(FLASH_SCK),
		.FLASH_CS	(FLASH_CS),
		.UART_TXD       (UART_RX_wire)
	);

	spiflash flash (
		.csb		(FLASH_CS),
		.clk		(FLASH_SCK),
		.io0		(FLASH_MOSI),
		.io1		(FLASH_MISO),
		.io2		(1'b 1),
		.io3		(1'b 1)
	);


	baudgen baud115200 (
		.clk		(clk),
		.tick           (uart_baud_4x)
	);

	rx uart_rx_inst (
		.res_n		(uresetn),
		.rx		(UART_RX_wire),
		.clk		(uart_baud_4x),		 /* Baud Rate x 4 (4 posedge's per bit) */
		.rx_byte	(UART_rx_byte),
		.rdy		(UART_rx_rdy)
	);

	always @(posedge clk) begin
		if (cycle > 5*50*1000000) begin
//		if (cycle > 1000) begin
			$display("Finished after about 5 seconds run time...\n\r");
			$finish;			
		end
	end

	always @(posedge uart_baud_4x) begin
		if (uresetn_cnt < 2)
			uresetn_cnt <= uresetn_cnt + 1;
		else
			uresetn <= 1;

		if (UART_rx_rdy) begin
			if (UART_rx_byte == 8'hff) begin
				$write("[TESTBENCH_END]\n\n");
				$write("RV32I Compliance test Halt");
				$finish;
			end else
				$write("%c", UART_rx_byte);
		end
	end



endmodule
module rx (
  input         res_n,
  input         rx,
  input         clk, /* Baud Rate x 4 (4 posedge's per bit) */
  output  [7:0] rx_byte,
  output        rdy
);

/* Count to 32 (8 bits x 4 samples )*/
reg       [4:0] count;
reg       [2:0] state;
reg       [2:0] state_nxt;

reg       [2:0] rx_shifter;
reg       [7:0] rx_byte_ff;
wire            rx_sample;

localparam WAIT = 3'b000,
           SNS1 = 3'b100,
           SNS2 = 3'b101,
           SNS3 = 3'b110,
           SNSX = 3'b111,
           READ = 3'b001,
           DONE = 3'b010;

/* When sampling RX if we got 2 highs in a row our sample 
   is high! */
assign rx_sample = (rx_shifter[2] && rx_shifter[1]) || 
                   (rx_shifter[1] && rx_shifter[0]);

assign rx_byte = rx_byte_ff;
assign rdy = state == DONE;

/* FSM Next State Derivation */
always @ (*)
begin
  case (state)
    WAIT: if (!rx)  /* As long was we are high stay waiting */
        state_nxt = SNS1;
      else          
        state_nxt = WAIT;
    SNS1: if (!rx)
        state_nxt = SNS2;
      else
        state_nxt = WAIT;
    SNS2: if (!rx)  /* If we get 4 lows in a row we got to read */
        state_nxt = SNSX;
      else
        state_nxt = WAIT;
    SNSX:
      state_nxt = READ;
    READ: if (count == 5'b11111) /* When read count is full, go back to wait */
        state_nxt = DONE;
      else
        state_nxt = READ;
    DONE:    state_nxt = WAIT;
    default: state_nxt = WAIT;
  endcase
end

/* Sense the start bit on posedge and negedge */
always @ (posedge clk or negedge res_n)
begin
   if (!res_n) 
    begin
      state <= WAIT;
      count <= 5'd0;
      rx_shifter <= 3'd0;
    end
   else
    begin
      state <= state_nxt;
      if (state == READ) begin
        rx_shifter <= {rx, rx_shifter[2:1]};
        count <= count + 1'b1;
      end
      else 
      begin
        rx_shifter <= 3'd0;
        count <= 5'd0;
      end
    end
end

/* If we are reading, stample the RX bits 
   every 3 samples shift it into RX byte */
always @ (posedge clk or negedge res_n)
begin
   if (!res_n) 
      rx_byte_ff <= 8'd0;
   else
     if ((state == READ) && count[1] && count[0])  /* When we are at count 3, sample the shift register */
       rx_byte_ff <= {rx_sample, rx_byte_ff[7:1]};
     else 
       rx_byte_ff <= rx_byte_ff;
end

endmodule
module MF8A18_SoC (
	clk,
	resetn,
	FLASH_SCK,
	FLASH_CS,
	FLASH_MISO,
	FLASH_MOSI,
	UART_TXD
	);

	output FLASH_SCK;
	output FLASH_CS;
	input FLASH_MISO;
	output FLASH_MOSI;

	input clk;
	input resetn;	
	output UART_TXD;

	wire [9:0] rom_addr;
	wire [15:0] rom_data;
	
	wire [15:0] maddr;
	wire [7:0]  mwdata;
	wire [7:0]  mrdata;
	wire        mwrite;

	MF8A18 cpu (
		.CLK		(clk),
        	.RSTn		(resetn),
	        .SPI_CS		(FLASH_CS),
	        .SPI_MISO	(FLASH_MISO),
	        .SPI_MOSI	(FLASH_MOSI),
	        .SPI_SCK	(FLASH_SCK),
	        .UART_TXD	(UART_TXD),
	        .maddr		(maddr),
	        .mread		(),
	        .mwdata		(mwdata),
	        .mwrite		(mwrite),
	        .ramdata	(mrdata),
	        .rom_addr	(rom_addr),
	        .rom_data	(rom_data)
	);

	ROM1K16 rom (
		.addr		(rom_addr),
	        .clk		(clk),
        	.dout		(rom_data)
	);

	RAM32K ram (
		.addr		(maddr[14:0]),
	        .clk		(clk),
        	.din		(mwdata),
	        .dout		(mrdata),
	        .we		(mwrite)
	);

endmodule
module MF8A18 (
   CLK,
   RSTn,
   rom_addr,
   rom_data,
   maddr,
   mwdata,
   ramdata,
   mwrite,
   mread,
   SPI_MISO,
   SPI_MOSI,
   SPI_SCK,
   SPI_CS,
   UART_TXD);
 

input   CLK; 
input   RSTn; 
output   [9:0] rom_addr; 
input   [15:0] rom_data; 
output   [15:0] maddr; 
output   [7:0] mwdata; 
input   [7:0] ramdata; 
output   mwrite; 
output   mread; 
input   SPI_MISO; 
output   SPI_MOSI; 
output   SPI_SCK; 
output   SPI_CS; 
output   UART_TXD; 


// 
wire    [9:0] rom_addr; 
wire    [15:0] maddr; 
wire    [7:0] mwdata; 
wire    mwrite; 
wire    mread; 
reg     SPI_MOSI; 
reg     SPI_SCK; 
reg     SPI_CS; 
reg     UART_TXD; 
reg     Reset_s_n; 
wire    Reset_s_n_i; 
wire    IO_Rd; 
wire    IO_Wr; 
wire    [5:0] IO_Addr; 
wire    [7:0] IO_WData; 
wire    [7:0] IO_RData; 

wire    [15:0] Z; 
wire    [7:0] ram_datain; 
wire    ram_write; 

wire    [15:0] maddr_i; 
wire    [15:0] maddr_s; 
wire    mread_i; 
wire    mwrite_i; 

assign maddr = maddr_i; 
assign mread = mread_i; 
assign mwrite = mwrite_i; 

always @(posedge CLK)
begin : process_1
	Reset_s_n <= RSTn;   
end

always @(posedge CLK or negedge Reset_s_n)
begin : process_2
	if (Reset_s_n === 1'b 0)
	begin
		UART_TXD <= 1'b 1;   
		SPI_CS   <= 1'b 1;   
		SPI_SCK  <= 1'b 1;   
		SPI_MOSI <= 1'b 1;   
	end else
	begin
	if (IO_Wr === 1'b 1)
	begin
        	if (IO_Addr[4:3] === 2'b 00) begin  UART_TXD <= IO_WData[0]; end //  00 xxxxx 0x20
		if (IO_Addr[4:3] === 2'b 01) begin  SPI_CS <= IO_WData[7];   end //  01 xxxx 0x10
		if (IO_Addr[4:3] === 2'b 10) begin  SPI_SCK <= IO_WData[0];  end //  11 xxxx 0x20
		if (IO_Addr[4:3] === 2'b 11) begin  SPI_MOSI <= IO_WData[7]; end //  10 xxxx 0x30
         end
      end
 end

assign mwdata = IO_WData; 

mf8_core core (
	.Clk		(CLK),
        .Reset_n	(Reset_s_n),
        .ROM_Addr	(rom_addr[9:0]),
        .ROM_Data	(rom_data),
        .ZZ		(maddr_i),
        .ram_datain	(ramdata),
        .ram_write	(mwrite_i),
        .ram_read	(mread_i),
        .IO_Rd		(IO_Rd),
        .IO_Wr		(IO_Wr),
        .IO_Addr	(IO_Addr),
        .IO_RData	(IO_RData),
        .IO_WData	(IO_WData)
);

assign IO_RData = {7'b 0000000, SPI_MISO}; 

endmodule //
module ROM1K16 (
	clk,
	addr,
	dout
);

input           clk;        
input [9:0]    addr;
output [15:0]  dout;

/*
 * Generic and simulator friendly memory
 */    

	reg [15:0] memory [0:2*1024-1];
	reg [15:0] memory_r;
	initial $readmemh("rv32i.mem", memory);

	assign dout =  memory_r;
    
	always @(posedge clk) begin
		memory_r <= memory[addr];
//		$write("\n\rROM: %04X", addr);
	end


endmodule
module mf8_pcs(Clk, Reset_n, Offs_In, Pause, RJmp, NPC, PC);
	input	Clk;
	input	Reset_n;
	input	[11:0]	Offs_In;
	input	Pause;
	input	RJmp;
	output	[11:0]	NPC;
	output	[11:0]	PC;

	reg 	[11:0]	PC_i;
	wire	[11:0]	NPC_i;
	wire	[11:0]	inc_or_nop;
	wire	[11:0]	real_offset;


	assign	NPC	= NPC_i;
	assign	PC	= PC_i;

	assign	inc_or_nop	= {11'b00000000000, ( ~Pause)};
	assign	real_offset	= (RJmp == 1'b0) ? (inc_or_nop)	: (Offs_In);
	assign	NPC_i	= PC_i + real_offset;

	always @(posedge Clk or negedge Reset_n) begin
		if (Reset_n == 1'b0) begin
			PC_i	<= 12'b000000000000;
		end else begin
			PC_i	<= NPC_i;
		end
	end
endmodule
module mf8_reg(Clk, Reset_n, Wr, Rd_Addr, Rr_Addr, Data_In, Rd_Data, Rr_Data, Z);
	input	Clk;
	input	Reset_n;
	input	Wr;
	input	[4:0]	Rd_Addr;
	input	[4:0]	Rr_Addr;
	input	[7:0]	Data_In;
	output	[7:0]	Rd_Data;
	reg	[7:0]	Rd_Data;
	output	[7:0]	Rr_Data;
	reg	[7:0]	Rr_Data;
	output	[15:0]	Z;
	reg	[15:0]	Z;	

	reg 	[7:0]	RegD	[31:0];
	reg 	[7:0]	RegR	[31:0];
	reg 	[4:0]	Rd_Addr_r;

	always @(posedge Clk) begin
		Rd_Addr_r	<= Rd_Addr;
		Rd_Data	<= RegD[Rd_Addr];
		Rr_Data	<= RegR[Rr_Addr];
		if (Wr == 1'b1) begin
			RegD[Rd_Addr_r]	<= Data_In;
			RegR[Rd_Addr_r]	<= Data_In;
			if (Rd_Addr_r == Rd_Addr) begin
				Rd_Data	<= Data_In;
			end
			if (Rd_Addr_r == Rr_Addr) begin
				Rr_Data	<= Data_In;
			end
			if (Rd_Addr_r == 5'b11110) begin
				Z[7:0]	<= Data_In;
			end
			if (Rd_Addr_r == 5'b11111) begin
				Z[15:8]	<= Data_In;
			end
		end
	end
endmodule
module RAM32K (
	clk,
	addr,
	din,
	dout,
	we
);

input           clk;        
input           we;        
input [14:0]    addr;
input  [7:0]    din;
output [7:0]    dout;


//wire    [13:0]  spram_addr;      
//wire    [15:0]  spram_wr_data;      
//wire    [15:0]  spram_rd_data;      
//wire    [3:0]  spram_mask;      

//assign spram_wr_data[15:8] = din;
//assign spram_wr_data [7:0] = din;
// use word address
//assign spram_addr = addr[14:1];
// assign write masks
//assign spram_mask[0] = ~addr[0];
//assign spram_mask[1] = ~addr[0];
//assign spram_mask[2] =  addr[0];
//assign spram_mask[3] =  addr[0];

// latch lower address
//reg    addr0_s;      
//always @ (posedge clk) begin
//	addr0_s <= addr[0];
//end
// return correct byte depending on latched address !
//assign dout = addr0_s ? spram_rd_data[15:8] : spram_rd_data[7:0];	

// iceCube2..
/*
SB_SPRAM256KA  inst_SPRAM256KA(
     .ADDRESS                 (spram_addr                   ),
     .DATAIN                  (spram_wr_data                ),
     .MASKWREN                (spram_mask                   ),
     .WREN                    (we                           ),
     .CHIPSELECT              (1'b1                         ),
     .CLOCK                   (clk                          ),
     .STANDBY                 (1'b0                         ),
     .SLEEP                   (1'b0                         ),
     .POWEROFF                (1'b1                         ),
     .DATAOUT                 (spram_rd_data                )
); 
*/

// Radiant..
/*
SP256K  inst_SPRAM256KA(
     .AD             (spram_addr                   ),
     .DI             (spram_wr_data                ),
     .MASKWE         (spram_mask                   ),
     .WE             (we                           ),
     .CS             (1'b1                         ),
     .CK             (clk                          ),
     .STDBY          (1'b0                         ),
     .SLEEP          (1'b0                         ),
     .PWROFF_N       (1'b1                         ),
     .DO             (spram_rd_data                )
); 
*/

/*
 * Generic and simulator friendly memory
 */    

	reg [7:0] memory [0:32*1024-1];
	reg [7:0] memory_r;
	initial $readmemh("riscv.mem", memory);

	assign dout =  memory_r;
    
	always @(posedge clk) begin
		if (we) memory[addr] <= din;
		memory_r <= memory[addr];
	end

	always @(posedge clk) begin
		if (we) begin
			if (addr < 40) begin
//				$write("\n\rWR: %04X %02X  ", addr, din);
			end
		end
	end



endmodule
module RAM32KAHB (
   maddr,
   mwdata,
   mrdata,
   mwrite,
   mread,
   mready,
   HADDR,
   HTRANS,
   HWRITE,
   HSIZE,
   HWDATA,
   HSEL,
   HMASTLOCK,
   HREADY_OUT,
   HREADY,
   HRDATA,
   HRESP,
   Clk);
 

input   [15:0] maddr; 
input   [7:0] mwdata; 
output   [7:0] mrdata; 
input   mwrite; 
input   mread; 
output   mready; 
output   [31:0] HADDR; 
output   [1:0] HTRANS; 
output   HWRITE; 
output   [1:0] HSIZE; 
output   [31:0] HWDATA; 
output   HSEL; 
output   HMASTLOCK; 
output   HREADY_OUT; 
input   HREADY; 
input   [31:0] HRDATA; 
input   HRESP; 
input   Clk; 

wire    [7:0] mrdata; 
wire    mready; 
wire    [31:0] HADDR; 
wire    [1:0] HTRANS; 
wire    HWRITE; 
wire    [1:0] HSIZE; 
wire    [31:0] HWDATA; 
wire    HSEL; 
wire    HMASTLOCK; 
wire    HREADY_OUT; 
reg     [7:0] mwdata_s; 

assign HREADY_OUT = HREADY; 
assign mready = HREADY; 

// 
assign HWDATA[31:16] = 16'h 0000; 

//  Latch write DATA 
assign HWDATA[15:8] = mwdata_s; 
assign HWDATA[7:0] = mwdata_s; 

always @(posedge Clk)
   begin : process_1
   mwdata_s <= mwdata;   
   end

assign HSIZE = 2'b 00; 
//  Byte transfers only
assign HSEL = 1'b 1; 
assign HTRANS[0] = 1'b 0; 
assign HTRANS[1] = mread | mwrite; 
assign HWRITE = mwrite; 
assign HADDR[0] = maddr[0]; 
assign HADDR[1] = 1'b 0; 
assign HADDR[15:2] = maddr[14:1]; 
assign HADDR[31:16] = 16'h 2000; 
//  eSRAM

//  input mux
assign mrdata = maddr[0] === 1'b 0 ? HRDATA[7:0] : 
	HRDATA[15:8]; 

endmodule // module RAM32KAHB
module proc_sys_sb(
    // Inputs
    CLK0_PAD,
    DEVRST_N,
    FAB_RESET_N,
    FIC_0_AHB_M_HRDATA,
    FIC_0_AHB_M_HREADY,
    FIC_0_AHB_M_HRESP,

    FIC_0_AHB_S_HADDR,
    FIC_0_AHB_S_HMASTLOCK,
    FIC_0_AHB_S_HREADY,
    FIC_0_AHB_S_HSEL,
    FIC_0_AHB_S_HSIZE,
    FIC_0_AHB_S_HTRANS,
    FIC_0_AHB_S_HWDATA,
    FIC_0_AHB_S_HWRITE,

    MMUART_0_RXD_F2M,
    MSS_INT_F2M,
    // Outputs
    FIC_0_AHB_M_HADDR,
    FIC_0_AHB_M_HSIZE,
    FIC_0_AHB_M_HTRANS,
    FIC_0_AHB_M_HWDATA,
    FIC_0_AHB_M_HWRITE,
    
    FIC_0_AHB_S_HRDATA,
    FIC_0_AHB_S_HREADYOUT,
    FIC_0_AHB_S_HRESP,
    
    FIC_0_CLK,
    FIC_0_LOCK,
    GPIO_0_M2F,
    INIT_DONE,
    MMUART_0_TXD_M2F,
    MSS_READY,
    POWER_ON_RESET_N
);

//--------------------------------------------------------------------
// Input
//--------------------------------------------------------------------
input         CLK0_PAD;
input         DEVRST_N;
input         FAB_RESET_N;
input  [31:0] FIC_0_AHB_M_HRDATA;
input         FIC_0_AHB_M_HREADY;
input         FIC_0_AHB_M_HRESP;
input  [31:0] FIC_0_AHB_S_HADDR;
input         FIC_0_AHB_S_HMASTLOCK;
input         FIC_0_AHB_S_HREADY;
input         FIC_0_AHB_S_HSEL;
input  [1:0]  FIC_0_AHB_S_HSIZE;
input  [1:0]  FIC_0_AHB_S_HTRANS;
input  [31:0] FIC_0_AHB_S_HWDATA;
input         FIC_0_AHB_S_HWRITE;
input         MMUART_0_RXD_F2M;
input  [15:0] MSS_INT_F2M;
//--------------------------------------------------------------------
// Output
//--------------------------------------------------------------------
output [31:0] FIC_0_AHB_M_HADDR;
output [1:0]  FIC_0_AHB_M_HSIZE;
output [1:0]  FIC_0_AHB_M_HTRANS;
output [31:0] FIC_0_AHB_M_HWDATA;
output        FIC_0_AHB_M_HWRITE;
output [31:0] FIC_0_AHB_S_HRDATA;
output        FIC_0_AHB_S_HREADYOUT;
output        FIC_0_AHB_S_HRESP;
output        FIC_0_CLK;
output        FIC_0_LOCK;
output        GPIO_0_M2F;
output        INIT_DONE;
output        MMUART_0_TXD_M2F;
output        MSS_READY;
output        POWER_ON_RESET_N;

wire clk;
assign clk = CLK0_PAD;

reg [15:0] maddr;
wire [7:0]  mwdata;
wire [7:0]  mrdata;
reg        mwrite;
  
reg ready_1;
reg ready_2;
reg ready_3;  

wire trans;
assign trans =  FIC_0_AHB_S_HTRANS[1];

always @(posedge clk or posedge trans) begin

    if (trans == 1'b1) begin
        ready_1 <= 1'b0;
        ready_2 <= 1'b0;
        ready_3 <= 1'b0;
    
    end else begin
        ready_1 <= 1'b1;
        ready_2 <= ready_1;
        ready_3 <= ready_2;
    end
    
    // delay 1 clk
    mwrite <= FIC_0_AHB_S_HWRITE;
    
    maddr[0] <= FIC_0_AHB_S_HADDR[0];
    maddr[14:1] <= FIC_0_AHB_S_HADDR[15:2];
end

// just delay transaction a few clocks
assign FIC_0_AHB_S_HREADYOUT = ready_3;
assign FIC_0_AHB_S_HRDATA = {16'h 0000, mrdata, mrdata};

RAM32K ram (
	.addr		(maddr[14:0]),
        .clk		(clk),
       	.din		(FIC_0_AHB_S_HWDATA[7:0]),
        .dout		(mrdata),
        .we	        (mwrite)
	);

endmodule
module tb (
`ifdef VERILATOR
	input clk
`endif
);
`ifndef VERILATOR
	reg clk = 1;
	always #10 clk = ~clk;
`endif

	reg resetn = 0;
	integer resetn_cnt = 0;

	reg uresetn = 0;
	integer uresetn_cnt = 0;

	integer cycle = 0;

	wire trap;

	initial begin
		$write("\nRISC-V Soft CPU Contest 2018\n");
		$write("Engine-V Contest entry by MicroFPGA UG\n");
		$write("Verilator testbench: MF8A18 booting from MSS eSRAM\n\n");

		$write("[TESTBENCH_BEGIN]\n");
	end

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

	always @(posedge clk) begin
		if (resetn_cnt < 200)
			resetn_cnt <= resetn_cnt + 1;
		else
			resetn <= 1;
	end

	wire UART_RX_wire;
	wire [7:0] UART_rx_byte;
	wire UART_rx_rdy;
	wire uart_baud_4x;

	MF8A18_SoC soc (
		.clk		(clk),
		.resetn		(resetn),
		.UART_TXD       (UART_RX_wire)
	);


	baudgen baud115200 (
		.clk		(clk),
		.tick           (uart_baud_4x)
	);

	rx uart_rx_inst (
		.res_n		(uresetn),
		.rx		(UART_RX_wire),
		.clk		(uart_baud_4x),		 /* Baud Rate x 4 (4 posedge's per bit) */
		.rx_byte	(UART_rx_byte),
		.rdy		(UART_rx_rdy)
	);

	always @(posedge clk) begin
		if (cycle > 5*50*1000000) begin
//		if (cycle > 1000) begin
			$display("Finished after about 5 seconds run time...\n\r");
			$finish;			
		end
	end

	always @(posedge uart_baud_4x) begin
		if (uresetn_cnt < 2)
			uresetn_cnt <= uresetn_cnt + 1;
		else
			uresetn <= 1;

		if (UART_rx_rdy) begin
			if (UART_rx_byte == 8'hff) begin
				$write("[TESTBENCH_END]\n\n");
				$write("RV32I Compliance test Halt");
				$finish;
			end else
				$write("%c", UART_rx_byte);
		end
	end



endmodule