dakies/OSS_Verilog huggingface dataset:
module uart_top #(
	parameter CLOCK_DIVIDE = 271)
(
	input clk, resetn,

	input             mem_valid,
	output reg        mem_ready,
	input      [31:0] mem_addr,
	input      [31:0] mem_wdata,
	input      [ 3:0] mem_wstrb,
	output reg [31:0] mem_rdata,

	output            tx,
	input             rx
   ) ;

   reg  [7:0] tx_byte;
   reg        transmit;
   wire       tx_fifo_full;

   wire [7:0] rx_byte;
   reg        rx_fifo_pop = 0;
   wire       rx_fifo_empty;
   
   wire       irq;
   wire       busy;

   reg        mem_ready_r;
   

	always @(posedge clk) begin
		if (!resetn) begin
			mem_ready <= 0;
			mem_rdata <= 0;
			
			tx_byte <= 8'hf;
			transmit <= 0;

			mem_ready_r <= 0;
		end else begin

			if ((mem_valid == 1) && (tx_fifo_full == 0) && (mem_ready_r == 0)) begin
				mem_ready_r <= 1;		
				mem_ready <= 1;
			end

			if (mem_ready)
				mem_ready <= 0;

			if (mem_valid == 0)
				mem_ready_r <= 0;	

			transmit <= 0;
			if ((mem_valid == 1) && (tx_fifo_full == 0) && (mem_ready_r == 0)) begin
				// mem_ready <= tx_fifo_full ? 0 : 1;
				transmit <= 1;
				// rx_BD_adr
				if (mem_addr[7:2] == {6'd1}) begin
					mem_rdata <= tx_byte;
					if (mem_wstrb==4'hF) tx_byte <= mem_wdata;
				end
				if (mem_addr[7:2] == {6'd2}) begin
					mem_rdata <= rx_byte;
					if (mem_wstrb==4'hF) tx_byte <= mem_wdata;
				end
			end
		end
	end


	uart_fifo #(
			.CLOCK_DIVIDE(CLOCK_DIVIDE),
			.DATA_WIDTH(8),
			.ADDR_EXP(12),
      		.ADDR_DEPTH(4096)
		) 
	_uart_fifo(
			.rx_byte       (rx_byte),
			.tx            (tx),
			.irq           (irq),
			.busy          (busy),
			.tx_fifo_full  (tx_fifo_full),
			.rx_fifo_empty (rx_fifo_empty),
			.tx_byte       (tx_byte),
			.clk           (clk),
			.rstn          (resetn),
			.rx            (rx),
			.transmit      (transmit),
			.rx_fifo_pop   (rx_fifo_pop)
		);

endmodule
module vram
(
  input  wire         clk_in,   // system clock
  input  wire         en_in,    // chip enable
  input  wire         r_nw_in,  // read/write select (read: 0, write: 1)
  input  wire  [10:0] a_in,     // memory address
  input  wire  [ 7:0] d_in,     // data input
  output wire  [ 7:0] d_out     // data output
);

wire       vram_bram_we;
wire [7:0] vram_bram_dout;

single_port_ram_sync #(.ADDR_WIDTH(11),
                       .DATA_WIDTH(8)) vram_bram(
  .clk(clk_in),
  .we(vram_bram_we),
  .addr_a(a_in),
  .din_a(d_in),
  .dout_a(vram_bram_dout)
);

assign vram_bram_we = (en_in) ? ~r_nw_in       : 1'b0;
assign d_out        = (en_in) ? vram_bram_dout : 8'h00;

endmodule
module wram
(
  input  wire         clk_in,   // system clock
  input  wire         en_in,    // chip enable
  input  wire         r_nw_in,  // read/write select (read: 0, write: 1)
  input  wire  [10:0] a_in,     // memory address
  input  wire  [ 7:0] d_in,     // data input
  output wire  [ 7:0] d_out     // data output
);

wire       wram_bram_we;
wire [7:0] wram_bram_dout;

single_port_ram_sync #(.ADDR_WIDTH(11),
                       .DATA_WIDTH(8)) wram_bram(
  .clk(clk_in),
  .we(wram_bram_we),
  .addr_a(a_in),
  .din_a(d_in),
  .dout_a(wram_bram_dout)
);

assign wram_bram_we = (en_in) ? ~r_nw_in       : 1'b0;
assign d_out        = (en_in) ? wram_bram_dout : 8'h00;

endmodule
module cart
(
  input  wire        clk_in,           // system clock signal

  // Mapper config data.
  input  wire [39:0] cfg_in,           // cartridge config (from iNES header)
  input  wire        cfg_upd_in,       // pulse signal on cfg_in update

  // PRG-ROM interface.
  input  wire        prg_nce_in,       // prg-rom chip enable (active low)
  input  wire [14:0] prg_a_in,         // prg-rom address
  input  wire        prg_r_nw_in,      // prg-rom read/write select
  input  wire [ 7:0] prg_d_in,         // prg-rom data in
  output wire [ 7:0] prg_d_out,        // prg-rom data out

  // CHR-ROM interface.
  input  wire [13:0] chr_a_in,         // chr-rom address
  input  wire        chr_r_nw_in,      // chr-rom read/write select
  input  wire [ 7:0] chr_d_in,         // chr-rom data in
  output wire [ 7:0] chr_d_out,        // chr-rom data out
  output wire        ciram_nce_out,    // vram chip enable (active low)
  output wire        ciram_a10_out     // vram a10 value (controls mirroring)
);

wire        prgrom_bram_we;
wire [14:0] prgrom_bram_a;
wire [7:0]  prgrom_bram_dout;

// Block ram instance for PRG-ROM memory range (0x8000 - 0xFFFF).  Will eventually be
// replaced with SRAM.
single_port_ram_sync #(.ADDR_WIDTH(15),
                       .DATA_WIDTH(8)) prgrom_bram(
  .clk(clk_in),
  .we(prgrom_bram_we),
  .addr_a(prgrom_bram_a),
  .din_a(prg_d_in),
  .dout_a(prgrom_bram_dout)
);

assign prgrom_bram_we = (~prg_nce_in) ? ~prg_r_nw_in     : 1'b0;
assign prg_d_out      = (~prg_nce_in) ? prgrom_bram_dout : 8'h00;
assign prgrom_bram_a  = (cfg_in[33])  ? prg_a_in[14:0]   : { 1'b0, prg_a_in[13:0] };

wire       chrrom_pat_bram_we;
wire [7:0] chrrom_pat_bram_dout;

// Block ram instance for "CHR Pattern Table" memory range (0x0000 - 0x1FFF).
single_port_ram_sync #(.ADDR_WIDTH(13),
                       .DATA_WIDTH(8)) chrrom_pat_bram(
  .clk(clk_in),
  .we(chrrom_pat_bram_we),
  .addr_a(chr_a_in[12:0]),
  .din_a(chr_d_in),
  .dout_a(chrrom_pat_bram_dout)
);

assign ciram_nce_out      = ~chr_a_in[13];
assign ciram_a10_out      = (cfg_in[16])    ? chr_a_in[10] : chr_a_in[11];
assign chrrom_pat_bram_we = (ciram_nce_out) ? ~chr_r_nw_in : 1'b0;
assign chr_d_out          = (ciram_nce_out) ? chrrom_pat_bram_dout : 8'h00;

endmodule
module rp2a03
(
  input  wire        clk_in,         // system clock
  input  wire        rst_in,         // system reset

  // CPU signals.
  input  wire        rdy_in,         // ready signal
  input  wire [ 7:0] d_in,           // data input bus
  input  wire        nnmi_in,        // /nmi interrupt signal (active low)
  input  wire        nres_in,        // /res interrupt signal (active low)
  output wire [ 7:0] d_out,          // data output bus
  output wire [15:0] a_out,          // address bus
  output wire        r_nw_out,       // read/write select (write low)
  output wire        brk_out,        // debug break signal

  // Joypad signals.
  input  wire        jp_data1_in,    // joypad 1 input signal
  input  wire        jp_data2_in,    // joypad 2 input signal
  output wire        jp_clk,         // joypad output clk signal
  output wire        jp_latch,       // joypad output latch signal

  // Audio signals.
  input  wire [ 3:0] mute_in,        // disable autio channels
  output wire        audio_out,      // pwm audio output

  // HCI interface.
  input  wire [ 3:0] dbgreg_sel_in,  // dbg reg select
  input  wire [ 7:0] dbgreg_d_in,    // dbg reg data in
  input  wire        dbgreg_wr_in,   // dbg reg write select
  output wire [ 7:0] dbgreg_d_out    // dbg reg data out
);

//
// CPU: central processing unit block.
//
wire        cpu_ready;
wire [ 7:0] cpu_din;
wire        cpu_nirq;
wire [ 7:0] cpu_dout;
wire [15:0] cpu_a;
wire        cpu_r_nw;

cpu cpu_blk(
  .clk_in(clk_in),
  .rst_in(rst_in),
  .ready_in(cpu_ready),
  .dbgreg_sel_in(dbgreg_sel_in),
  .dbgreg_in(dbgreg_d_in),
  .dbgreg_wr_in(dbgreg_wr_in),
  .d_in(cpu_din),
  .nnmi_in(nnmi_in),
  .nres_in(nres_in),
  .nirq_in(cpu_nirq),
  .d_out(cpu_dout),
  .a_out(cpu_a),
  .r_nw_out(cpu_r_nw),
  .brk_out(brk_out),
  .dbgreg_out(dbgreg_d_out)
);

//
// APU: audio processing unit block.
//
wire [7:0] audio_dout;

apu apu_blk(
  .clk_in(clk_in),
  .rst_in(rst_in),
  .mute_in(mute_in),
  .a_in(cpu_a),
  .d_in(cpu_dout),
  .r_nw_in(cpu_r_nw),
  .audio_out(audio_out),
  .d_out(audio_dout)
);

//
// JP: joypad controller block.
//
wire [7:0] jp_dout;

jp jp_blk(
  .clk(clk_in),
  .rst(rst_in),
  .wr(~cpu_r_nw),
  .addr(cpu_a),
  .din(cpu_dout[0]),
  .jp_data1(jp_data1_in),
  .jp_data2(jp_data2_in),
  .jp_clk(jp_clk),
  .jp_latch(jp_latch),
  .dout(jp_dout)
);

//
// SPRDMA: sprite dma controller block.
//
wire        sprdma_active;
wire [15:0] sprdma_a;
wire [ 7:0] sprdma_dout;
wire        sprdma_r_nw;

sprdma sprdma_blk(
  .clk_in(clk_in),
  .rst_in(rst_in),
  .cpumc_a_in(cpu_a),
  .cpumc_din_in(cpu_dout),
  .cpumc_dout_in(cpu_din),
  .cpu_r_nw_in(cpu_r_nw),
  .active_out(sprdma_active),
  .cpumc_a_out(sprdma_a),
  .cpumc_d_out(sprdma_dout),
  .cpumc_r_nw_out(sprdma_r_nw)
);

assign cpu_ready = rdy_in & !sprdma_active;
assign cpu_din   = d_in | jp_dout | audio_dout;
assign cpu_nirq  = 1'b1;

assign d_out     = (sprdma_active) ? sprdma_dout : cpu_dout;
assign a_out     = (sprdma_active) ? sprdma_a    : cpu_a;
assign r_nw_out  = (sprdma_active) ? sprdma_r_nw : cpu_r_nw;

endmodule
module uart
#(
  parameter SYS_CLK_FREQ = 50000000,
  parameter BAUD_RATE    = 19200,
  parameter DATA_BITS    = 8,
  parameter STOP_BITS    = 1,
  parameter PARITY_MODE  = 0  // 0 = none, 1 = odd, 2 = even
)
(
  input  wire                 clk,        // System clk
  input  wire                 reset,      // Reset signal
  input  wire                 rx,         // RS-232 rx pin
  input  wire [DATA_BITS-1:0] tx_data,    // Data to be transmitted when wr_en is 1
  input  wire                 rd_en,      // Pops current read FIFO front off the queue
  input  wire                 wr_en,      // Write tx_data over serial connection
  output wire                 tx,         // RS-232 tx pin
  output wire [DATA_BITS-1:0] rx_data,    // Data currently at front of read FIFO
  output wire                 rx_empty,   // 1 if there is no more read data available
  output wire                 tx_full,    // 1 if the transmit FIFO cannot accept more requests
  output wire                 parity_err  // 1 if a parity error has been detected
);

localparam BAUD_CLK_OVERSAMPLE_RATE = 16;

wire                 baud_clk_tick;

wire [DATA_BITS-1:0] rx_fifo_wr_data;
wire                 rx_done_tick;
wire                 rx_parity_err;

wire [DATA_BITS-1:0] tx_fifo_rd_data;
wire                 tx_done_tick;
wire                 tx_fifo_empty;

// Store parity error in a flip flop as persistent state.
reg  q_rx_parity_err;
wire d_rx_parity_err;

always @(posedge clk, posedge reset)
  begin
    if (reset)
      q_rx_parity_err <= 1'b0;
    else
      q_rx_parity_err <= d_rx_parity_err;
  end

assign parity_err      = q_rx_parity_err;
assign d_rx_parity_err = q_rx_parity_err || rx_parity_err;

// BAUD clock module
uart_baud_clk #(.SYS_CLK_FREQ(SYS_CLK_FREQ),
                .BAUD(BAUD_RATE),
                .BAUD_CLK_OVERSAMPLE_RATE(BAUD_CLK_OVERSAMPLE_RATE)) uart_baud_clk_blk
(
  .clk(clk),
  .reset(reset),
  .baud_clk_tick(baud_clk_tick)
);

// RX (receiver) module
uart_rx #(.DATA_BITS(DATA_BITS),
          .STOP_BITS(STOP_BITS),
          .PARITY_MODE(PARITY_MODE),
          .BAUD_CLK_OVERSAMPLE_RATE(BAUD_CLK_OVERSAMPLE_RATE)) uart_rx_blk
(
  .clk(clk),
  .reset(reset),
  .baud_clk_tick(baud_clk_tick),
  .rx(rx),
  .rx_data(rx_fifo_wr_data),
  .rx_done_tick(rx_done_tick),
  .parity_err(rx_parity_err)
);

// TX (transmitter) module
uart_tx #(.DATA_BITS(DATA_BITS),
          .STOP_BITS(STOP_BITS),
          .PARITY_MODE(PARITY_MODE),
          .BAUD_CLK_OVERSAMPLE_RATE(BAUD_CLK_OVERSAMPLE_RATE)) uart_tx_blk
(
  .clk(clk),
  .reset(reset),
  .baud_clk_tick(baud_clk_tick),
  .tx_start(~tx_fifo_empty),
  .tx_data(tx_fifo_rd_data),
  .tx_done_tick(tx_done_tick),
  .tx(tx)
);

// RX FIFO
fifo #(.DATA_BITS(DATA_BITS),
       .ADDR_BITS(3)) uart_rx_fifo
(
  .clk(clk),
  .reset(reset),
  .rd_en(rd_en),
  .wr_en(rx_done_tick),
  .wr_data(rx_fifo_wr_data),
  .rd_data(rx_data),
  .empty(rx_empty),
  .full()
);

// TX FIFO
fifo #(.DATA_BITS(DATA_BITS),
       .ADDR_BITS(3)) uart_tx_fifo
(
  .clk(clk),
  .reset(reset),
  .rd_en(tx_done_tick),
  .wr_en(wr_en),
  .wr_data(tx_data),
  .rd_data(tx_fifo_rd_data),
  .empty(tx_fifo_empty),
  .full(tx_full)
);

endmodule
module uart_baud_clk
#(
  parameter SYS_CLK_FREQ             = 50000000,
  parameter BAUD                     = 19200,
  parameter BAUD_CLK_OVERSAMPLE_RATE = 16
)
(
  input  wire clk,
  input  wire reset,
  output wire baud_clk_tick
);

localparam [15:0] CLKS_PER_OVERSAMPLE_TICK = (SYS_CLK_FREQ / BAUD) / BAUD_CLK_OVERSAMPLE_RATE;

// Registers
reg  [15:0] q_cnt;
wire [15:0] d_cnt;

always @(posedge clk, posedge reset)
  begin
    if (reset)
      q_cnt <= 0;
    else
      q_cnt <= d_cnt;
  end

assign d_cnt         = (q_cnt == (CLKS_PER_OVERSAMPLE_TICK - 1)) ? 16'h0000 : (q_cnt + 16'h0001);
assign baud_clk_tick = (q_cnt == (CLKS_PER_OVERSAMPLE_TICK - 1)) ? 1'b1     : 1'b0;

endmodule
module vga_sync
(
  input  wire       clk,    // 100Mhz clock signal
  output wire       hsync,  // HSYNC VGA control output
  output wire       vsync,  // VSYNC VGA control output
  output wire       en,     // Indicates when RGB generation circuit should enable (x,y valid)
  output wire [9:0] x,      // Current X position being displayed
  output wire [9:0] y,      // Current Y position being displayed (top = 0)
  output wire [9:0] x_next, // Next X position to be displayed next clock
  output wire [9:0] y_next  // Next Y position to be displayed
);

//
// VGA signal timing parameters.  Taken from http://tinyvga.com/vga-timing/640x480@60Hz.  Note
// that this circuit uses a 25MHz clock instead of specified 25.175MHz clock.  Most displays can
// cope with this out of spec behavior.
//
localparam H_DISP  = 640;  // Number of displayable columns
localparam H_FP    = 16;   // Horizontal front porch in pixel clocks
localparam H_RT    = 96;   // Horizontal retrace (hsync pulse) in pixel clocks
localparam H_BP    = 48;   // Horizontal back porch in pixel clocks
localparam V_DISP  = 480;  // Number of displayable rows
localparam V_FP    = 10;   // Vertical front porch in lines
localparam V_RT    = 2;    // Vertical retrace (vsync pulse) in lines
localparam V_BP    = 29;   // Vertical back porch in lines

// FF for mod-4 counter.  Used to generate a 25MHz pixel enable signal.
reg  [1:0] q_mod4_cnt;
wire [1:0] d_mod4_cnt;

// Horizontal and vertical counters.  Used relative to timings specified in pixels or lines, above.
// Equivalent to x,y position when in the displayable region.
reg  [9:0] q_hcnt, q_vcnt;
wire [9:0] d_hcnt, d_vcnt;

// Output signal FFs.
reg  q_hsync, q_vsync, q_en;
wire d_hsync, d_vsync, d_en;

// FF update logic.
always @(posedge clk)
  begin
    q_mod4_cnt <= d_mod4_cnt;
    q_hcnt     <= d_hcnt;
    q_vcnt     <= d_vcnt;
    q_hsync    <= d_hsync;
    q_vsync    <= d_vsync;
    q_en       <= d_en;
  end

wire pix_pulse;     // 1 clk tick per-pixel
wire line_pulse;    // 1 clk tick per-line (reset to h-pos 0)
wire screen_pulse;  // 1 clk tick per-screen (reset to v-pos 0)

assign d_mod4_cnt = q_mod4_cnt + 2'h1;

assign pix_pulse    = (q_mod4_cnt == 0);
assign line_pulse   = pix_pulse  && (q_hcnt == (H_DISP + H_FP + H_RT + H_BP - 1));
assign screen_pulse = line_pulse && (q_vcnt == (V_DISP + V_FP + V_RT + V_BP - 1));

assign d_hcnt = (line_pulse)   ? 10'h000 : ((pix_pulse)  ? q_hcnt + 10'h001 : q_hcnt);
assign d_vcnt = (screen_pulse) ? 10'h000 : ((line_pulse) ? q_vcnt + 10'h001 : q_vcnt);

assign d_hsync = (q_hcnt >= (H_DISP + H_FP)) && (q_hcnt < (H_DISP + H_FP + H_RT));
assign d_vsync = (q_vcnt >= (V_DISP + V_FP)) && (q_vcnt < (V_DISP + V_FP + V_RT));

assign d_en = (q_hcnt < H_DISP) && (q_vcnt < V_DISP);

// Assign output wires to appropriate FFs.
assign hsync  = q_hsync;
assign vsync  = q_vsync;
assign x      = q_hcnt;
assign y      = q_vcnt;
assign x_next = d_hcnt;
assign y_next = (y == (V_DISP + V_FP + V_RT + V_BP - 10'h001)) ? 10'h000 : (q_vcnt + 10'h001);
assign en     = q_en;

endmodule
module apu_envelope_generator
(
  input  wire       clk_in,       // system clock signal
  input  wire       rst_in,       // reset signal
  input  wire       eg_pulse_in,  // 1 clk pulse for every env gen update
  input  wire [5:0] env_in,       // envelope value (e.g., via $4000)
  input  wire       env_wr_in,    // envelope value write
  input  wire       env_restart,  // envelope restart
  output wire [3:0] env_out       // output volume
);

reg  [5:0] q_reg;
wire [5:0] d_reg;
reg  [3:0] q_cnt,        d_cnt;
reg        q_start_flag, d_start_flag;

always @(posedge clk_in)
  begin
    if (rst_in)
      begin
        q_reg        <= 6'h00;
        q_cnt        <= 4'h0;
        q_start_flag <= 1'b0;
      end
    else
      begin
        q_reg        <= d_reg;
        q_cnt        <= d_cnt;
        q_start_flag <= d_start_flag;
      end
  end

reg  divider_pulse_in;
reg  divider_reload;
wire divider_pulse_out;

apu_div #(.PERIOD_BITS(4)) divider(
  .clk_in(clk_in),
  .rst_in(rst_in),
  .pulse_in(divider_pulse_in),
  .reload_in(divider_reload),
  .period_in(q_reg[3:0]),
  .pulse_out(divider_pulse_out)
);

always @*
  begin
    d_cnt        = q_cnt;
    d_start_flag = q_start_flag;

    divider_pulse_in = 1'b0;
    divider_reload   = 1'b0;

    // When the divider outputs a clock, one of two actions occurs: If the counter is non-zero, it
    // is decremented, otherwise if the loop flag is set, the counter is loaded with 15.
    if (divider_pulse_out)
      begin
        divider_reload = 1'b1;

        if (q_cnt != 4'h0)
          d_cnt = q_cnt - 4'h1;
        else if (q_reg[5])
          d_cnt = 4'hF;
      end

    // When clocked by the frame counter, one of two actions occurs: if the start flag is clear,
    // the divider is clocked, otherwise the start flag is cleared, the counter is loaded with 15,
    // and the divider's period is immediately reloaded.
    if (eg_pulse_in)
      begin
        if (q_start_flag == 1'b0)
          begin
            divider_pulse_in = 1'b1;
          end
        else
          begin
            d_start_flag = 1'b0;
            d_cnt        = 4'hF;
          end
      end

    if (env_restart)
      d_start_flag = 1'b1;
  end

assign d_reg = (env_wr_in) ? env_in : q_reg;

// The envelope unit's volume output depends on the constant volume flag: if set, the envelope
// parameter directly sets the volume, otherwise the counter's value is the current volume.
assign env_out = (q_reg[4]) ? q_reg[3:0] : q_cnt;

endmodule
module apu_frame_counter
(
  input  wire       clk_in,              // system clock signal
  input  wire       rst_in,              // reset signal
  input  wire       cpu_cycle_pulse_in,  // 1 clk pulse on every cpu cycle
  input  wire       apu_cycle_pulse_in,  // 1 clk pulse on every apu cycle
  input  wire [1:0] mode_in,             // mode ([0] = IRQ inhibit, [1] = sequence mode)
  input  wire       mode_wr_in,          // update mode
  output reg        e_pulse_out,         // envelope and linear counter pulse (~240 Hz)
  output reg        l_pulse_out,         // length counter and sweep pulse (~120 Hz)
  output reg        f_pulse_out          // frame pulse (~60Hz, should drive IRQ)
);

reg [14:0] q_apu_cycle_cnt, d_apu_cycle_cnt;
reg        q_seq_mode,      d_seq_mode;
reg        q_irq_inhibit,   d_irq_inhibit;

always @(posedge clk_in)
  begin
    if (rst_in)
      begin
        q_apu_cycle_cnt <= 15'h0000;
        q_seq_mode      <= 1'b0;
        q_irq_inhibit   <= 1'b0;
      end
    else
      begin
        q_apu_cycle_cnt <= d_apu_cycle_cnt;
        q_seq_mode      <= d_seq_mode;
        q_irq_inhibit   <= d_irq_inhibit;
      end
  end

always @*
  begin
    d_apu_cycle_cnt = q_apu_cycle_cnt;
    d_seq_mode      = (mode_wr_in) ? mode_in[1] : q_seq_mode;
    d_irq_inhibit   = (mode_wr_in) ? mode_in[0] : q_irq_inhibit;

    e_pulse_out = 1'b0;
    l_pulse_out = 1'b0;
    f_pulse_out = 1'b0;

    if (apu_cycle_pulse_in)
      begin
        d_apu_cycle_cnt = q_apu_cycle_cnt + 15'h0001;

        if ((q_apu_cycle_cnt == 15'h0E90) || (q_apu_cycle_cnt == 15'h2BB1))
          begin
            e_pulse_out = 1'b1;
          end
        else if (q_apu_cycle_cnt == 15'h1D20)
          begin
            e_pulse_out = 1'b1;
            l_pulse_out = 1'b1;
          end
        else if (!q_seq_mode && (q_apu_cycle_cnt == 15'h3A42))
          begin
            e_pulse_out = 1'b1;
            l_pulse_out = 1'b1;
            f_pulse_out = ~q_irq_inhibit;

            d_apu_cycle_cnt = 15'h0000;
          end
        else if ((q_apu_cycle_cnt == 15'h48d0))
          begin
            e_pulse_out = q_seq_mode;
            l_pulse_out = q_seq_mode;

            d_apu_cycle_cnt = 15'h0000;
          end
      end

      if (cpu_cycle_pulse_in && mode_wr_in)
        d_apu_cycle_cnt = 15'h48d0;
  end

endmodule
module apu_div
#(
  parameter PERIOD_BITS = 16
)
(
  input  wire                   clk_in,     // system clock signal
  input  wire                   rst_in,     // reset signal
  input  wire                   pulse_in,   // input pulse
  input  wire                   reload_in,  // reset counter to period_in (no pulse_out generated)
  input  wire [PERIOD_BITS-1:0] period_in,  // new period value
  output wire                   pulse_out   // divided output pulse
);

reg  [PERIOD_BITS-1:0] q_cnt;
wire [PERIOD_BITS-1:0] d_cnt;

always @(posedge clk_in)
  begin
    if (rst_in)
      q_cnt <= 0;
    else
      q_cnt <= d_cnt;
  end

assign d_cnt     = (reload_in || (pulse_in && (q_cnt == 0))) ? period_in    :
                   (pulse_in)                                ? q_cnt - 1'h1 : q_cnt;
assign pulse_out = pulse_in && (q_cnt == 0);

endmodule
module neorv32_verilog_tb;

  reg clk, nrst; // generators
  wire uart_txd; // serial TX line (default baud rate is 19200)
  wire [7:0] char_data; // character detected by the UART receiver
  wire char_valid; // valid character

  // generator setup
  initial begin
    $display ("neorv32-verilog verification testbench\n");
    clk = 0;
    nrst = 0;
    #100; // active reset for 100 * timescale = 100 ns
    nrst = 1;
    #15_000_000;
    // if we reach this the simulation has failed
    $display("Simulation terminated (time out)!");
    $finish; // terminate
  end

  // clock generator
  always begin
    #5 clk = !clk; // T = 2*5ns -> f = 100MHz
  end

  // unit under test: minimal NEORV32 Verilog wrapper
  // note that there are NO parameters available - the configuration has to be done
  // in the NEORV32 VHDL wrapper *before* synthesizing the Verilog netlist
  neorv32_verilog_wrapper neorv32_verilog_inst (
    .clk_i       (clk),
    .rstn_i      (nrst),
    .uart0_rxd_i (1'b0),
    .uart0_txd_o (uart_txd)
  );

  // simulation UART receiver - outputs all received characters to the simulator console
  uart_sim_receiver #(
    .CLOCK_FREQ (100000000), // clock frequency of the core
    .BAUD_RATE  (19200)      // default baud rate of the NEORV32 bootloader
  ) uart_sim_receiver_inst(
    .clk_i   (clk),
    .txd_i   (uart_txd),
    .data_o  (char_data),
    .valid_o (char_valid)
  );

  // buffer the processor's UART data in a small FIFO-like queue
  reg [7:0] char_buffer [0:6];
  integer i;

  always @(posedge clk) begin
    // update "FIFO"
    if (char_valid == 1'b1) begin
      // top-to-bottom shift
      for (i=6; i>0; i=i-1) begin
        char_buffer[i-1] <= char_buffer[i];
      end
      char_buffer[6] <= char_data;
    end
    // check for result string: "NEORV32" is sent by the default bootloader right after reset
    if ((char_buffer[0] == "N") &&
        (char_buffer[1] == "E") &&
        (char_buffer[2] == "O") &&
        (char_buffer[3] == "R") &&
        (char_buffer[4] == "V") &&
        (char_buffer[5] == "3") &&
        (char_buffer[6] == "2")) begin
      // simulation was successful
      $display (""); // force line break
      $display("Simulation successful!");
      $finish; // terminate
    end
  end

endmodule
module uart_sim_receiver
#(
  parameter CLOCK_FREQ = 100000000, // clock frequency of <clk_i> in Hz
  parameter BAUD_RATE  = 19200      // target baud rate
)
(
  input  wire       clk_i,  // clock input, triggering on rising edge
  input  wire       txd_i,  // UART transmit data
  output wire [7:0] data_o, // character data
  output wire       valid_o // character data valid when set
);

  // duration of a single bit
  localparam UART_BAUD_VAL = CLOCK_FREQ / BAUD_RATE;

  reg     [4:0] uart_rx_sync; // synchronizer shift register
  reg           uart_rx_busy; // busy flag
  reg     [8:0] uart_rx_sreg; // de-serializer
  integer       uart_rx_baud_cnt; // bit-sample counter for baud rate
  integer       uart_rx_bitcnt; // bit counter: 8 data bits, 1 start bit
  wire    [7:0] char = uart_rx_sreg[8:1]; // character data

  // initialize because we don't have a real reset
  initial begin
    uart_rx_sync = 5'b11111;
    uart_rx_busy = 1'b0;
    uart_rx_sreg = 9'b000000000;
    uart_rx_baud_cnt = UART_BAUD_VAL / 2;
    uart_rx_bitcnt = 0;
  end

  // UART receiver
  always @(posedge clk_i) begin
    // synchronizer
    uart_rx_sync <= {uart_rx_sync[3:0], txd_i};
    // arbiter
    if (!uart_rx_busy) begin // idle
      uart_rx_busy     <= 0;
      uart_rx_baud_cnt <= UART_BAUD_VAL / 2;
      uart_rx_bitcnt   <= 9;
      if (uart_rx_sync[4:1] == 4'b1100) begin // start bit (falling edge)?
        uart_rx_busy <= 1;
      end
    end else begin
      if (uart_rx_baud_cnt == 0) begin
        if (uart_rx_bitcnt == 1) begin
          uart_rx_baud_cnt <= UART_BAUD_VAL / 2;
        end else begin
          uart_rx_baud_cnt <= UART_BAUD_VAL;
        end
        // sample 8 data bits and 1 start bit
        if (uart_rx_bitcnt == 0) begin
          uart_rx_busy <= 1'b0; // done
          if ((char >= 32) && (char <= 127)) begin // is a printable char?
            $write ("%c", char);
          end else if (char == 10) begin // Linux line break?
            $display (""); // force terminal line break
          end
        end else begin
          uart_rx_sreg   <= {uart_rx_sync[4], uart_rx_sreg[8:1]};
          uart_rx_bitcnt <= uart_rx_bitcnt - 1;
        end
      end else begin
        uart_rx_baud_cnt <= uart_rx_baud_cnt - 1;
      end
    end
  end

  // character output
  assign data_o = char; // character data
  assign valid_o = ((uart_rx_baud_cnt == 0) && (uart_rx_bitcnt == 0)) ? 1'b1 : 1'b0; // character valid

endmodule // uart_sim_receiver
module test_top ();

reg  PCIE_CLK_N;
reg  PCIE_CLK_P;
wire [7:0] PCIE_RX_N;
wire [7:0] PCIE_RX_P;
wire [7:0] PCIE_TX_N;
wire [7:0] PCIE_TX_P;
reg  PERSTN;
reg  FPGA_SYSCLK_N;
reg  FPGA_SYSCLK_P;
reg  RESET;
wire  UART_RXD_OUT;
wire  UART_TXD_IN;
top_wrapper DUT (
  .PCIE_CLK_N (PCIE_CLK_N),
  .PCIE_CLK_P (PCIE_CLK_P),
  .PCIE_RX_N (PCIE_RX_N),
  .PCIE_RX_P (PCIE_RX_P),
  .PCIE_TX_N (PCIE_TX_N),
  .PCIE_TX_P (PCIE_TX_P),
  .PERSTN (PERSTN),
  .FPGA_SYSCLK_N (FPGA_SYSCLK_N),
  .FPGA_SYSCLK_P (FPGA_SYSCLK_P),
  .RESET (RESET),
  .UART_RXD_OUT (UART_RXD_OUT),
  .UART_TXD_IN (UART_TXD_IN)
);

always
begin
  PCIE_CLK_N = 1;
  #5.0;
  PCIE_CLK_N = 0;
  #5.0;
end
always
begin
  PCIE_CLK_P = 0;
  #5.0;
  PCIE_CLK_P = 1;
  #5.0;
end

always
begin
  FPGA_SYSCLK_N = 0;
  #2.5;
  FPGA_SYSCLK_N = 1;
  #2.5;
end
always
begin
  FPGA_SYSCLK_P = 1;
  #2.5;
  FPGA_SYSCLK_P = 0;
  #2.5;
end

initial
begin
  $display("[%t] : System Reset(test_top/RESET) Is Asserted...", $realtime);
  RESET = 1;
  #5000;
  $display("[%t] : System Reset(test_top/RESET) Is DeAsserted...", $realtime);
  RESET = 0;
end

initial
begin
  $display("[%t] : System Reset(test_top/PERSTN) Is Asserted...", $realtime);
  PERSTN = 0;
  #100;
  $display("[%t] : System Reset(test_top/PERSTN) Is DeAsserted...", $realtime);
  PERSTN = 1;
end
//initial begin
//    $fsdbDumpfile("./testbench.fsdb");
//    $fsdbDumpvars;
//end

initial begin
  $display("V: testbench init.");
end

endmodule
module ram_dp_sc
#(parameter DATA_WIDTH=128, parameter ADDR_WIDTH=9)
(
    input [(DATA_WIDTH-1):0] data,
    input [(ADDR_WIDTH-1):0] read_addr, write_addr,
    input we, clk,
    output reg [(DATA_WIDTH-1):0] q
);

    // Declare the RAM variable
    reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];

    always @ (posedge clk)
    begin
        // Write
        if (we)
            ram[write_addr] <= data;

        // Read (if read_addr == write_addr, return OLD data).  To return
        // NEW data, use = (blocking write) rather than <= (non-blocking write)
        // in the write assignment.  NOTE: NEW data may require extra bypass
        // logic around the RAM.
        q <= ram[read_addr];
    end

endmodule
module simple_counter
#(
    parameter   DATW  = 32
)
(
    input                           i_clk
,   input                           i_rst_n

,   input       [        DATW -1:0] i_init
,   input                           i_rst
,   input                           i_en
,   input                           i_count
,   input                           i_updown        // 0:up, 1:down

,   output      [        DATW -1:0] o_dat
);

    //---------------------------------------------------------------------
    // Constant Declarations
    //---------------------------------------------------------------------


    //---------------------------------------------------------------------
    // Reg/Wire
    //---------------------------------------------------------------------

    reg         [        DATW -1:0] r_cnt           , n_cnt             ;
    reg         [        DATW -1:0] cnt_change;

    always@(*)
    begin: COMBO
        cnt_change          = i_updown ? (r_cnt-1) : (r_cnt+1);
        n_cnt               = i_rst             ? i_init     :
                              (i_en & i_count)  ? cnt_change : r_cnt ;
    end // COMBO

    always@(posedge i_clk or negedge i_rst_n)
    begin: FF
        if ( ~i_rst_n ) begin
            r_cnt          <= i_init;
        end
        else begin
            r_cnt          <= n_cnt;
        end
    end // FF

    // Combo Out
    // Const Out
      
    // Reg   Out
    assign o_dat            = r_cnt;

endmodule
module serving
  (
   input wire 	      i_clk,
   input wire 	      i_rst,
   input wire 	      i_timer_irq,

   output wire [31:0] o_wb_adr,
   output wire [31:0] o_wb_dat,
   output wire [3:0]  o_wb_sel,
   output wire 	      o_wb_we ,
   output wire 	      o_wb_stb,
   input wire [31:0]  i_wb_rdt,
   input wire 	      i_wb_ack);

   parameter memfile = "";
   parameter memsize = 8192;
   parameter sim = 1'b0;
   parameter RESET_STRATEGY = "NONE";
   parameter WITH_CSR = 1;
   localparam regs = 32+WITH_CSR*4;

   localparam rf_width = 8;

   wire [31:0] 	wb_mem_adr;
   wire [31:0] 	wb_mem_dat;
   wire [3:0] 	wb_mem_sel;
   wire 	wb_mem_we;
   wire 	wb_mem_stb;
   wire [31:0] 	wb_mem_rdt;
   wire 	wb_mem_ack;

   wire [6+WITH_CSR:0] rf_waddr;
   wire [rf_width-1:0] rf_wdata;
   wire 	       rf_wen;
   wire [6+WITH_CSR:0] rf_raddr;
   wire [rf_width-1:0] rf_rdata;
   wire		       rf_ren;

   wire [$clog2(memsize)-1:0] sram_waddr;
   wire [rf_width-1:0] sram_wdata;
   wire 	       sram_wen;
   wire [$clog2(memsize)-1:0] sram_raddr;
   wire [rf_width-1:0] sram_rdata;
   wire		       sram_ren;

   serving_ram
     #(.memfile (memfile),
       .depth   (memsize))
   ram
     (// Wishbone interface
      .i_clk (i_clk),
      .i_waddr  (sram_waddr),
      .i_wdata  (sram_wdata),
      .i_wen    (sram_wen),
      .i_raddr  (sram_raddr),
      .o_rdata  (sram_rdata)/*,
      .i_ren    (rf_ren)*/);

   servile_rf_mem_if
     #(.depth   (memsize),
       .rf_regs (regs))
   rf_mem_if
     (// Wishbone interface
      .i_clk (i_clk),
      .i_rst (i_rst),

      .i_waddr  (rf_waddr),
      .i_wdata  (rf_wdata),
      .i_wen    (rf_wen),
      .i_raddr  (rf_raddr),
      .o_rdata  (rf_rdata),
      .i_ren    (rf_ren),

      .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),

      .i_wb_adr (wb_mem_adr[$clog2(memsize)-1:2]),
      .i_wb_stb (wb_mem_stb),
      .i_wb_we  (wb_mem_we) ,
      .i_wb_sel (wb_mem_sel),
      .i_wb_dat (wb_mem_dat),
      .o_wb_rdt (wb_mem_rdt),
      .o_wb_ack (wb_mem_ack));

   servile
     #(.reset_pc (32'h0000_0000),
       .reset_strategy (RESET_STRATEGY),
       .sim (sim),
       .with_csr (WITH_CSR))
   servile
     (
      .i_clk       (i_clk),
      .i_rst       (i_rst),
      .i_timer_irq (i_timer_irq),
      //Memory interface
      .o_wb_mem_adr   (wb_mem_adr),
      .o_wb_mem_dat   (wb_mem_dat),
      .o_wb_mem_sel   (wb_mem_sel),
      .o_wb_mem_we    (wb_mem_we),
      .o_wb_mem_stb   (wb_mem_stb),
      .i_wb_mem_rdt   (wb_mem_rdt),
      .i_wb_mem_ack   (wb_mem_ack),

      //Extension interface
      .o_wb_ext_adr   (o_wb_adr),
      .o_wb_ext_dat   (o_wb_dat),
      .o_wb_ext_sel   (o_wb_sel),
      .o_wb_ext_we    (o_wb_we),
      .o_wb_ext_stb   (o_wb_stb),
      .i_wb_ext_rdt   (i_wb_rdt),
      .i_wb_ext_ack   (i_wb_ack),

      //RF IF
      .o_rf_waddr  (rf_waddr),
      .o_rf_wdata  (rf_wdata),
      .o_rf_wen    (rf_wen),
      .o_rf_raddr  (rf_raddr),
      .o_rf_ren    (rf_ren),
      .i_rf_rdata  (rf_rdata));


endmodule
module serving_ram
  #(//Memory parameters
    parameter depth = 256,
    parameter aw    = $clog2(depth),
    parameter memfile = "")
   (input wire		i_clk,
    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);

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

   always @(posedge i_clk) begin
      if (i_wen) mem[i_waddr]   <= i_wdata;
      o_rdata <= mem[i_raddr];
   end

   initial
     if(|memfile) begin
	$display("Preloading %m from %s", memfile);
	$readmemh(memfile, mem);
     end
endmodule
module serv_immdec
  #(parameter SHARED_RFADDR_IMM_REGS = 1)
  (
   input wire 	     i_clk,
   //State
   input wire 	     i_cnt_en,
   input wire 	     i_cnt_done,
   //Control
   input wire [3:0]  i_immdec_en,
   input wire 	     i_csr_imm_en,
   input wire [3:0]  i_ctrl,
   output wire [4:0] o_rd_addr,
   output wire [4:0] o_rs1_addr,
   output wire [4:0] o_rs2_addr,
   //Data
   output wire 	     o_csr_imm,
   output wire 	     o_imm,
   //External
   input wire 	     i_wb_en,
   input wire [31:7] i_wb_rdt);

   reg 		     imm31;

   reg [8:0]  imm19_12_20;
   reg 	      imm7;
   reg [5:0]  imm30_25;
   reg [4:0]  imm24_20;
   reg [4:0]  imm11_7;

   assign o_csr_imm = imm19_12_20[4];

   wire       signbit = imm31 & !i_csr_imm_en;

   generate
      if (SHARED_RFADDR_IMM_REGS) begin : gen_shared_imm_regs
	 assign o_rs1_addr = imm19_12_20[8:4];
	 assign o_rs2_addr = imm24_20;
	 assign o_rd_addr  = imm11_7;

	 always @(posedge i_clk) begin
	    if (i_wb_en) begin
	       /* CSR immediates are always zero-extended, hence clear the signbit */
	       imm31     <= i_wb_rdt[31];
	    end
	    if (i_wb_en | (i_cnt_en & i_immdec_en[1]))
	      imm19_12_20 <= i_wb_en ? {i_wb_rdt[19:12],i_wb_rdt[20]} : {i_ctrl[3] ? signbit : imm24_20[0], imm19_12_20[8:1]};
	    if (i_wb_en | (i_cnt_en))
	      imm7        <= i_wb_en ? i_wb_rdt[7]                    : signbit;

	    if (i_wb_en | (i_cnt_en & i_immdec_en[3]))
	      imm30_25    <= i_wb_en ? i_wb_rdt[30:25] : {i_ctrl[2] ? imm7 : i_ctrl[1] ? signbit : imm19_12_20[0], imm30_25[5:1]};

	    if (i_wb_en | (i_cnt_en & i_immdec_en[2]))
	      imm24_20    <= i_wb_en ? i_wb_rdt[24:20] : {imm30_25[0], imm24_20[4:1]};

	    if (i_wb_en | (i_cnt_en & i_immdec_en[0]))
	      imm11_7     <= i_wb_en ? i_wb_rdt[11:7] : {imm30_25[0], imm11_7[4:1]};
	 end
      end else begin : gen_separate_imm_regs
	 reg [4:0]  rd_addr;
	 reg [4:0]  rs1_addr;
	 reg [4:0]  rs2_addr;

	 assign o_rd_addr  = rd_addr;
	 assign o_rs1_addr = rs1_addr;
	 assign o_rs2_addr = rs2_addr;
	 always @(posedge i_clk) begin
	    if (i_wb_en) begin
	       /* CSR immediates are always zero-extended, hence clear the signbit */
	       imm31       <= i_wb_rdt[31];
	       imm19_12_20 <= {i_wb_rdt[19:12],i_wb_rdt[20]};
	       imm7        <= i_wb_rdt[7];
	       imm30_25    <= i_wb_rdt[30:25];
	       imm24_20    <= i_wb_rdt[24:20];
	       imm11_7     <= i_wb_rdt[11:7];

               rd_addr  <= i_wb_rdt[11:7];
               rs1_addr <= i_wb_rdt[19:15];
               rs2_addr <= i_wb_rdt[24:20];
	    end
	    if (i_cnt_en) begin
	       imm19_12_20 <= {i_ctrl[3] ? signbit : imm24_20[0], imm19_12_20[8:1]};
	       imm7        <= signbit;
	       imm30_25    <= {i_ctrl[2] ? imm7 : i_ctrl[1] ? signbit : imm19_12_20[0], imm30_25[5:1]};
	       imm24_20    <= {imm30_25[0], imm24_20[4:1]};
	       imm11_7     <= {imm30_25[0], imm11_7[4:1]};
	    end
	 end
      end
   endgenerate

	 assign o_imm = i_cnt_done ? signbit : i_ctrl[0] ? imm11_7[0] : imm24_20[0];

endmodule
module serv_bufreg2
  (
   input wire 	      i_clk,
   //State
   input wire 	      i_en,
   input wire 	      i_init,
   input wire 	      i_cnt_done,
   input wire [1:0]   i_lsb,
   input wire 	      i_byte_valid,
   output wire 	      o_sh_done,
   output wire 	      o_sh_done_r,
   //Control
   input wire 	      i_op_b_sel,
   input wire 	      i_shift_op,
   //Data
   input wire 	      i_rs2,
   input wire 	      i_imm,
   output wire 	      o_op_b,
   output wire 	      o_q,
   //External
   output wire [31:0] o_dat,
   input wire 	      i_load,
   input wire [31:0]  i_dat);

   reg [31:0] 	 dat;

   assign o_op_b = i_op_b_sel ? i_rs2 : i_imm;

   wire 	 dat_en = i_shift_op | (i_en & i_byte_valid);

   /* The dat register has three different use cases for store, load and
    shift operations.
    store : Data to be written is shifted to the correct position in dat during
            init by dat_en and is presented on the data bus as o_wb_dat
    load  : Data from the bus gets latched into dat during i_wb_ack and is then
            shifted out at the appropriate time to end up in the correct
            position in rd
    shift : Data is shifted in during init. After that, the six LSB are used as
            a downcounter (with bit 5 initially set to 0) that triggers
            o_sh_done and o_sh_done_r when they wrap around to indicate that
            the requested number of shifts have been performed
    */
   wire [5:0] dat_shamt = (i_shift_op & !i_init) ?
	      //Down counter mode
	      dat[5:0]-1 :
	      //Shift reg mode with optional clearing of bit 5
	      {dat[6] & !(i_shift_op & i_cnt_done),dat[5:1]};

   assign o_sh_done = dat_shamt[5];
   assign o_sh_done_r = dat[5];

   assign o_q =
	       ((i_lsb == 2'd3) & dat[24]) |
	       ((i_lsb == 2'd2) & dat[16]) |
	       ((i_lsb == 2'd1) & dat[8]) |
	       ((i_lsb == 2'd0) & dat[0]);

   assign o_dat = dat;

   always @(posedge i_clk) begin
      if (dat_en | i_load)
	dat <= i_load ? i_dat : {o_op_b, dat[31:7], dat_shamt};
   end

endmodule
module serv_aligner
   (
    input wire clk,
    input wire rst,
    // serv_top
    input  wire [31:0]  i_ibus_adr,
    input  wire         i_ibus_cyc,
    output wire [31:0]  o_ibus_rdt,
    output wire         o_ibus_ack,
    // serv_rf_top
    output wire [31:0]  o_wb_ibus_adr,
    output wire         o_wb_ibus_cyc,
    input  wire [31:0]  i_wb_ibus_rdt,
    input  wire         i_wb_ibus_ack);

    wire [31:0] ibus_rdt_concat;
    wire        ack_en;

    reg  [15:0] lower_hw;
    reg         ctrl_misal ;

    /* From SERV core to Memory

    o_wb_ibus_adr: Carries address of instruction to memory. In case of misaligned access,
    which is caused by pc+2 due to compressed instruction, next instruction is fetched
    by pc+4 and concatenation is done to make the instruction aligned.

    o_wb_ibus_cyc: Simply forwarded from SERV to Memory and is only altered by memory or SERV core.
    */
    assign o_wb_ibus_adr = ctrl_misal ? (i_ibus_adr+32'b100) : i_ibus_adr;
    assign o_wb_ibus_cyc = i_ibus_cyc;

    /* From Memory to SERV core

        o_ibus_ack: Instruction bus acknowledge is send to SERV only when the aligned instruction,
        either compressed or un-compressed, is ready to dispatch.

        o_ibus_rdt: Carries the instruction from memory to SERV core. It can be either aligned
        instruction coming from memory or made aligned by two bus transactions and concatenation.
    */
    assign o_ibus_ack = i_wb_ibus_ack & ack_en;
    assign o_ibus_rdt = ctrl_misal ? ibus_rdt_concat : i_wb_ibus_rdt;

    /* 16-bit register used to hold the upper half word of the current instruction in-case
       concatenation will be required with the upper half word of upcoming instruction
    */
    always @(posedge clk) begin
        if(i_wb_ibus_ack)begin
            lower_hw <= i_wb_ibus_rdt[31:16];
        end
    end

    assign ibus_rdt_concat = {i_wb_ibus_rdt[15:0],lower_hw};

    /* Two control signals: ack_en, ctrl_misal are set to control the bus transactions between
    SERV core and the memory
    */
    assign ack_en   = !(i_ibus_adr[1] & !ctrl_misal);

    always @(posedge clk ) begin
        if(rst)
            ctrl_misal <= 0;
        else if(i_wb_ibus_ack & i_ibus_adr[1])
            ctrl_misal <= !ctrl_misal;
    end

endmodule
module serv_mem_if
  #(
    parameter [0:0] WITH_CSR = 1,
    parameter	    W = 1,
    parameter	    B = W-1
  )
  (
   input wire 	     i_clk,
   //State
   input wire [1:0]  i_bytecnt,
   input wire [1:0]  i_lsb,
   output wire 	     o_byte_valid,
   output wire 	     o_misalign,
   //Control
   input wire 	     i_signed,
   input wire 	     i_word,
   input wire 	     i_half,
   //MDU
   input wire 	     i_mdu_op,
   //Data
   input wire [B:0] i_bufreg2_q,
   output wire [B:0] o_rd,
   //External interface
   output wire [3:0] o_wb_sel);

   reg signbit;

   /*
    Before a store operation, the data to be written needs to be shifted into
    place. Depending on the address alignment, we need to shift different
    amounts. One formula for calculating this is to say that we shift when
    i_lsb + i_bytecnt < 4. Unfortunately, the synthesis tools don't seem to be
    clever enough so the hideous expression below is used to achieve the same
    thing in a more optimal way.
    */
   assign o_byte_valid
     = (!i_lsb[0] & !i_lsb[1])         |
       (!i_bytecnt[0] & !i_bytecnt[1]) |
       (!i_bytecnt[1] & !i_lsb[1])     |
       (!i_bytecnt[1] & !i_lsb[0])     |
       (!i_bytecnt[0] & !i_lsb[1]);

   wire dat_valid =
	i_mdu_op |
	i_word |
	(i_bytecnt == 2'b00) |
	(i_half & !i_bytecnt[1]);

   assign o_rd = dat_valid ? i_bufreg2_q : {W{i_signed & signbit}};

   assign o_wb_sel[3] = (i_lsb == 2'b11) | i_word | (i_half & i_lsb[1]);
   assign o_wb_sel[2] = (i_lsb == 2'b10) | i_word;
   assign o_wb_sel[1] = (i_lsb == 2'b01) | i_word | (i_half & !i_lsb[1]);
   assign o_wb_sel[0] = (i_lsb == 2'b00);

   always @(posedge i_clk) begin
      if (dat_valid)
        signbit <= i_bufreg2_q[B];
   end

   /*
    mem_misalign is checked after the init stage to decide whether to do a data
    bus transaction or go to the trap state. It is only guaranteed to be correct
    at this time
    */
   assign o_misalign = WITH_CSR & ((i_lsb[0] & (i_word | i_half)) | (i_lsb[1] & i_word));

endmodule
module serv_bufreg #(
      parameter [0:0] MDU = 0,
      parameter W = 1,
      parameter B = W-1
)(
   input wire 	      i_clk,
   //State
   input wire 	      i_cnt0,
   input wire 	      i_cnt1,
   input wire 	      i_en,
   input wire 	      i_init,
   input wire           i_mdu_op,
   output wire [1:0]    o_lsb,
   //Control
   input wire 	      i_rs1_en,
   input wire 	      i_imm_en,
   input wire 	      i_clr_lsb,
   input wire 	      i_sh_signed,
   //Data
   input wire [B:0] i_rs1,
   input wire [B:0] i_imm,
   output wire [B:0] o_q,
   //External
   output wire [31:0] o_dbus_adr,
   //Extension
   output wire [31:0] o_ext_rs1);

   wire		      c;
   wire [B:0]	      q;
   reg [B:0]	      c_r;
   reg [31:0]	      data;
   wire [B:0]	      clr_lsb;

   assign clr_lsb[0] = i_cnt0 & i_clr_lsb;

   assign {c,q} = {1'b0,(i_rs1 & {W{i_rs1_en}})} + {1'b0,(i_imm & {W{i_imm_en}} & ~clr_lsb)} + c_r;

   always @(posedge i_clk) begin
      //Make sure carry is cleared before loading new data
      c_r    <= {W{1'b0}};
      c_r[0] <= c & i_en;
   end

   reg [1:0] lsb;

   generate
      if (W == 1) begin : gen_w_eq_1
	 always @(posedge i_clk) begin
	    if (i_en)
	      data[31:2] <= {i_init ? q : {W{data[31] & i_sh_signed}}, data[31:3]};

	    if (i_init ? (i_cnt0 | i_cnt1) : i_en)
	      data[1:0] <= {i_init ? q : data[2], data[1]};
	 end
	 always @(*) lsb = data[1:0];
	 assign o_q = data[0] & {W{i_en}};
      end
   endgenerate


   assign o_dbus_adr = {data[31:2], 2'b00};
   assign o_ext_rs1  = data;
   assign o_lsb = (MDU & i_mdu_op) ? 2'b00 : lsb;

endmodule
module serv_alu
  #(
   parameter W = 1,
   parameter B = W-1
  )
  (
   input wire 	    clk,
   //State
   input wire 	    i_en,
   input wire 	    i_cnt0,
   output wire 	    o_cmp,
   //Control
   input wire 	    i_sub,
   input wire [1:0] i_bool_op,
   input wire 	    i_cmp_eq,
   input wire 	    i_cmp_sig,
   input wire [2:0] i_rd_sel,
   //Data
   input wire  [B:0] i_rs1,
   input wire  [B:0] i_op_b,
   input wire  [B:0] i_buf,
   output wire [B:0] o_rd);

   wire [B:0]  result_add;
   wire [B:0]  result_slt;

   reg 	       cmp_r;

   wire        add_cy;
   reg [B:0]   add_cy_r;

   //Sign-extended operands
   wire rs1_sx  = i_rs1[B] & i_cmp_sig;
   wire op_b_sx = i_op_b[B]  & i_cmp_sig;

   wire [B:0] add_b = i_op_b^{W{i_sub}};

   assign {add_cy,result_add}   = i_rs1+add_b+add_cy_r;

   wire result_lt = rs1_sx + ~op_b_sx + add_cy;

   wire result_eq = !(|result_add) & (cmp_r | i_cnt0);

   assign o_cmp = i_cmp_eq ? result_eq : result_lt;

   /*
    The result_bool expression implements the following operations between
    i_rs1 and i_op_b depending on the value of i_bool_op

    00 xor
    01 0
    10 or
    11 and

    i_bool_op will be 01 during shift operations, so by outputting zero under
    this condition we can safely or result_bool with i_buf
    */
   wire [B:0] result_bool = ((i_rs1 ^ i_op_b) & ~{W{i_bool_op[0]}}) | ({W{i_bool_op[1]}} & i_op_b & i_rs1);

   assign result_slt[0] = cmp_r & i_cnt0;
   generate
      if (W>1) begin : gen_w_gt_1
	 assign result_slt[B:1] = {B{1'b0}};
      end
   endgenerate

   assign o_rd = i_buf |
                 ({W{i_rd_sel[0]}} & result_add) |
                 ({W{i_rd_sel[1]}} & result_slt) |
                 ({W{i_rd_sel[2]}} & result_bool);

   always @(posedge clk) begin
      add_cy_r    <= {W{1'b0}};
      add_cy_r[0] <= i_en ? add_cy : i_sub;

      if (i_en)
	cmp_r <= o_cmp;
   end

endmodule
module uart_decoder
  #(parameter BAUD_RATE = 115200)
   (input rx);

   localparam T = 1000000000/BAUD_RATE;

   integer i;
   reg [7:0] ch;

   initial 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
endmodule
module servant_tb;

   parameter memfile = "hello_uart.hex";
   parameter memsize = 8192;
   parameter with_csr = 1;

   reg wb_clk = 1'b0;
   reg wb_rst = 1'b1;

   wire q;

   always  #31 wb_clk <= !wb_clk;
   initial #62 wb_rst <= 1'b0;

   vlog_tb_utils vtu();

   uart_decoder #(57600) uart_decoder (q);

   servant_sim
     #(.memfile  (memfile),
       .memsize  (memsize),
       .with_csr (with_csr))
   dut
     (.wb_clk (wb_clk),
      .wb_rst (wb_rst),
      .pc_adr (),
      .pc_vld (),
      .q      (q));

endmodule