dakies/OSS_Verilog huggingface dataset:
module MF8A18_SoC (
	clk,
	resetn,
	UART_TXD
	);

	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;
	wire        mread;
	wire        mready;


	MF8A18 cpu (
		.CLK		(clk),
        	.RSTn		(resetn),
	        .UART_TXD	(UART_TXD),
	        .maddr		(maddr),
	        .mread		(mread),
	        .mwdata		(mwdata),
	        .mwrite		(mwrite),
	        .ramdata	(mrdata),
	        .mready		(mready),
	        .rom_addr	(rom_addr),
	        .rom_data	(rom_data)
	);

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

wire   [31:0] HRDATA;
wire   [31:0] HADDR;

wire          HREADY;
wire   [1:0]  HSIZE;
wire   [1:0]  HTRANS;
wire   [31:0] HWDATA;
wire          HWRITE;


proc_sys_sb proc_sys_sb_0(
        // Inputs
        .FAB_RESET_N           ( 1'b1 ),
        .CLK0_PAD              ( clk ),
        .DEVRST_N              ( resetn ),
        .FIC_0_AHB_S_HWRITE    ( HWRITE ),
        .FIC_0_AHB_S_HSEL      ( ),
        .FIC_0_AHB_S_HMASTLOCK ( ),
        .FIC_0_AHB_S_HREADY    ( ),
        .FIC_0_AHB_M_HREADY    ( 1'b1 ),
        .FIC_0_AHB_M_HRESP     ( 1'b0 ),
        .MMUART_0_RXD_F2M      ( 1'b1 ),
        .MSS_INT_F2M           (  ),
        .FIC_0_AHB_S_HADDR     ( HADDR ),
        .FIC_0_AHB_S_HTRANS    ( HTRANS ),
        .FIC_0_AHB_S_HSIZE     ( HSIZE ),
        .FIC_0_AHB_S_HWDATA    ( HWDATA ),
        .FIC_0_AHB_M_HRDATA    (  ),
        // Outputs
        .POWER_ON_RESET_N      (  ),
        .INIT_DONE             (  ),
        .FIC_0_CLK             (  ),
        .FIC_0_LOCK            (  ),
        .MSS_READY             (  ),
        .FIC_0_AHB_S_HREADYOUT ( HREADY ),
        .FIC_0_AHB_S_HRESP     (  ),
        .FIC_0_AHB_M_HWRITE    (  ),
        .MMUART_0_TXD_M2F      (  ),
        .GPIO_0_M2F            (  ),
        .FIC_0_AHB_S_HRDATA    ( HRDATA ),
        .FIC_0_AHB_M_HADDR     (  ),
        .FIC_0_AHB_M_HTRANS    (  ),
        .FIC_0_AHB_M_HSIZE     ( HSIZE ),
        .FIC_0_AHB_M_HWDATA    (  ) 
        );


RAM32KAHB RAM32KAHB_0(
        // Inputs
        .mwrite     ( mwrite ),
        .mread      ( mread ),
        .HREADY     ( HREADY ),
        .HRESP      ( ),
        .Clk        ( clk ),
        .maddr      ( maddr ),
        .mwdata     ( mwdata ),
        .HRDATA     ( HRDATA ),
        // Outputs
        .mready     ( mready ),
        .HWRITE     ( HWRITE ),
        .HSEL       ( ),
        .HMASTLOCK  ( ),
        .HREADY_OUT (  ),
        .mrdata     ( mrdata ),
        .HADDR      ( HADDR ),
        .HTRANS     ( HTRANS ),
        .HSIZE      ( HSIZE ),
        .HWDATA     ( HWDATA ) 
        );

endmodule
module MF8A18 (
	CLK,
	RSTn,
	rom_addr,
	rom_data,
	maddr,
	mwdata,
	ramdata,
	mwrite,
	mread,
	mready,
	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   mready; 
output   UART_TXD; 


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

reg     UART_TXD; 
reg     Reset_s_n; 
wire    IO_Rd; 
wire    IO_Wr; 
wire    IO_Wr_HR; 
wire    [5:0] IO_Addr; 
wire    [7:0] IO_WData; 
wire    [7:0] IO_RData; 
wire    [15:0] maddr_i; 
wire    mread_i; 
wire    mwrite_i; 

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

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;   
	end else
	begin
		if (IO_Wr === 1'b 1)
		begin
			UART_TXD <= IO_WData[0];   
		end
	end
end

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),
        .ram_ready	(mready),
        .IO_Rd		(IO_Rd),
        .IO_Wr		(IO_Wr),
        .IO_Addr	(IO_Addr),
        .IO_RData	(IO_RData),
        .IO_WData	(IO_WData)
);

assign IO_RData = 8'b 00000000; 

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 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 MF8A18_SoC
   (CLK,
    RSTn,
    FLASH_CS,
    FLASH_MISO,
    FLASH_MOSI,
    FLASH_SCK,
    UART_TXD
	);
	
  
  input CLK;
  input RSTn;
  
  output FLASH_CS;
  input FLASH_MISO;
  output FLASH_MOSI;
  output FLASH_SCK;
  output UART_TXD;

  wire Clk_0_1;
  wire [7:0]RAM32K_0_dout;
  wire RSTn_0_1;
  wire SPI_MISO_0_1;
  wire [15:0]rom1200_0_D;
  wire top_0_DEBUG_LED;
  wire top_0_LED;
  wire top_0_SPI_CS;
  wire top_0_SPI_MOSI;
  wire top_0_SPI_SCK;
  wire top_0_UART_TXD;
  wire [15:0]top_0_maddr;
  wire [7:0]top_0_mwdata;
  wire top_0_mwrite;
  wire [9:0]top_0_rom_addr;

  assign Clk_0_1 = CLK;
  assign RSTn_0_1 = RSTn;
  assign FLASH_CS = top_0_SPI_CS;
  assign SPI_MISO_0_1 = FLASH_MISO;
  assign FLASH_MOSI = top_0_SPI_MOSI;
  assign FLASH_SCK = top_0_SPI_SCK;
  
  assign UART_TXD = top_0_UART_TXD;  
 
	
  RAM32K RAM32K_0	(
		.addr		(top_0_maddr[14:0]),
        .clk		(Clk_0_1),
        .din		(top_0_mwdata),
        .dout		(RAM32K_0_dout),
        .we			(top_0_mwrite));
  
  ROM512K16 mc_rom        (.addr(top_0_rom_addr[8:0]),         .clk(Clk_0_1),         .dout(rom1200_0_D));
		
		
  MF8A18 top_0       (
		.CLK		(Clk_0_1),
        .RSTn		(RSTn_0_1),
        .SPI_CS		(top_0_SPI_CS),
        .SPI_MISO	(SPI_MISO_0_1),
        .SPI_MOSI	(top_0_SPI_MOSI),
        .SPI_SCK	(top_0_SPI_SCK),
        .UART_TXD	(top_0_UART_TXD),
        .maddr		(top_0_maddr),
        .mwdata		(top_0_mwdata),
        .mwrite		(top_0_mwrite),
        .ramdata	(RAM32K_0_dout),
        .rom_addr	(top_0_rom_addr),
        .rom_data	(rom1200_0_D)
		);
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;		// appended automatically by vhdl2verilog.
	output	[7:0]	Rr_Data;
	reg	[7:0]	Rr_Data;		// appended automatically by vhdl2verilog.
	output	[15:0]	Z;
	reg	[15:0]	Z;		// appended automatically by vhdl2verilog.


	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                )
); 
*/
endmodule
module axis_interconnect #(
	parameter CHANNELS_IN = 4,
	parameter CHANNELS_OUT = 1,
	parameter DATA_WIDTH = 8,
	parameter USER_WIDTH = 2
)
(
	input wire aclk,
	input wire aresetn,
	input wire [CHANNELS_IN*DATA_WIDTH-1:0]s_axis_tdata,
	input wire [CHANNELS_IN*$clog2(CHANNELS_OUT)-1:0]s_axis_tdest,
	input wire [CHANNELS_IN*USER_WIDTH-1:0]s_axis_tuser,
	input wire [CHANNELS_IN-1:0]s_axis_tvalid,
	output wire [CHANNELS_IN-1:0]s_axis_tready,
	input wire [CHANNELS_IN-1:0]s_axis_tlast,
	output wire [CHANNELS_OUT*DATA_WIDTH-1:0]m_axis_tdata,
	output wire [CHANNELS_OUT*USER_WIDTH-1:0]m_axis_tuser,
	output wire [CHANNELS_OUT-1:0]m_axis_tvalid,
	input wire [CHANNELS_OUT-1:0]m_axis_tready,
	output wire [CHANNELS_OUT-1:0]m_axis_tlast	
);

genvar g, h;

generate 
	wire [CHANNELS_IN*CHANNELS_OUT-1:0]arb_tready;
	wire [CHANNELS_IN*CHANNELS_OUT-1:0]axis_tready;

	for (g = 0; g < CHANNELS_OUT; g = g + 1) begin : ARBITER
		for (h = 0; h < CHANNELS_IN; h = h + 1) begin
			assign axis_tready[CHANNELS_OUT*h+g+:1] = arb_tready[CHANNELS_IN*g+h+:1];
		end
	
		axis_arbiter #(
			.CHAN_NUM(CHANNELS_IN),
			.DATA_WIDTH(DATA_WIDTH),
			.DEST_INDEX(g),
			.DEST_WIDTH($clog2(CHANNELS_OUT)),
			.USER_WIDTH(USER_WIDTH)
		) axis_arbiter_inst (
			.aclk(aclk),
			.aresetn(aresetn),
			.s_axis_tdata(s_axis_tdata),
			.s_axis_tuser(s_axis_tuser),
			.s_axis_tdest(s_axis_tdest),
			.s_axis_tvalid(s_axis_tvalid),
			.s_axis_tready(arb_tready[CHANNELS_IN*(g+1)-1-:CHANNELS_IN]),
			.s_axis_tlast(s_axis_tlast),
			.m_axis_tdata(m_axis_tdata[DATA_WIDTH*(g+1)-1-:DATA_WIDTH]),
			.m_axis_tuser(m_axis_tuser[USER_WIDTH*(g+1)-1-:USER_WIDTH]),
			.m_axis_tvalid(m_axis_tvalid[g]),
			.m_axis_tready(m_axis_tready[g]),
			.m_axis_tlast(m_axis_tlast[g])
		);
	end 
	for (h = 0; h < CHANNELS_IN; h = h + 1) begin
		assign s_axis_tready[h] = (axis_tready[CHANNELS_OUT*(h+1)-1-:CHANNELS_OUT] != 0);
	end 
endgenerate

endmodule
module axis_arbiter #(
	parameter CHAN_NUM = 4,
	parameter DATA_WIDTH = 8,
	parameter DEST_INDEX = 0,
	parameter DEST_WIDTH = 4,
	parameter USER_WIDTH = 2
)
(
	input wire aclk,
	input wire aresetn,
	input wire [DATA_WIDTH*CHAN_NUM-1:0]s_axis_tdata,
	input wire [USER_WIDTH*CHAN_NUM-1:0]s_axis_tuser,
	input wire [CHAN_NUM*DEST_WIDTH-1:0]s_axis_tdest,
	input wire [CHAN_NUM-1:0]s_axis_tvalid,
	output wire [CHAN_NUM-1:0]s_axis_tready,
	input wire [CHAN_NUM-1:0]s_axis_tlast,
	output wire [DATA_WIDTH-1:0]m_axis_tdata,
	output wire [USER_WIDTH-1:0]m_axis_tuser,
	output wire m_axis_tvalid,
	input wire m_axis_tready,
	output wire m_axis_tlast
);

localparam PTR_WIDTH = $clog2(CHAN_NUM);

reg [PTR_WIDTH-1:0]curr;
reg curr_wrap;
reg [PTR_WIDTH-1:0]next;
reg act;
wire [CHAN_NUM-1:0]axis_tvalid;

integer i,j;
genvar g;

generate for (g = 0; g < CHAN_NUM; g = g + 1) begin
	if (DEST_WIDTH > 0) begin
		wire dest_valid = (s_axis_tdest[DEST_WIDTH*(g+1)-1-:DEST_WIDTH] == DEST_INDEX);
		assign s_axis_tready[g] = (dest_valid ? (curr == g ? m_axis_tready : 1'b0) : 1'b0) & aresetn;
		assign axis_tvalid[g] = (dest_valid ? s_axis_tvalid[g] : 1'b0) & aresetn;
	end else begin
		assign s_axis_tready[g] = (curr == g ? m_axis_tready : 1'b0) & aresetn;
		assign axis_tvalid[g] = s_axis_tvalid[g] & aresetn;
	end
end endgenerate

assign m_axis_tdata = axis_tvalid[curr] ? s_axis_tdata[DATA_WIDTH*(curr+1)-1-:DATA_WIDTH] : 0;
assign m_axis_tuser = axis_tvalid[curr] ? s_axis_tuser[USER_WIDTH*(curr+1)-1-:USER_WIDTH] : 0;
assign m_axis_tvalid = aresetn ? axis_tvalid[curr] : 1'b0;
assign m_axis_tlast = s_axis_tlast[curr] & axis_tvalid[curr];

always @(posedge aclk) begin
	if (aresetn == 1'b0) begin
		act <= 1'b0;
		next <= 0;
	end else begin
		if (act == 1'b0) begin
			if (m_axis_tvalid) begin
				if (m_axis_tready & m_axis_tlast) begin
					act <= 1'b0;
					if (curr == (CHAN_NUM - 1)) begin
						next <= 0;
					end else begin
						next <= curr + 1;
					end
				end else begin
					act <= 1'b1;
					next <= curr;
				end
			end
		end else begin
			if (m_axis_tvalid & m_axis_tready & m_axis_tlast) begin
				act <= 1'b0;
				if (curr == (CHAN_NUM - 1)) begin
					next <= 0;
				end else begin
					next <= curr + 1;
				end
			end
		end
	end
end

always @(*) begin
	curr = next;
	curr_wrap = 1'b1;
	if (act == 1'b0) begin
		for (i = 0; i < CHAN_NUM; i = i + 1) begin
			if (i == next) begin
				for (j = (CHAN_NUM - 1); j >= i; j = j - 1) begin
					if (axis_tvalid[j]) begin
						curr = j;
						curr_wrap = 1'b0;
					end
				end
				if (curr_wrap == 1'b1) begin
					for (j = i - 1; j >= 0; j = j - 1) begin
						if (axis_tvalid[j]) begin
							curr = j;
						end
					end
				end
			end
		end
	end
end

endmodule
module mactable_dpcam_line_array #(
	parameter ADDR_WIDTH = 8,
	parameter KEY_WIDTH = 8
)
(
	input wire clk,
	input wire rst,
	input wire [ADDR_WIDTH-1:0]set_addr,
	input wire [KEY_WIDTH-1:0]set_key,
	input wire set_clr,
	input wire set_valid,
	input wire [KEY_WIDTH-1:0]req_key0,
	input wire [KEY_WIDTH-1:0]req_key1,
	input wire req_valid,
	output wire [2**ADDR_WIDTH-1:0]line_match0,
	output wire [2**ADDR_WIDTH-1:0]line_match1
);

localparam MEM_WIDTH = KEY_WIDTH;

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[1:0];
wire [KEY_WIDTH-1:0]key[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];
	assign key[g] = mem_tmp;
end endgenerate

assign line_match0 = match[0];
assign line_match1 = match[1];

/* 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
					mem[i] <= set_key;
					active[i] <= ~set_clr;
				end
			end
		end
	end
end

/* Request */
always @(posedge clk) begin
	if (rst == 1'b1) begin
		match[0] <= {2**ADDR_WIDTH{1'b0}};
		match[1] <= {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
				match[0][i] <= ((key[i] ^ req_key0) == 0) & active[i];
				match[1][i] <= ((key[i] ^ req_key1) == 0) & active[i];
			end
		end
	end
end

endmodule
module mactable_dpcam_line_encoder #(
	parameter ADDR_WIDTH = 8
)
(
	input wire clk,
	input wire rst,
	input wire [2**ADDR_WIDTH-1:0]line_match,
	input wire line_valid,
	output wire [ADDR_WIDTH-1:0]addr,
	output wire addr_valid,
	output wire addr_null
);

reg encode;
reg [2**ADDR_WIDTH-1:0]line;
reg [ADDR_WIDTH-1:0]addr_out;
reg valid_out;
reg null_out;
integer i;

assign addr = addr_out;
assign addr_valid = valid_out;
assign addr_null = null_out;

always @(posedge clk) begin
	if (rst == 1'b1) begin
		encode <= 1'b0;
	end else begin
		if (encode == 1'b0) begin
			if (line_valid) begin
				line <= line_match;
				encode <= 1'b1;
			end
		end else begin
			if (line == 0) begin
				encode <= 1'b0;
			end else begin
				if ((line & ~(2**addr_out))) begin
					line[addr_out] <= 1'b0;
				end else begin
					encode <= 1'b0;
				end
			end
		end
	end
end

always @(*) begin
	addr_out = 0;
	valid_out = 1'b0;
	null_out = 1'b0;
	
	if (encode == 1'b1) begin
		if (line == 0) begin
			valid_out = 1'b1;
			null_out = 1'b1;
		end else begin
			for (i = 2**ADDR_WIDTH - 1; i >= 0; i = i - 1) begin
				if (line[i] == 1'b1) begin
					addr_out = i;
					valid_out = 1'b1;
				end
			end
		end
	end
end

endmodule
module mactable_dpcam_dpram #(
	parameter ADDR_WIDTH = 8,
	parameter DATA_WIDTH = 8,
	parameter RAM_STYLE = "block"
)
(
	input wire clk,
	input wire [DATA_WIDTH-1:0]dina,
	input wire [ADDR_WIDTH-1:0]addra,
	input wire [ADDR_WIDTH-1:0]addrb,
	input wire wea,
	output wire [DATA_WIDTH-1:0]douta,
	output wire [DATA_WIDTH-1:0]doutb
);

(* ram_style = RAM_STYLE *) reg [DATA_WIDTH-1:0]ram[2**ADDR_WIDTH-1:0];
reg [ADDR_WIDTH-1:0]rdouta; 
reg [ADDR_WIDTH-1:0]rdoutb;
integer i;

assign douta = rdouta;
assign doutb = rdoutb;

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

always @(posedge clk) begin
	if (wea) begin
		ram[addra] <= dina;
	end
	rdouta <= ram[addra];
	rdoutb <= ram[addrb];
end

endmodule
module wb_tv80 (nrst_i, clk_i,
                wbm_adr_o, wbm_tga_o, wbm_dat_i, wbm_dat_o, wbm_cyc_o,
                wbm_stb_o, wbm_we_o, wbm_ack_i,
                nmi_req_i,
                int_req_i,
                busrq_i,
                busak_o);

    input          nrst_i;
    input          clk_i;

    // WISHBONE master interface
    output [15:0]  wbm_adr_o;
    output [1:0]   wbm_tga_o;
    input  [7:0]   wbm_dat_i;
    output [7:0]   wbm_dat_o;
    output         wbm_cyc_o;
    output         wbm_stb_o;
    output         wbm_we_o;
    input          wbm_ack_i;
    
    // Z80-specific interface
    input          nmi_req_i;
    input          int_req_i;
    input          busrq_i;
    output         busak_o;

    // TV80 Interface
    wire           m1_n;
    wire           mreq_n;
    wire           iorq_n;
    wire           rd_n; 
    wire           wr_n;
    wire           rfsh_n;
    wire           halt_n;
    wire           busak_n;
    wire [15:0]    tv80_adr; 
    wire  [7:0]    tv80_dat_o;
    wire           wait_n;
    wire           int_n;
    wire           nmi_n;
    wire           busrq_n;
    wire  [7:0]    tv80_dat_i;

    assign wbm_adr_o = tv80_adr;
    assign wbm_dat_o = tv80_dat_o;
    assign wbm_we_o  = ~wr_n & (~mreq_n | ~iorq_n);
    assign wbm_stb_o = (~wr_n | ~rd_n) & (~mreq_n | ~iorq_n | ~m1_n);
    assign wbm_cyc_o = wbm_stb_o;
    assign wbm_tga_o = (~iorq_n ? `TAG_IO : `TAG_MEM);

    assign wait_n    = wbm_stb_o == 1'b0 ? 1'b1 : wbm_ack_i;

    assign tv80_dat_i = wbm_dat_i;   

    assign int_n   = ~int_req_i;
    assign nmi_n   = ~nmi_req_i;
    assign busrq_n = ~busrq_i;
    assign busak_o = ~busak_n;

// Instantiate TV80 CPU Core
tv80s z80_core (
    .m1_n(m1_n), 
    .mreq_n(mreq_n), 
    .iorq_n(iorq_n), 
    .rd_n(rd_n), 
    .wr_n(wr_n), 
    .rfsh_n(rfsh_n), 
    .halt_n(halt_n), 
    .busak_n(busak_n), 
    .A(tv80_adr), 
    .do(tv80_dat_o), 
    .reset_n(nrst_i), 
    .clk(clk_i), 
    .wait_n(wait_n), 
    .int_n(int_n), 
    .nmi_n(nmi_n), 
    .busrq_n(busrq_n), 
    .di(tv80_dat_i)
    );
   
endmodule
module ram_1r_1w (/*AUTOARG*/
  // Outputs
  rd_data, 
  // Inputs
  clk, wr_addr, wr_en, wr_data, rd_addr
  );

  parameter  width = 8;
  parameter  depth = 128;
  parameter  addr_sz = 7;

  input               clk;
  input [addr_sz-1:0] wr_addr;
  input               wr_en;
  input [width-1:0]   wr_data;

  input [addr_sz-1:0] rd_addr;
  output [width-1:0]  rd_data;

  reg [width-1:0]     mem [0:depth-1];

  always @(posedge clk)
    begin
      if (wr_en)
        mem[wr_addr] <= #1 wr_data;
    end

  assign rd_data = mem[rd_addr];

endmodule // ram_1r_1w
module sync2
  ( input     clk,
    input     data_in,
    output    data_out );

  reg         sync_ff1, sync_ff2;

  always @(posedge clk)
    begin
      sync_ff1 <= #1 data_in;
      sync_ff2 <= #1 sync_ff1;
    end

  assign data_out = sync_ff2;

endmodule // sync2
module behave1p_mem
  #(parameter width=8,
    parameter depth=256,
    parameter addr_sz=8)  //log2(depth))
  (/*AUTOARG*/
  // Outputs
  d_out,
  // Inputs
  wr_en, rd_en, clk, d_in, addr
  );
  input        wr_en, rd_en, clk;
  input [width-1:0] d_in;
  input [addr_sz-1:0]     addr;

  output [width-1:0]     d_out;

  reg [addr_sz-1:0] r_addr;

  reg [width-1:0]            array[0:depth-1];
  
  always @(posedge clk)
    begin
      if (wr_en)
        begin
          array[addr] <= #1 d_in;
        end
      else if (rd_en)
        begin
          r_addr <= #1 addr;
        end
    end // always @ (posedge clk)

  assign d_out = array[r_addr];

endmodule
module tv80_reg (/*AUTOARG*/
  // Outputs
  DOBH, DOAL, DOCL, DOBL, DOCH, DOAH, 
  // Inputs
  AddrC, AddrA, AddrB, DIH, DIL, clk, CEN, WEH, WEL
  );
    input  [2:0] AddrC;
    output [7:0] DOBH;
    input  [2:0] AddrA;
    input  [2:0] AddrB;
    input  [7:0] DIH;
    output [7:0] DOAL;
    output [7:0] DOCL;
    input  [7:0] DIL;
    output [7:0] DOBL;
    output [7:0] DOCH;
    output [7:0] DOAH;
    input  clk, CEN, WEH, WEL;

  reg [7:0] RegsH [0:7];
  reg [7:0] RegsL [0:7];

  always @(posedge clk)
    begin
      if (CEN)
        begin
          if (WEH) RegsH[AddrA] <= DIH;
          if (WEL) RegsL[AddrA] <= DIL;
        end
    end
          
  assign DOAH = RegsH[AddrA];
  assign DOAL = RegsL[AddrA];
  assign DOBH = RegsH[AddrB];
  assign DOBL = RegsL[AddrB];
  assign DOCH = RegsH[AddrC];
  assign DOCL = RegsL[AddrC];

  // break out ram bits for waveform debug
// synopsys translate_off
  wire [7:0] B = RegsH[0];
  wire [7:0] BP = RegsH[4];
  wire [7:0] C = RegsL[0];
  wire [7:0] CP = RegsL[4];
  wire [7:0] D = RegsH[1];
  wire [7:0] DP = RegsH[5];
  wire [7:0] E = RegsL[1];
  wire [7:0] EP = RegsL[5];
  wire [7:0] H = RegsH[2];
  wire [7:0] HP = RegsH[6];
  wire [7:0] L = RegsL[2];
  wire [7:0] LP = RegsL[6];

  wire [15:0] IX = { RegsH[3], RegsL[3] };
  wire [15:0] IY = { RegsH[7], RegsL[7] };
// synopsys translate_on
  
endmodule
module sd_zmem
  #(parameter mem_size=8192,
    parameter z_asz=16)
  (
   input        clk,
   input        reset,

   /*AUTOINPUT*/
   // Beginning of automatic inputs (from unused autoinst inputs)
   input [z_asz-1:0]	addr,			// To access64 of sd_access64.v
   input		cs_n,			// To access64 of sd_access64.v
   input		mreq_n,			// To access64 of sd_access64.v
   input		rd_n,			// To access64 of sd_access64.v
   input [7:0]		wr_data,		// To access64 of sd_access64.v
   input		wr_n,			// To access64 of sd_access64.v
   // End of automatics
   /*AUTOOUTPUT*/
   // Beginning of automatic outputs (from unused autoinst outputs)
   output		ack,			// From access64 of sd_access64.v
   output [7:0]		rd_data		// From access64 of sd_access64.v
   // End of automatics
   );

  wire [63:0] 		s2z_data;		// From sboard of sd_scoreboard.v
  wire [63:0]		z2s_data;		// From access64 of sd_access64.v
  wire [s_asz-1:0]	z2s_itemid;		// From access64 of sd_access64.v
  wire [63:0]		z2s_mask;		// From access64 of sd_access64.v
   /*AUTOWIRE*/
   // Beginning of automatic wires (for undeclared instantiated-module outputs)
   wire			s2z_drdy;		// From access64 of sd_access64.v
   wire			s2z_srdy;		// From sboard of sd_scoreboard.v
   wire			z2s_drdy;		// From sboard of sd_scoreboard.v
   wire			z2s_req_type;		// From access64 of sd_access64.v
   wire			z2s_srdy;		// From access64 of sd_access64.v
   // End of automatics

  localparam s_asz = $clog2(mem_size);

  sd_access64 #(/*AUTOINSTPARAM*/
		// Parameters
		.z_asz			(z_asz),
		.s_asz			(s_asz)) access64
    (/*AUTOINST*/
     // Outputs
     .ack				(ack),
     .rd_data				(rd_data[7:0]),
     .z2s_srdy				(z2s_srdy),
     .z2s_req_type			(z2s_req_type),
     .z2s_mask				(z2s_mask[63:0]),
     .z2s_data				(z2s_data[63:0]),
     .z2s_itemid			(z2s_itemid[s_asz-1:0]),
     .s2z_drdy				(s2z_drdy),
     // Inputs
     .reset				(reset),
     .clk				(clk),
     .mreq_n				(mreq_n),
     .cs_n				(cs_n),
     .rd_n				(rd_n),
     .wr_n				(wr_n),
     .addr				(addr[z_asz-1:0]),
     .wr_data				(wr_data[7:0]),
     .z2s_drdy				(z2s_drdy),
     .s2z_srdy				(s2z_srdy),
     .s2z_data				(s2z_data[63:0]));

/* sd_scoreboard AUTO_TEMPLATE
 (
    .c_txid				(),
    .p_txid				(),
    .c_\(.*\)           (z2s_\1),
    .p_\(.*\)           (s2z_\1),
  );
 */
  sd_scoreboard #(
		  // Parameters
		  .width		(64),
		  .items		(mem_size),
		  .use_txid		(0),
		  .use_mask		(1),
		  .txid_sz		(8)) sboard
    (/*AUTOINST*/
     // Outputs
     .c_drdy				(z2s_drdy),		 // Templated
     .p_srdy				(s2z_srdy),		 // Templated
     .p_txid				(),			 // Templated
     .p_data				(s2z_data),		 // Templated
     // Inputs
     .clk				(clk),
     .reset				(reset),
     .c_srdy				(z2s_srdy),		 // Templated
     .c_req_type			(z2s_req_type),		 // Templated
     .c_txid				(),			 // Templated
     .c_mask				(z2s_mask),		 // Templated
     .c_data				(z2s_data),		 // Templated
     .c_itemid				(z2s_itemid),		 // Templated
     .p_drdy				(s2z_drdy));		 // Templated

endmodule // sd_zmem
module test;

   logic rst_n = 0;

   logic clk = 0;
   always #125 clk = !clk;

   logic VGND;
   logic VPWR;

   logic [7:0] ui_in;
   logic [7:0] uo_out;
   logic [7:0] uio_in;
   logic [7:0] uio_out;
   logic [7:0] uio_oe;
   wire        ena;


`ifdef ANA_TYPE_REAL
   real        ua_0  = 0;
   real        ua_1 = 0;

`else
   tri [7:0]   ua;
   logic       uain = 0;
   assign ua = uain;
`endif
   tt_um_TT06_SAR_wulffern dut (
                                .VGND(VGND),
                                .VPWR(VPWR),
                                .ui_in(ui_in),
                                .uo_out(uo_out),
                                .uio_in(uio_in),
                                .uio_out(uio_out),
                                .uio_oe(uio_oe),
`ifdef ANA_TYPE_REAL
                                .ua_0(ua_0),
                                .ua_1(ua_1),
`else
                                .ua(ua),
`endif
                                .ena(ena),
                                .clk(clk),
                                .rst_n(rst_n)
                                );


`ifdef ANA_TYPE_REAL
   always #100 begin
      ua_0 = $sin(2*3.14*1/7750*$time);
      ua_1 = -$sin(2*3.14*1/7750*$time);
   end
`endif



   initial
     begin
        $dumpfile("test.vcd");
        $dumpvars(0,test);

        ui_in = 0;


        #10 rst_n = 0;
        #10 rst_n = 1;

        #10 VGND = 0;
        #1 VPWR = 1;

        #500 ui_in[0] = 1;

        #5000 $stop;

     end
endmodule // test
module trng (
        input clk, 
        input rst, 
        input stop,
        output random
    );

    (* keep *) wire [31:1] stage;
    reg meta1, meta2;

    assign random = meta2;

    always@(posedge clk or posedge rst)
    if (rst) begin
        meta1 <= 1'b0;
        meta2 <= 1'b0;
    end else begin
        meta1 <= stage[1];
        meta2 <= meta1;
    end

    assign stage[1] = ~&{stage[2] ^ stage[1],stop};
    assign stage[2] = !stage[3];
    assign stage[3] = !stage[4] ^ stage[1];
    assign stage[4] = !stage[5] ^ stage[1];
    assign stage[5] = !stage[6] ^ stage[1];
    assign stage[6] = !stage[7] ^ stage[1];
    assign stage[7] = !stage[8];
    assign stage[8] = !stage[9] ^ stage[1];
    assign stage[9] = !stage[10] ^ stage[1];
    assign stage[10] = !stage[11];
    assign stage[11] = !stage[12];
    assign stage[12] = !stage[13] ^ stage[1];
    assign stage[13] = !stage[14];
    assign stage[14] = !stage[15] ^ stage[1];
    assign stage[15] = !stage[16] ^ stage[1];
    assign stage[16] = !stage[17] ^ stage[1];
    assign stage[17] = !stage[18];
    assign stage[18] = !stage[19];
    assign stage[19] = !stage[20] ^ stage[1];
    assign stage[20] = !stage[21] ^ stage[1];
    assign stage[21] = !stage[22];
    assign stage[22] = !stage[23];
    assign stage[23] = !stage[24];
    assign stage[24] = !stage[25];
    assign stage[25] = !stage[26];
    assign stage[26] = !stage[27] ^ stage[1];
    assign stage[27] = !stage[28];
    assign stage[28] = !stage[29];
    assign stage[29] = !stage[30];
    assign stage[30] = !stage[31];
    assign stage[31] = !stage[1];

endmodule
module  lfsr_fib(i_clk, i_reset, i_ce, i_in, o_bit);
    parameter       LN=8;   // LFSR Register length/polynomial deg
    parameter [(LN-1):0]    TAPS = 8'h2d,
                INITIAL_FILL = { { (LN-1){1'b0}}, 1'b1 };
    //
    input   wire            i_clk, i_reset, i_ce, i_in;
    output  wire            o_bit;

    reg [(LN-1):0]  sreg;

    initial sreg = INITIAL_FILL;
    always @(posedge i_clk)
        if (i_reset)
        begin
            sreg <= INITIAL_FILL;
        end else if (i_ce)
        begin
            sreg[(LN-2):0] <= sreg[(LN-1):1];
            sreg[(LN-1)] <= (^(sreg & TAPS)) ^ i_in;
        end

    assign  o_bit = sreg[0];

endmodule
module BUF(A, Y);
    input A;
    output Y;
    assign Y = A;
endmodule
module NOT(A, Y);
    input A;
    output Y;
    assign Y = ~A;
endmodule
module NAND(A, B, Y);
    input A, B;
    output Y;
    assign Y = ~(A & B);
endmodule
module NOR(A, B, Y);
    input A, B;
    output Y;
    assign Y = ~(A | B);
endmodule
module DFF(C, D, Q);
    input C, D;
    output reg Q;
    always @(posedge C)
        Q <= D;
endmodule
module DFFSR(C, D, Q, S, R);
    input C, D, S, R;
    output reg Q;
    always @(posedge C, posedge S, posedge R)
        if (S)
            Q <= 1'b1;
        else if (R)
            Q <= 1'b0;
        else
            Q <= D;
endmodule
module user_project_wrapper #(
    parameter BITS = 32
)(
`ifdef USE_POWER_PINS
    inout vdda1,	// User area 1 3.3V supply
    inout vdda2,	// User area 2 3.3V supply
    inout vssa1,	// User area 1 analog ground
    inout vssa2,	// User area 2 analog ground
    inout vccd1,	// User area 1 1.8V supply
    inout vccd2,	// User area 2 1.8v supply
    inout vssd1,	// User area 1 digital ground
    inout vssd2,	// User area 2 digital ground
`endif

    // Wishbone Slave ports (WB MI A)
    input wb_clk_i,
    input wb_rst_i,
    input wbs_stb_i,
    input wbs_cyc_i,
    input wbs_we_i,
    input [3:0] wbs_sel_i,
    input [31:0] wbs_dat_i,
    input [31:0] wbs_adr_i,
    output wbs_ack_o,
    output [31:0] wbs_dat_o,

    // Logic Analyzer Signals
    input  [127:0] la_data_in,
    output [127:0] la_data_out,
    input  [127:0] la_oen,

    // IOs
    input  [`MPRJ_IO_PADS-1:0] io_in,
    output [`MPRJ_IO_PADS-1:0] io_out,
    output [`MPRJ_IO_PADS-1:0] io_oeb,

    // Analog (direct connection to GPIO pad---use with caution)
    // Note that analog I/O is not available on the 7 lowest-numbered
    // GPIO pads, and so the analog_io indexing is offset from the
    // GPIO indexing by 7.
    inout [`MPRJ_IO_PADS-8:0] analog_io,

    // Independent clock (on independent integer divider)
    input   user_clock2
);

    /*--------------------------------------*/
    /* User project is instantiated  here   */
    /*--------------------------------------*/

    user_proj_example mprj (
    `ifdef USE_POWER_PINS
	.vdda1(vdda1),	// User area 1 3.3V power
	.vdda2(vdda2),	// User area 2 3.3V power
	.vssa1(vssa1),	// User area 1 analog ground
	.vssa2(vssa2),	// User area 2 analog ground
	.vccd1(vccd1),	// User area 1 1.8V power
	.vccd2(vccd2),	// User area 2 1.8V power
	.vssd1(vssd1),	// User area 1 digital ground
	.vssd2(vssd2),	// User area 2 digital ground
    `endif

	// MGMT core clock and reset

    	.wb_clk_i(wb_clk_i),
    	.wb_rst_i(wb_rst_i),

	// MGMT SoC Wishbone Slave

	.wbs_cyc_i(wbs_cyc_i),
	.wbs_stb_i(wbs_stb_i),
	.wbs_we_i(wbs_we_i),
	.wbs_sel_i(wbs_sel_i),
	.wbs_adr_i(wbs_adr_i),
	.wbs_dat_i(wbs_dat_i),
	.wbs_ack_o(wbs_ack_o),
	.wbs_dat_o(wbs_dat_o),

	// Logic Analyzer

	.la_data_in(la_data_in),
	.la_data_out(la_data_out),
	.la_oen (la_oen),

	// IO Pads

	.io_in (io_in),
    	.io_out(io_out),
    	.io_oeb(io_oeb)
    );

endmodule	// user_project_wrapper
module subservient_fpga
(
 input wire  i_clk,
 input wire  i_rst,
 output wire q);

   parameter memfile = "hello.hex";
   parameter memsize = 1024;
   localparam aw    = $clog2(memsize);

   wire      clk;
   wire      rst;

   wire [aw-1:0] sram_waddr;
   wire [7:0] 	 sram_wdata;
   wire 	 sram_wen;
   wire [aw-1:0] sram_raddr;
   wire [7:0] 	 sram_rdata;
   wire 	 sram_ren;

   subservient_fpga_clock_gen clock_gen
     (.i_clk (i_clk),
      .i_rst (i_rst),
      .o_clk (clk),
      .o_rst (rst));

   subservient_generic_ram
     #(.depth (memsize),
       .memfile (memfile))
   memory
     (.i_clk   (clk),
      .i_rst   (rst),
      .i_waddr (sram_waddr),
      .i_wdata (sram_wdata),
      .i_wen   (sram_wen),
      .i_raddr (sram_raddr),
      .o_rdata (sram_rdata),
      .i_ren   (sram_ren));
     
   subservient
     #(.memsize  (memsize),
       .WITH_CSR (0))
   dut
     (// Clock & reset
      .i_clk (clk),
      .i_rst (rst),

      //SRAM interface
      .o_sram_waddr (sram_waddr),
      .o_sram_wdata (sram_wdata),
      .o_sram_wen   (sram_wen),
      .o_sram_raddr (sram_raddr),
      .i_sram_rdata (sram_rdata),
      .o_sram_ren   (sram_ren),

      //Debug interface
      .i_debug_mode (1'b0),
      .i_wb_dbg_adr (32'd0),
      .i_wb_dbg_dat (32'd0),
      .i_wb_dbg_sel (4'd0),
      .i_wb_dbg_we  (1'd0),
      .i_wb_dbg_stb (1'd0),
      .o_wb_dbg_rdt (),
      .o_wb_dbg_ack (),

      // External I/O
      .o_gpio (q));

endmodule
module subservient
  #(//Memory parameters
    parameter memsize  = 512,
    parameter aw       = $clog2(memsize),
    //Enable CSR + interrupts
    parameter WITH_CSR = 0)
  (
   input wire 		i_clk,
   input wire 		i_rst,

   //SRAM interface
   output wire [aw-1:0] o_sram_waddr,
   output wire [7:0] 	o_sram_wdata,
   output wire 		o_sram_wen,
   output wire [aw-1:0] o_sram_raddr,
   input wire [7:0] 	i_sram_rdata,
   output wire 		o_sram_ren,

   //Debug interface
   input wire 		i_debug_mode,
   input wire [31:0] 	i_wb_dbg_adr,
   input wire [31:0] 	i_wb_dbg_dat,
   input wire [3:0] 	i_wb_dbg_sel,
   input wire 		i_wb_dbg_we ,
   input wire 		i_wb_dbg_stb,
   output wire [31:0] 	o_wb_dbg_rdt,
   output wire 		o_wb_dbg_ack,

   //External I/O
   output wire 		o_gpio);

   wire [31:0] 	wb_core_adr;
   wire [31:0] 	wb_core_dat;
   wire [3:0] 	wb_core_sel;
   wire 	wb_core_we;
   wire 	wb_core_stb;
   wire [31:0] 	wb_core_rdt;
   wire 	wb_core_ack;

   wire 	wb_gpio_rdt;
   assign wb_core_rdt = {31'd0, wb_gpio_rdt};

   subservient_gpio gpio
     (.i_wb_clk (i_clk),
      .i_wb_rst (i_rst),
      .i_wb_dat (wb_core_dat[0]),
      .i_wb_we  (wb_core_we),
      .i_wb_stb (wb_core_stb),
      .o_wb_rdt (wb_gpio_rdt),
      .o_wb_ack (wb_core_ack),
      .o_gpio   (o_gpio));

   subservient_core
     #(.memsize (memsize),
       .WITH_CSR (WITH_CSR))
   core
     (.i_clk       (i_clk),
      .i_rst       (i_rst),
      .i_timer_irq (1'b0),

      //SRAM interface
      .o_sram_waddr (o_sram_waddr),
      .o_sram_wdata (o_sram_wdata),
      .o_sram_wen   (o_sram_wen),
      .o_sram_raddr (o_sram_raddr),
      .i_sram_rdata (i_sram_rdata),
      .o_sram_ren   (o_sram_ren),

      //Debug interface
      .i_debug_mode (i_debug_mode),
      .i_wb_dbg_adr (i_wb_dbg_adr),
      .i_wb_dbg_dat (i_wb_dbg_dat),
      .i_wb_dbg_sel (i_wb_dbg_sel),
      .i_wb_dbg_we  (i_wb_dbg_we ),
      .i_wb_dbg_stb (i_wb_dbg_stb),
      .o_wb_dbg_rdt (o_wb_dbg_rdt),
      .o_wb_dbg_ack (o_wb_dbg_ack),

      //Peripheral interface
      .o_wb_adr (wb_core_adr),
      .o_wb_dat (wb_core_dat),
      .o_wb_sel (wb_core_sel),
      .o_wb_we  (wb_core_we) ,
      .o_wb_stb (wb_core_stb),
      .i_wb_rdt (wb_core_rdt),
      .i_wb_ack (wb_core_ack));

endmodule
module subservient_fpga_clock_gen
  (input wire  i_clk,
   input wire  i_rst,
   output wire o_clk,
   output reg  o_rst);

   wire   clkfb;
   wire   locked;
   reg 	  locked_r;

   PLLE2_BASE
     #(.BANDWIDTH("OPTIMIZED"),
       .CLKIN1_PERIOD(10.0), //100MHz
       .CLKFBOUT_MULT(16),
       .CLKOUT0_DIVIDE(50),
       .DIVCLK_DIVIDE(1),
       .STARTUP_WAIT("FALSE"))
   PLLE2_BASE_inst
     (.CLKOUT0(o_clk), //100MHz*16/50 = 32 MHz
      .CLKOUT1(),
      .CLKOUT2(),
      .CLKOUT3(),
      .CLKOUT4(),
      .CLKOUT5(),
      .CLKFBOUT(clkfb),
      .LOCKED(locked),
      .CLKIN1(i_clk),
      .PWRDWN(1'b0),
      .RST(!i_rst),
      .CLKFBIN(clkfb));

   always @(posedge o_clk) begin
      locked_r <= locked;
      o_rst  <= !locked_r;
   end

endmodule
module subservient_generic_ram
  #(parameter depth = 0,
    parameter aw = $clog2(depth),
    parameter memfile = "")
   (input wire		i_clk,
    input wire		i_rst,
    //SRAM interface
    input wire [aw-1:0]	i_waddr,
    input wire [7:0]	i_wdata,
    input wire		i_wen,
    input wire [aw-1:0]	i_raddr,
    output reg [7:0]	o_rdata,
    input wire		i_ren);

   reg [7:0]	       mem [0:depth-1] /* verilator public */;

   always @(posedge i_clk) begin
      if (i_wen) mem[i_waddr]   <= i_wdata;
      o_rdata <= i_ren ? mem[i_raddr] : 8'bx;
   end

   initial
     if(|memfile) begin
	$display("Preloading %m from %s", memfile);
	$readmemh(memfile, mem);
     end
endmodule
module subservient_gpio
  (input wire i_wb_clk,
   input wire i_wb_rst,
   input wire i_wb_dat,
   input wire i_wb_we,
   input wire i_wb_stb,
   output reg o_wb_rdt,
   output reg o_wb_ack,
   output reg o_gpio);

   always @(posedge i_wb_clk) begin
      o_wb_rdt <= o_gpio;
      if (i_wb_stb & i_wb_we)
	o_gpio <= i_wb_dat;
      o_wb_ack <= i_wb_stb & !o_wb_ack;

      if (i_wb_rst) begin
	 o_wb_ack <= 1'b0;
	 o_gpio   <= 1'b0;
      end
   end
endmodule
module subservient_ram
  #(//Memory parameters
    parameter depth = 256,
    parameter aw    = $clog2(depth))
   (input wire 		 i_clk,
    input wire 		 i_rst,
    input wire [aw-1:0]  i_waddr,
    input wire [7:0] 	 i_wdata,
    input wire 		 i_wen,
    input wire [aw-1:0]  i_raddr,
    output wire [7:0] 	 o_rdata,
    input wire 		 i_ren,

    output wire [aw-1:0] o_sram_waddr,
    output wire [7:0] 	 o_sram_wdata,
    output wire 	 o_sram_wen,
    output wire [aw-1:0] o_sram_raddr,
    input wire [7:0] 	 i_sram_rdata,
    output wire 	 o_sram_ren,

    input wire [aw-1:2]  i_wb_adr,
    input wire [31:0] 	 i_wb_dat,
    input wire [3:0] 	 i_wb_sel,
    input wire 		 i_wb_we,
    input wire 		 i_wb_stb,
    output wire [31:0] 	 o_wb_rdt,
    output reg 		 o_wb_ack);

   reg [aw-1:0]		 rf_waddr_r;
   reg [7:0]		 rf_wdata_r;
   reg			 rf_wen_r;

   reg [1:0] 		bsel;

   wire 		wb_en = i_wb_stb & !rf_wen_r & !o_wb_ack;

   wire 		wb_we = i_wb_we & i_wb_sel[bsel];

   assign o_sram_waddr = wb_en ? {i_wb_adr[aw-1:2],bsel} : rf_waddr_r;
   assign o_sram_wdata = wb_en ? i_wb_dat[bsel*8+:8]     : rf_wdata_r;
   assign o_sram_wen   = wb_en ? wb_we : rf_wen_r;
   assign o_sram_raddr = wb_en ? {i_wb_adr[aw-1:2],bsel} : i_raddr;
   assign o_sram_ren   = wb_en ? !i_wb_we : i_ren;

   reg [23:0] 		wb_rdt;
   assign o_wb_rdt = {i_sram_rdata, wb_rdt};

   reg 			regzero;
   always @(posedge i_clk) begin
      rf_waddr_r <= i_waddr;
      rf_wdata_r <= i_wdata;
      rf_wen_r   <= i_wen;

      if (wb_en) bsel <= bsel + 2'd1;
      o_wb_ack <= wb_en & &bsel;
      if (bsel == 2'b01) wb_rdt[7:0]   <= i_sram_rdata;
      if (bsel == 2'b10) wb_rdt[15:8]  <= i_sram_rdata;
      if (bsel == 2'b11) wb_rdt[23:16] <= i_sram_rdata;
      if (i_rst) begin
	 bsel <= 2'd0;
	 o_wb_ack <= 1'b0;
      end
      regzero <= &i_raddr[aw-1:2];
   end

   assign o_rdata = regzero ? 8'd0 : i_sram_rdata;

endmodule
module subservient_debug_switch
  (//Debug selector
   input wire 	      i_debug_mode,

   //Debug interface
   input wire [31:0]  i_wb_dbg_adr,
   input wire [31:0]  i_wb_dbg_dat,
   input wire [3:0]   i_wb_dbg_sel,
   input wire 	      i_wb_dbg_we,
   input wire 	      i_wb_dbg_stb,
   output wire [31:0] o_wb_dbg_rdt,
   output wire 	      o_wb_dbg_ack,

   //Data bus interface towards CPU
   input wire [31:0]  i_wb_dbus_adr,
   input wire [31:0]  i_wb_dbus_dat,
   input wire [3:0]   i_wb_dbus_sel,
   input wire 	      i_wb_dbus_we,
   input wire 	      i_wb_dbus_stb,
   output wire [31:0] o_wb_dbus_rdt,
   output wire 	      o_wb_dbus_ack,

   //Data bus interface towards memory/peripherals
   output wire [31:0] o_wb_mux_adr,
   output wire [31:0] o_wb_mux_dat,
   output wire [3:0]  o_wb_mux_sel,
   output wire 	      o_wb_mux_we,
   output wire 	      o_wb_mux_stb,
   input wire [31:0]  i_wb_mux_rdt,
   input wire 	      i_wb_mux_ack);

   assign o_wb_dbg_rdt  = i_wb_mux_rdt;
   assign o_wb_dbg_ack  = i_wb_mux_ack & i_debug_mode;

   assign o_wb_dbus_rdt = i_wb_mux_rdt;
   assign o_wb_dbus_ack = i_wb_mux_ack & !i_debug_mode;

   assign o_wb_mux_adr = i_debug_mode ? i_wb_dbg_adr : i_wb_dbus_adr;
   assign o_wb_mux_dat = i_debug_mode ? i_wb_dbg_dat : i_wb_dbus_dat;
   assign o_wb_mux_sel = i_debug_mode ? i_wb_dbg_sel : i_wb_dbus_sel;
   assign o_wb_mux_we  = i_debug_mode ? i_wb_dbg_we  : i_wb_dbus_we ;
   assign o_wb_mux_stb = i_debug_mode ? i_wb_dbg_stb : i_wb_dbus_stb;


endmodule
module uart_decoder
  (input wire [31:0] baud_rate,
   input wire 	     rx);

   integer i;
   reg [7:0] ch;

   real t;

   initial begin

      @(posedge rx);
      t = 1000000000/baud_rate;

      forever begin
	 @(negedge rx);
	 #(t/2) ch = 0;
	 for (i=0;i<8;i=i+1)
	   #t ch[i] = rx;
	 $write("%c",ch);
	 $fflush;
      end
   end
endmodule
module subservient_fpga_clock_gen
  (input wire  i_clk,
   input wire  i_rst,
   output wire o_clk,
   output reg  o_rst);

   assign o_clk = i_clk;
   always @(posedge i_clk) o_rst <= i_rst;

endmodule
module pc_reg(
	      input wire 		clk,
	      input wire 		rst,
	      output reg [`InstAddrBus] pc,
	      output reg 		ce
	      );
   always @ (posedge clk)
     begin
	if (ce == `ChipDisable) pc <= 32'h0000000;
	else pc <= pc+4'h4;
     end
   always @ (posedge clk)
     begin
	if (rst == `RstEnable) ce <= `ChipDisable;
	else ce <= `ChipEnable;
     end
endmodule // pc_reg
module ex(

	  input wire 		   rst,
   
	  //送到执行阶段的信息
	  input wire [`AluOpBus]   aluop_i,
	  input wire [`AluSelBus]  alusel_i,
	  input wire [`RegBus] 	   reg1_i,
	  input wire [`RegBus] 	   reg2_i,
	  input wire [`RegAddrBus] wd_i,
	  input wire 		   wreg_i,


	  output reg [`RegAddrBus] wd_o,
	  output reg 		   wreg_o,
	  output reg [`RegBus] 	   wdata_o
	  );
   
   reg [`RegBus] 		   logicout;
   reg [`RegBus] 		   shiftres;

   // Logic
   always @ (*)
     begin
	if (rst == `RstEnable) logicout <= `ZeroWord;
	else
	  begin
	     case (aluop_i)
	       `EXE_AND_OP: logicout <= reg1_i & reg2_i;
	       `EXE_OR_OP: logicout <= reg1_i | reg2_i;
	       `EXE_XOR_OP: logicout <= reg1_i ^ reg2_i;
	       default: logicout <= `ZeroWord;
	     endcase // case (aluop_i)
	  end // else: !if(rst == `RstEnable)
     end // always @ (*)

   // Shift
   always @ (*) begin
      if(rst == `RstEnable) shiftres <= `ZeroWord;
      else 
	begin
	   case (aluop_i)
	     `EXE_SLL_OP: shiftres <= reg1_i << reg2_i[4:0];
	     `EXE_SRL_OP: shiftres <= reg1_i >> reg2_i[4:0];
	     `EXE_SRA_OP:
	       shiftres <= ({32{reg1_i[31]}} << (6'd32-{1'b0, reg2_i[4:0]}))| reg1_i >> reg2_i[4:0];
	     default: shiftres <= `ZeroWord;	     
	   endcase // case (aluop_i)
	end // else: !if(rst == `RstEnable)
   end // always @ (*)
   
			    
   always @ (*) 
     begin
	wd_o <= wd_i;
	wreg_o <= wreg_i;
	case (alusel_i) 
	  `EXE_RES_LOGIC: wdata_o <= logicout;
	  `EXE_RES_SHIFT: wdata_o <= shiftres;
	  default: wdata_o <= `ZeroWord;
	endcase // case (alusel_i)
     end // always @ (*)
   
endmodule // ex
module openmips_min_sopc_tb();

   reg CLOCK_50;
   reg     rst;

   integer i;
   
   initial
     begin
	CLOCK_50 = 1'b0;
	forever #10 CLOCK_50 = ~CLOCK_50;
     end

   initial
     begin
	rst = `RstEnable;
	#19 rst = `RstDisable;
	#1000 $finish;
     end

   openmips_min_sopc openmips_min_sopc0(
					.clk(CLOCK_50),
					.rst(rst)
					);
   
endmodule // openmips_min_sopc_tb
module ex_mem(
	      input wire 	       clk,
	      input wire 	       rst,


	      //来自执行阶段的信息	
	      input wire [`RegAddrBus] ex_wd,
	      input wire 	       ex_wreg,
	      input wire [`RegBus]     ex_wdata, 

	      //送到访存阶段的信息
	      output reg [`RegAddrBus] mem_wd,
	      output reg 	       mem_wreg,
	      output reg [`RegBus]     mem_wdata

	      );

   always @ (posedge clk) 
     begin
	if(rst == `RstEnable) 
	  begin
	     mem_wd <= `NOPRegAddr;
	     mem_wreg <= `WriteDisable;
	     mem_wdata <= `ZeroWord;	
	  end 
	else 
	  begin
	     mem_wd <= ex_wd;
	     mem_wreg <= ex_wreg;
	     mem_wdata <= ex_wdata;			
	  end // else: !if(rst == `RstEnable)
     end // always @ (posedge clk)

endmodule // ex_mem
module inst_rom(
		input wire 		  ce,
		input wire [`InstAddrBus] addr,
		output reg [`InstBus] 	  inst
	      );

   reg[`InstBus]  inst_mem[0:10];
   
   initial $readmemh ("instr.data",inst_mem);

   always @ (*)
     begin
	if (ce == `ChipDisable) inst <= `ZeroWord;
	else
	  inst <= inst_mem[addr[`InstMemNumLog2+1:2]];
     end

endmodule // inst_rom