dakies/OSS_Verilog huggingface dataset:
module cclk_detector #(
    parameter CLK_RATE = 50000000
    )(
    input clk,
    input rst,
    input cclk,
    output ready
);

    parameter CTR_SIZE = $clog2(CLK_RATE/50000);

    reg [CTR_SIZE-1:0] ctr_d, ctr_q;
    reg ready_d, ready_q;

    assign ready = ready_q;

    // ready should only go high once cclk has been high for a while
    // if cclk ever falls, ready should go low again
    always @(ctr_q or cclk) begin
        ready_d = 1'b0;
        if (cclk == 1'b0) begin // when cclk is 0 reset the counter
            ctr_d = 1'b0;
        end else if (ctr_q != {CTR_SIZE{1'b1}}) begin
            ctr_d = ctr_q + 1'b1; // counter isn't max value yet
        end else begin
            ctr_d = ctr_q;
            ready_d = 1'b1; // counter reached the max, we are ready
        end

    end

    always @(posedge clk) begin
        if (rst) begin
            ctr_q <= 1'b0;
            ready_q <= 1'b0;
        end else begin
            ctr_q <= ctr_d;
            ready_q <= ready_d;
        end
    end
endmodule
module mojo_top(
    // 50MHz clock input
    input clk,
    // Input from reset button (active low)
    input rst_n,
    // cclk input from AVR, high when AVR is ready
    input cclk,
    // Outputs to the 8 onboard LEDs
    output[7:0]led,
    // AVR SPI connections
    output spi_miso,
    input spi_ss,
    input spi_mosi,
    input spi_sck,
    // AVR ADC channel select
    output [3:0] spi_channel,
    // Serial connections
    input avr_tx, // AVR Tx => FPGA Rx
    output avr_rx, // AVR Rx => FPGA Tx
    input avr_rx_busy // AVR Rx buffer full
    );

wire rst = ~rst_n; // make reset active high

// these signals should be high-z when not used
assign spi_miso = 1'bz;
assign avr_rx = 1'bz;
assign spi_channel = 4'bzzzz;

assign led = 8'b0;

endmodule
module serial_tx #(
        parameter CLK_PER_BIT = 50
    )(
        input clk,
        input rst,
        output tx,
        input block,
        output busy,
        input [7:0] data,
        input new_data
    );

    // clog2 is 'ceiling of log base 2' which gives you the number of bits needed to store a value
    parameter CTR_SIZE = $clog2(CLK_PER_BIT);

    localparam STATE_SIZE = 2;
    localparam IDLE = 2'd0,
    START_BIT = 2'd1,
    DATA = 2'd2,
    STOP_BIT = 2'd3;

    reg [CTR_SIZE-1:0] ctr_d, ctr_q;
    reg [2:0] bit_ctr_d, bit_ctr_q;
    reg [7:0] data_d, data_q;
    reg [STATE_SIZE-1:0] state_d, state_q = IDLE;
    reg tx_d, tx_q;
    reg busy_d, busy_q;
    reg block_d, block_q;

    assign tx = tx_q;
    assign busy = busy_q;

    always @(*) begin
        block_d = block;
        ctr_d = ctr_q;
        bit_ctr_d = bit_ctr_q;
        data_d = data_q;
        state_d = state_q;
        busy_d = busy_q;

        case (state_q)
            IDLE: begin
                if (block_q) begin
                    busy_d = 1'b1;
                    tx_d = 1'b1;
                end else begin
                    busy_d = 1'b0;
                    tx_d = 1'b1;
                    bit_ctr_d = 3'b0;
                    ctr_d = 1'b0;
                    if (new_data) begin
                        data_d = data;
                        state_d = START_BIT;
                        busy_d = 1'b1;
                    end
                end
            end
            START_BIT: begin
                busy_d = 1'b1;
                ctr_d = ctr_q + 1'b1;
                tx_d = 1'b0;
                if (ctr_q == CLK_PER_BIT - 1) begin
                    ctr_d = 1'b0;
                    state_d = DATA;
                end
            end
            DATA: begin
                busy_d = 1'b1;
                tx_d = data_q[bit_ctr_q];
                ctr_d = ctr_q + 1'b1;
                if (ctr_q == CLK_PER_BIT - 1) begin
                    ctr_d = 1'b0;
                    bit_ctr_d = bit_ctr_q + 1'b1;
                    if (bit_ctr_q == 7) begin
                        state_d = STOP_BIT;
                    end
                end
            end
            STOP_BIT: begin
                busy_d = 1'b1;
                tx_d = 1'b1;
                ctr_d = ctr_q + 1'b1;
                if (ctr_q == CLK_PER_BIT - 1) begin
                    state_d = IDLE;
                end
            end
            default: begin
                state_d = IDLE;
            end
        endcase
    end

    always @(posedge clk) begin
        if (rst) begin
            state_q <= IDLE;
            tx_q <= 1'b1;
        end else begin
            state_q <= state_d;
            tx_q <= tx_d;
        end

        block_q <= block_d;
        data_q <= data_d;
        bit_ctr_q <= bit_ctr_d;
        ctr_q <= ctr_d;
        busy_q <= busy_d;
    end

endmodule
module serial_rx #(
        parameter CLK_PER_BIT = 50
    )(
        input clk,
        input rst,
        input rx,
        output [7:0] data,
        output new_data
    );

    // clog2 is 'ceiling of log base 2' which gives you the number of bits needed to store a value
    parameter CTR_SIZE = $clog2(CLK_PER_BIT);

    localparam STATE_SIZE = 2;
    localparam IDLE = 2'd0,
    WAIT_HALF = 2'd1,
    WAIT_FULL = 2'd2,
    WAIT_HIGH = 2'd3;

    reg [CTR_SIZE-1:0] ctr_d, ctr_q;
    reg [2:0] bit_ctr_d, bit_ctr_q;
    reg [7:0] data_d, data_q;
    reg new_data_d, new_data_q;
    reg [STATE_SIZE-1:0] state_d, state_q = IDLE;
    reg rx_d, rx_q;

    assign new_data = new_data_q;
    assign data = data_q;

    always @(*) begin
        rx_d = rx;
        state_d = state_q;
        ctr_d = ctr_q;
        bit_ctr_d = bit_ctr_q;
        data_d = data_q;
        new_data_d = 1'b0;

        case (state_q)
            IDLE: begin
                bit_ctr_d = 3'b0;
                ctr_d = 1'b0;
                if (rx_q == 1'b0) begin
                    state_d = WAIT_HALF;
                end
            end
            WAIT_HALF: begin
                ctr_d = ctr_q + 1'b1;
                if (ctr_q == (CLK_PER_BIT >> 1)) begin
                    ctr_d = 1'b0;
                    state_d = WAIT_FULL;
                end
            end
            WAIT_FULL: begin
                ctr_d = ctr_q + 1'b1;
                if (ctr_q == CLK_PER_BIT - 1) begin
                    data_d = {rx_q, data_q[7:1]};
                    bit_ctr_d = bit_ctr_q + 1'b1;
                    ctr_d = 1'b0;
                    if (bit_ctr_q == 3'd7) begin
                        state_d = WAIT_HIGH;
                        new_data_d = 1'b1;
                    end
                end
            end
            WAIT_HIGH: begin
                if (rx_q == 1'b1) begin
                    state_d = IDLE;
                end
            end
            default: begin
                state_d = IDLE;
            end
        endcase

    end

    always @(posedge clk) begin
        if (rst) begin
            ctr_q <= 1'b0;
            bit_ctr_q <= 3'b0;
            new_data_q <= 1'b0;
            state_q <= IDLE;
        end else begin
            ctr_q <= ctr_d;
            bit_ctr_q <= bit_ctr_d;
            new_data_q <= new_data_d;
            state_q <= state_d;
        end

        rx_q <= rx_d;
        data_q <= data_d;
    end

endmodule
module spi_slave(
    input clk,
    input rst,
    input ss,
    input mosi,
    output miso,
    input sck,
    output done,
    input [7:0] din,
    output [7:0] dout
    );

reg mosi_d, mosi_q;
reg ss_d, ss_q;
reg sck_d, sck_q;
reg sck_old_d, sck_old_q;
reg [7:0] data_d, data_q;
reg done_d, done_q;
reg [2:0] bit_ct_d, bit_ct_q;
reg [7:0] dout_d, dout_q;
reg miso_d, miso_q;

assign miso = miso_q;
assign done = done_q;
assign dout = dout_q;

always @(*) begin
    ss_d = ss;
    mosi_d = mosi;
    miso_d = miso_q;
    sck_d = sck;
    sck_old_d = sck_q;
    data_d = data_q;
    done_d = 1'b0;
    bit_ct_d = bit_ct_q;
    dout_d = dout_q;

    if (ss_q) begin
        bit_ct_d = 3'b0;
        data_d = din;
        miso_d = data_q[7];
    end else begin
        if (!sck_old_q && sck_q) begin // rising edge
            data_d = {data_q[6:0], mosi_q};
            bit_ct_d = bit_ct_q + 1'b1;
            if (bit_ct_q == 3'b111) begin
                dout_d = {data_q[6:0], mosi_q};
                done_d = 1'b1;
                data_d = din;
            end
        end else if (sck_old_q && !sck_q) begin // falling edge
            miso_d = data_q[7];
        end
    end
end

always @(posedge clk) begin
    if (rst) begin
        done_q <= 1'b0;
        bit_ct_q <= 3'b0;
        dout_q <= 8'b0;
        miso_q <= 1'b1;
    end else begin
        done_q <= done_d;
        bit_ct_q <= bit_ct_d;
        dout_q <= dout_d;
        miso_q <= miso_d;
    end

    sck_q <= sck_d;
    mosi_q <= mosi_d;
    ss_q <= ss_d;
    data_q <= data_d;
    sck_old_q <= sck_old_d;

end


endmodule
module sha256_k_constants(
                          input wire  [5 : 0] round,
                          output wire [31 : 0] K
                         );

  //----------------------------------------------------------------
  // Wires.
  //----------------------------------------------------------------
  reg [31 : 0] tmp_K;


  //----------------------------------------------------------------
  // Concurrent connectivity for ports etc.
  //----------------------------------------------------------------
  assign K = tmp_K;


  //----------------------------------------------------------------
  // round_mux
  //----------------------------------------------------------------
  always @*
    begin : round_mux
      case(round)
        00: tmp_K = 32'h428a2f98;
        01: tmp_K = 32'h71374491;
        02: tmp_K = 32'hb5c0fbcf;
        03: tmp_K = 32'he9b5dba5;
        04: tmp_K = 32'h3956c25b;
        05: tmp_K = 32'h59f111f1;
        06: tmp_K = 32'h923f82a4;
        07: tmp_K = 32'hab1c5ed5;
        08: tmp_K = 32'hd807aa98;
        09: tmp_K = 32'h12835b01;
        10: tmp_K = 32'h243185be;
        11: tmp_K = 32'h550c7dc3;
        12: tmp_K = 32'h72be5d74;
        13: tmp_K = 32'h80deb1fe;
        14: tmp_K = 32'h9bdc06a7;
        15: tmp_K = 32'hc19bf174;
        16: tmp_K = 32'he49b69c1;
        17: tmp_K = 32'hefbe4786;
        18: tmp_K = 32'h0fc19dc6;
        19: tmp_K = 32'h240ca1cc;
        20: tmp_K = 32'h2de92c6f;
        21: tmp_K = 32'h4a7484aa;
        22: tmp_K = 32'h5cb0a9dc;
        23: tmp_K = 32'h76f988da;
        24: tmp_K = 32'h983e5152;
        25: tmp_K = 32'ha831c66d;
        26: tmp_K = 32'hb00327c8;
        27: tmp_K = 32'hbf597fc7;
        28: tmp_K = 32'hc6e00bf3;
        29: tmp_K = 32'hd5a79147;
        30: tmp_K = 32'h06ca6351;
        31: tmp_K = 32'h14292967;
        32: tmp_K = 32'h27b70a85;
        33: tmp_K = 32'h2e1b2138;
        34: tmp_K = 32'h4d2c6dfc;
        35: tmp_K = 32'h53380d13;
        36: tmp_K = 32'h650a7354;
        37: tmp_K = 32'h766a0abb;
        38: tmp_K = 32'h81c2c92e;
        39: tmp_K = 32'h92722c85;
        40: tmp_K = 32'ha2bfe8a1;
        41: tmp_K = 32'ha81a664b;
        42: tmp_K = 32'hc24b8b70;
        43: tmp_K = 32'hc76c51a3;
        44: tmp_K = 32'hd192e819;
        45: tmp_K = 32'hd6990624;
        46: tmp_K = 32'hf40e3585;
        47: tmp_K = 32'h106aa070;
        48: tmp_K = 32'h19a4c116;
        49: tmp_K = 32'h1e376c08;
        50: tmp_K = 32'h2748774c;
        51: tmp_K = 32'h34b0bcb5;
        52: tmp_K = 32'h391c0cb3;
        53: tmp_K = 32'h4ed8aa4a;
        54: tmp_K = 32'h5b9cca4f;
        55: tmp_K = 32'h682e6ff3;
        56: tmp_K = 32'h748f82ee;
        57: tmp_K = 32'h78a5636f;
        58: tmp_K = 32'h84c87814;
        59: tmp_K = 32'h8cc70208;
        60: tmp_K = 32'h90befffa;
        61: tmp_K = 32'ha4506ceb;
        62: tmp_K = 32'hbef9a3f7;
        63: tmp_K = 32'hc67178f2;
      endcase // case (round)
    end // block: round_mux
endmodule // sha256_k_constants
module rf2_256x128_wm1_rtl_top (
          CENYA, 
          AYA, 
          CENYB, 
          WENYB, 
          AYB, 
          QA, 
          SOA, 
          SOB, 
          CLKA, 
          CENA, 
          AA, 
          CLKB, 
          CENB, 
          WENB, 
          AB, 
          DB, 
          EMAA, 
          EMASA, 
          EMAB, 
          TENA, 
          TCENA, 
          TAA, 
          TENB, 
          TCENB, 
          TWENB, 
          TAB, 
          TDB, 
          RET1N, 
          SIA, 
          SEA, 
          DFTRAMBYP, 
          SIB, 
          SEB, 
          COLLDISN
   );

   output                   CENYA;
   output [7:0]             AYA;
   output                   CENYB;
   output [127:0]           WENYB;
   output [7:0]             AYB;
   output [127:0]           QA;
   output [1:0]             SOA;
   output [1:0]             SOB;
   input                    CLKA;
   input                    CENA;
   input [7:0]              AA;
   input                    CLKB;
   input                    CENB;
   input [127:0]            WENB;
   input [7:0]              AB;
   input [127:0]            DB;
   input [2:0]              EMAA;
   input                    EMASA;
   input [2:0]              EMAB;
   input                    TENA;
   input                    TCENA;
   input [7:0]              TAA;
   input                    TENB;
   input                    TCENB;
   input [127:0]            TWENB;
   input [7:0]              TAB;
   input [127:0]            TDB;
   input                    RET1N;
   input [1:0]              SIA;
   input                    SEA;
   input                    DFTRAMBYP;
   input [1:0]              SIB;
   input                    SEB;
   input                    COLLDISN;
   wire [127:0]             QOA;
   wire [127:0]             DIB;

   assign QA = QOA;
   assign DIB = DB;
   rf2_256x128_wm1_fr_top u0 (
         .CENYA(CENYA),
         .AYA(AYA),
         .CENYB(CENYB),
         .WENYB(WENYB),
         .AYB(AYB),
         .QOA(QOA),
         .SOA(SOA),
         .SOB(SOB),
         .CLKA(CLKA),
         .CENA(CENA),
         .AA(AA),
         .CLKB(CLKB),
         .CENB(CENB),
         .WENB(WENB),
         .AB(AB),
         .DIB(DIB),
         .EMAA(EMAA),
         .EMASA(EMASA),
         .EMAB(EMAB),
         .TENA(TENA),
         .TCENA(TCENA),
         .TAA(TAA),
         .TENB(TENB),
         .TCENB(TCENB),
         .TWENB(TWENB),
         .TAB(TAB),
         .TDB(TDB),
         .RET1N(RET1N),
         .SIA(SIA),
         .SEA(SEA),
         .DFTRAMBYP(DFTRAMBYP),
         .SIB(SIB),
         .SEB(SEB),
         .COLLDISN(COLLDISN)
);

endmodule
module rf2_256x128_wm1_fr_top (
          CENYA, 
          AYA, 
          CENYB, 
          WENYB, 
          AYB, 
          QOA, 
          SOA, 
          SOB, 
          CLKA, 
          CENA, 
          AA, 
          CLKB, 
          CENB, 
          WENB, 
          AB, 
          DIB, 
          EMAA, 
          EMASA, 
          EMAB, 
          TENA, 
          TCENA, 
          TAA, 
          TENB, 
          TCENB, 
          TWENB, 
          TAB, 
          TDB, 
          RET1N, 
          SIA, 
          SEA, 
          DFTRAMBYP, 
          SIB, 
          SEB, 
          COLLDISN
   );

   output                   CENYA;
   output [7:0]             AYA;
   output                   CENYB;
   output [127:0]           WENYB;
   output [7:0]             AYB;
   output [127:0]           QOA;
   output [1:0]             SOA;
   output [1:0]             SOB;
   input                    CLKA;
   input                    CENA;
   input [7:0]              AA;
   input                    CLKB;
   input                    CENB;
   input [127:0]            WENB;
   input [7:0]              AB;
   input [127:0]            DIB;
   input [2:0]              EMAA;
   input                    EMASA;
   input [2:0]              EMAB;
   input                    TENA;
   input                    TCENA;
   input [7:0]              TAA;
   input                    TENB;
   input                    TCENB;
   input [127:0]            TWENB;
   input [7:0]              TAB;
   input [127:0]            TDB;
   input                    RET1N;
   input [1:0]              SIA;
   input                    SEA;
   input                    DFTRAMBYP;
   input [1:0]              SIB;
   input                    SEB;
   input                    COLLDISN;

   wire [127:0]    DB;
   wire [127:0]    QA;

   assign DB=DIB;
   assign QOA=QA;
   rf2_256x128_wm1 u0 (
         .CENYA(CENYA),
         .AYA(AYA),
         .CENYB(CENYB),
         .WENYB(WENYB),
         .AYB(AYB),
         .QA(QA),
         .SOA(SOA),
         .SOB(SOB),
         .CLKA(CLKA),
         .CENA(CENA),
         .AA(AA),
         .CLKB(CLKB),
         .CENB(CENB),
         .WENB(WENB),
         .AB(AB),
         .DB(DB),
         .EMAA(EMAA),
         .EMASA(EMASA),
         .EMAB(EMAB),
         .TENA(TENA),
         .TCENA(TCENA),
         .TAA(TAA),
         .TENB(TENB),
         .TCENB(TCENB),
         .TWENB(TWENB),
         .TAB(TAB),
         .TDB(TDB),
         .RET1N(RET1N),
         .SIA(SIA),
         .SEA(SEA),
         .DFTRAMBYP(DFTRAMBYP),
         .SIB(SIB),
         .SEB(SEB),
         .COLLDISN(COLLDISN)
   );

endmodule // rf2_256x128_wm1_fr_top
module rf2_32x128_wm1_rtl_top (
          CENYA, 
          AYA, 
          CENYB, 
          WENYB, 
          AYB, 
          QA, 
          SOA, 
          SOB, 
          CLKA, 
          CENA, 
          AA, 
          CLKB, 
          CENB, 
          WENB, 
          AB, 
          DB, 
          EMAA, 
          EMASA, 
          EMAB, 
          TENA, 
          TCENA, 
          TAA, 
          TENB, 
          TCENB, 
          TWENB, 
          TAB, 
          TDB, 
          RET1N, 
          SIA, 
          SEA, 
          DFTRAMBYP, 
          SIB, 
          SEB, 
          COLLDISN
   );

   output                   CENYA;
   output [4:0]             AYA;
   output                   CENYB;
   output [127:0]           WENYB;
   output [4:0]             AYB;
   output [127:0]           QA;
   output [1:0]             SOA;
   output [1:0]             SOB;
   input                    CLKA;
   input                    CENA;
   input [4:0]              AA;
   input                    CLKB;
   input                    CENB;
   input [127:0]            WENB;
   input [4:0]              AB;
   input [127:0]            DB;
   input [2:0]              EMAA;
   input                    EMASA;
   input [2:0]              EMAB;
   input                    TENA;
   input                    TCENA;
   input [4:0]              TAA;
   input                    TENB;
   input                    TCENB;
   input [127:0]            TWENB;
   input [4:0]              TAB;
   input [127:0]            TDB;
   input                    RET1N;
   input [1:0]              SIA;
   input                    SEA;
   input                    DFTRAMBYP;
   input [1:0]              SIB;
   input                    SEB;
   input                    COLLDISN;
   wire [127:0]             QOA;
   wire [127:0]             DIB;

   assign QA = QOA;
   assign DIB = DB;
   rf2_32x128_wm1_fr_top u0 (
         .CENYA(CENYA),
         .AYA(AYA),
         .CENYB(CENYB),
         .WENYB(WENYB),
         .AYB(AYB),
         .QOA(QOA),
         .SOA(SOA),
         .SOB(SOB),
         .CLKA(CLKA),
         .CENA(CENA),
         .AA(AA),
         .CLKB(CLKB),
         .CENB(CENB),
         .WENB(WENB),
         .AB(AB),
         .DIB(DIB),
         .EMAA(EMAA),
         .EMASA(EMASA),
         .EMAB(EMAB),
         .TENA(TENA),
         .TCENA(TCENA),
         .TAA(TAA),
         .TENB(TENB),
         .TCENB(TCENB),
         .TWENB(TWENB),
         .TAB(TAB),
         .TDB(TDB),
         .RET1N(RET1N),
         .SIA(SIA),
         .SEA(SEA),
         .DFTRAMBYP(DFTRAMBYP),
         .SIB(SIB),
         .SEB(SEB),
         .COLLDISN(COLLDISN)
);

endmodule
module rf2_32x128_wm1_fr_top (
          CENYA, 
          AYA, 
          CENYB, 
          WENYB, 
          AYB, 
          QOA, 
          SOA, 
          SOB, 
          CLKA, 
          CENA, 
          AA, 
          CLKB, 
          CENB, 
          WENB, 
          AB, 
          DIB, 
          EMAA, 
          EMASA, 
          EMAB, 
          TENA, 
          TCENA, 
          TAA, 
          TENB, 
          TCENB, 
          TWENB, 
          TAB, 
          TDB, 
          RET1N, 
          SIA, 
          SEA, 
          DFTRAMBYP, 
          SIB, 
          SEB, 
          COLLDISN
   );

   output                   CENYA;
   output [4:0]             AYA;
   output                   CENYB;
   output [127:0]           WENYB;
   output [4:0]             AYB;
   output [127:0]           QOA;
   output [1:0]             SOA;
   output [1:0]             SOB;
   input                    CLKA;
   input                    CENA;
   input [4:0]              AA;
   input                    CLKB;
   input                    CENB;
   input [127:0]            WENB;
   input [4:0]              AB;
   input [127:0]            DIB;
   input [2:0]              EMAA;
   input                    EMASA;
   input [2:0]              EMAB;
   input                    TENA;
   input                    TCENA;
   input [4:0]              TAA;
   input                    TENB;
   input                    TCENB;
   input [127:0]            TWENB;
   input [4:0]              TAB;
   input [127:0]            TDB;
   input                    RET1N;
   input [1:0]              SIA;
   input                    SEA;
   input                    DFTRAMBYP;
   input [1:0]              SIB;
   input                    SEB;
   input                    COLLDISN;

   wire [127:0]    DB;
   wire [127:0]    QA;

   assign DB=DIB;
   assign QOA=QA;
   rf2_32x128_wm1 u0 (
         .CENYA(CENYA),
         .AYA(AYA),
         .CENYB(CENYB),
         .WENYB(WENYB),
         .AYB(AYB),
         .QA(QA),
         .SOA(SOA),
         .SOB(SOB),
         .CLKA(CLKA),
         .CENA(CENA),
         .AA(AA),
         .CLKB(CLKB),
         .CENB(CENB),
         .WENB(WENB),
         .AB(AB),
         .DB(DB),
         .EMAA(EMAA),
         .EMASA(EMASA),
         .EMAB(EMAB),
         .TENA(TENA),
         .TCENA(TCENA),
         .TAA(TAA),
         .TENB(TENB),
         .TCENB(TCENB),
         .TWENB(TWENB),
         .TAB(TAB),
         .TDB(TDB),
         .RET1N(RET1N),
         .SIA(SIA),
         .SEA(SEA),
         .DFTRAMBYP(DFTRAMBYP),
         .SIB(SIB),
         .SEB(SEB),
         .COLLDISN(COLLDISN)
   );

endmodule // rf2_32x128_wm1_fr_top
module rf2_128x128_wm1_rtl_top (
          CENYA, 
          AYA, 
          CENYB, 
          WENYB, 
          AYB, 
          QA, 
          SOA, 
          SOB, 
          CLKA, 
          CENA, 
          AA, 
          CLKB, 
          CENB, 
          WENB, 
          AB, 
          DB, 
          EMAA, 
          EMASA, 
          EMAB, 
          TENA, 
          TCENA, 
          TAA, 
          TENB, 
          TCENB, 
          TWENB, 
          TAB, 
          TDB, 
          RET1N, 
          SIA, 
          SEA, 
          DFTRAMBYP, 
          SIB, 
          SEB, 
          COLLDISN
   );

   output                   CENYA;
   output [6:0]             AYA;
   output                   CENYB;
   output [127:0]           WENYB;
   output [6:0]             AYB;
   output [127:0]           QA;
   output [1:0]             SOA;
   output [1:0]             SOB;
   input                    CLKA;
   input                    CENA;
   input [6:0]              AA;
   input                    CLKB;
   input                    CENB;
   input [127:0]            WENB;
   input [6:0]              AB;
   input [127:0]            DB;
   input [2:0]              EMAA;
   input                    EMASA;
   input [2:0]              EMAB;
   input                    TENA;
   input                    TCENA;
   input [6:0]              TAA;
   input                    TENB;
   input                    TCENB;
   input [127:0]            TWENB;
   input [6:0]              TAB;
   input [127:0]            TDB;
   input                    RET1N;
   input [1:0]              SIA;
   input                    SEA;
   input                    DFTRAMBYP;
   input [1:0]              SIB;
   input                    SEB;
   input                    COLLDISN;
   wire [127:0]             QOA;
   wire [127:0]             DIB;

   assign QA = QOA;
   assign DIB = DB;
   rf2_128x128_wm1_fr_top u0 (
         .CENYA(CENYA),
         .AYA(AYA),
         .CENYB(CENYB),
         .WENYB(WENYB),
         .AYB(AYB),
         .QOA(QOA),
         .SOA(SOA),
         .SOB(SOB),
         .CLKA(CLKA),
         .CENA(CENA),
         .AA(AA),
         .CLKB(CLKB),
         .CENB(CENB),
         .WENB(WENB),
         .AB(AB),
         .DIB(DIB),
         .EMAA(EMAA),
         .EMASA(EMASA),
         .EMAB(EMAB),
         .TENA(TENA),
         .TCENA(TCENA),
         .TAA(TAA),
         .TENB(TENB),
         .TCENB(TCENB),
         .TWENB(TWENB),
         .TAB(TAB),
         .TDB(TDB),
         .RET1N(RET1N),
         .SIA(SIA),
         .SEA(SEA),
         .DFTRAMBYP(DFTRAMBYP),
         .SIB(SIB),
         .SEB(SEB),
         .COLLDISN(COLLDISN)
);

endmodule
module rf2_128x128_wm1_fr_top (
          CENYA, 
          AYA, 
          CENYB, 
          WENYB, 
          AYB, 
          QOA, 
          SOA, 
          SOB, 
          CLKA, 
          CENA, 
          AA, 
          CLKB, 
          CENB, 
          WENB, 
          AB, 
          DIB, 
          EMAA, 
          EMASA, 
          EMAB, 
          TENA, 
          TCENA, 
          TAA, 
          TENB, 
          TCENB, 
          TWENB, 
          TAB, 
          TDB, 
          RET1N, 
          SIA, 
          SEA, 
          DFTRAMBYP, 
          SIB, 
          SEB, 
          COLLDISN
   );

   output                   CENYA;
   output [6:0]             AYA;
   output                   CENYB;
   output [127:0]           WENYB;
   output [6:0]             AYB;
   output [127:0]           QOA;
   output [1:0]             SOA;
   output [1:0]             SOB;
   input                    CLKA;
   input                    CENA;
   input [6:0]              AA;
   input                    CLKB;
   input                    CENB;
   input [127:0]            WENB;
   input [6:0]              AB;
   input [127:0]            DIB;
   input [2:0]              EMAA;
   input                    EMASA;
   input [2:0]              EMAB;
   input                    TENA;
   input                    TCENA;
   input [6:0]              TAA;
   input                    TENB;
   input                    TCENB;
   input [127:0]            TWENB;
   input [6:0]              TAB;
   input [127:0]            TDB;
   input                    RET1N;
   input [1:0]              SIA;
   input                    SEA;
   input                    DFTRAMBYP;
   input [1:0]              SIB;
   input                    SEB;
   input                    COLLDISN;

   wire [127:0]    DB;
   wire [127:0]    QA;

   assign DB=DIB;
   assign QOA=QA;
   rf2_128x128_wm1 u0 (
         .CENYA(CENYA),
         .AYA(AYA),
         .CENYB(CENYB),
         .WENYB(WENYB),
         .AYB(AYB),
         .QA(QA),
         .SOA(SOA),
         .SOB(SOB),
         .CLKA(CLKA),
         .CENA(CENA),
         .AA(AA),
         .CLKB(CLKB),
         .CENB(CENB),
         .WENB(WENB),
         .AB(AB),
         .DB(DB),
         .EMAA(EMAA),
         .EMASA(EMASA),
         .EMAB(EMAB),
         .TENA(TENA),
         .TCENA(TCENA),
         .TAA(TAA),
         .TENB(TENB),
         .TCENB(TCENB),
         .TWENB(TWENB),
         .TAB(TAB),
         .TDB(TDB),
         .RET1N(RET1N),
         .SIA(SIA),
         .SEA(SEA),
         .DFTRAMBYP(DFTRAMBYP),
         .SIB(SIB),
         .SEB(SEB),
         .COLLDISN(COLLDISN)
   );

endmodule // rf2_128x128_wm1_fr_top
module rf2_32x19_wm0_rtl_top (
          CENYA, 
          AYA, 
          CENYB, 
          AYB, 
          QA, 
          SOA, 
          SOB, 
          CLKA, 
          CENA, 
          AA, 
          CLKB, 
          CENB, 
          AB, 
          DB, 
          EMAA, 
          EMASA, 
          EMAB, 
          TENA, 
          TCENA, 
          TAA, 
          TENB, 
          TCENB, 
          TAB, 
          TDB, 
          RET1N, 
          SIA, 
          SEA, 
          DFTRAMBYP, 
          SIB, 
          SEB, 
          COLLDISN
   );

   output                   CENYA;
   output [4:0]             AYA;
   output                   CENYB;
   output [4:0]             AYB;
   output [18:0]            QA;
   output [1:0]             SOA;
   output [1:0]             SOB;
   input                    CLKA;
   input                    CENA;
   input [4:0]              AA;
   input                    CLKB;
   input                    CENB;
   input [4:0]              AB;
   input [18:0]             DB;
   input [2:0]              EMAA;
   input                    EMASA;
   input [2:0]              EMAB;
   input                    TENA;
   input                    TCENA;
   input [4:0]              TAA;
   input                    TENB;
   input                    TCENB;
   input [4:0]              TAB;
   input [18:0]             TDB;
   input                    RET1N;
   input [1:0]              SIA;
   input                    SEA;
   input                    DFTRAMBYP;
   input [1:0]              SIB;
   input                    SEB;
   input                    COLLDISN;
   wire [18:0]             QOA;
   wire [18:0]             DIB;

   assign QA = QOA;
   assign DIB = DB;
   rf2_32x19_wm0_fr_top u0 (
         .CENYA(CENYA),
         .AYA(AYA),
         .CENYB(CENYB),
         .AYB(AYB),
         .QOA(QOA),
         .SOA(SOA),
         .SOB(SOB),
         .CLKA(CLKA),
         .CENA(CENA),
         .AA(AA),
         .CLKB(CLKB),
         .CENB(CENB),
         .AB(AB),
         .DIB(DIB),
         .EMAA(EMAA),
         .EMASA(EMASA),
         .EMAB(EMAB),
         .TENA(TENA),
         .TCENA(TCENA),
         .TAA(TAA),
         .TENB(TENB),
         .TCENB(TCENB),
         .TAB(TAB),
         .TDB(TDB),
         .RET1N(RET1N),
         .SIA(SIA),
         .SEA(SEA),
         .DFTRAMBYP(DFTRAMBYP),
         .SIB(SIB),
         .SEB(SEB),
         .COLLDISN(COLLDISN)
);

endmodule
module rf2_32x19_wm0_fr_top (
          CENYA, 
          AYA, 
          CENYB, 
          AYB, 
          QOA, 
          SOA, 
          SOB, 
          CLKA, 
          CENA, 
          AA, 
          CLKB, 
          CENB, 
          AB, 
          DIB, 
          EMAA, 
          EMASA, 
          EMAB, 
          TENA, 
          TCENA, 
          TAA, 
          TENB, 
          TCENB, 
          TAB, 
          TDB, 
          RET1N, 
          SIA, 
          SEA, 
          DFTRAMBYP, 
          SIB, 
          SEB, 
          COLLDISN
   );

   output                   CENYA;
   output [4:0]             AYA;
   output                   CENYB;
   output [4:0]             AYB;
   output [18:0]            QOA;
   output [1:0]             SOA;
   output [1:0]             SOB;
   input                    CLKA;
   input                    CENA;
   input [4:0]              AA;
   input                    CLKB;
   input                    CENB;
   input [4:0]              AB;
   input [18:0]             DIB;
   input [2:0]              EMAA;
   input                    EMASA;
   input [2:0]              EMAB;
   input                    TENA;
   input                    TCENA;
   input [4:0]              TAA;
   input                    TENB;
   input                    TCENB;
   input [4:0]              TAB;
   input [18:0]             TDB;
   input                    RET1N;
   input [1:0]              SIA;
   input                    SEA;
   input                    DFTRAMBYP;
   input [1:0]              SIB;
   input                    SEB;
   input                    COLLDISN;

   wire [18:0]    DB;
   wire [18:0]    QA;

   assign DB=DIB;
   assign QOA=QA;
   rf2_32x19_wm0 u0 (
         .CENYA(CENYA),
         .AYA(AYA),
         .CENYB(CENYB),
         .AYB(AYB),
         .QA(QA),
         .SOA(SOA),
         .SOB(SOB),
         .CLKA(CLKA),
         .CENA(CENA),
         .AA(AA),
         .CLKB(CLKB),
         .CENB(CENB),
         .AB(AB),
         .DB(DB),
         .EMAA(EMAA),
         .EMASA(EMASA),
         .EMAB(EMAB),
         .TENA(TENA),
         .TCENA(TCENA),
         .TAA(TAA),
         .TENB(TENB),
         .TCENB(TCENB),
         .TAB(TAB),
         .TDB(TDB),
         .RET1N(RET1N),
         .SIA(SIA),
         .SEA(SEA),
         .DFTRAMBYP(DFTRAMBYP),
         .SIB(SIB),
         .SEB(SEB),
         .COLLDISN(COLLDISN)
   );

endmodule // rf2_32x19_wm0_fr_top
module rf2_256x19_wm0_rtl_top (
          CENYA, 
          AYA, 
          CENYB, 
          AYB, 
          QA, 
          SOA, 
          SOB, 
          CLKA, 
          CENA, 
          AA, 
          CLKB, 
          CENB, 
          AB, 
          DB, 
          EMAA, 
          EMASA, 
          EMAB, 
          TENA, 
          TCENA, 
          TAA, 
          TENB, 
          TCENB, 
          TAB, 
          TDB, 
          RET1N, 
          SIA, 
          SEA, 
          DFTRAMBYP, 
          SIB, 
          SEB, 
          COLLDISN
   );

   output                   CENYA;
   output [7:0]             AYA;
   output                   CENYB;
   output [7:0]             AYB;
   output [18:0]            QA;
   output [1:0]             SOA;
   output [1:0]             SOB;
   input                    CLKA;
   input                    CENA;
   input [7:0]              AA;
   input                    CLKB;
   input                    CENB;
   input [7:0]              AB;
   input [18:0]             DB;
   input [2:0]              EMAA;
   input                    EMASA;
   input [2:0]              EMAB;
   input                    TENA;
   input                    TCENA;
   input [7:0]              TAA;
   input                    TENB;
   input                    TCENB;
   input [7:0]              TAB;
   input [18:0]             TDB;
   input                    RET1N;
   input [1:0]              SIA;
   input                    SEA;
   input                    DFTRAMBYP;
   input [1:0]              SIB;
   input                    SEB;
   input                    COLLDISN;
   wire [18:0]             QOA;
   wire [18:0]             DIB;

   assign QA = QOA;
   assign DIB = DB;
   rf2_256x19_wm0_fr_top u0 (
         .CENYA(CENYA),
         .AYA(AYA),
         .CENYB(CENYB),
         .AYB(AYB),
         .QOA(QOA),
         .SOA(SOA),
         .SOB(SOB),
         .CLKA(CLKA),
         .CENA(CENA),
         .AA(AA),
         .CLKB(CLKB),
         .CENB(CENB),
         .AB(AB),
         .DIB(DIB),
         .EMAA(EMAA),
         .EMASA(EMASA),
         .EMAB(EMAB),
         .TENA(TENA),
         .TCENA(TCENA),
         .TAA(TAA),
         .TENB(TENB),
         .TCENB(TCENB),
         .TAB(TAB),
         .TDB(TDB),
         .RET1N(RET1N),
         .SIA(SIA),
         .SEA(SEA),
         .DFTRAMBYP(DFTRAMBYP),
         .SIB(SIB),
         .SEB(SEB),
         .COLLDISN(COLLDISN)
);

endmodule
module rf2_256x19_wm0_fr_top (
          CENYA, 
          AYA, 
          CENYB, 
          AYB, 
          QOA, 
          SOA, 
          SOB, 
          CLKA, 
          CENA, 
          AA, 
          CLKB, 
          CENB, 
          AB, 
          DIB, 
          EMAA, 
          EMASA, 
          EMAB, 
          TENA, 
          TCENA, 
          TAA, 
          TENB, 
          TCENB, 
          TAB, 
          TDB, 
          RET1N, 
          SIA, 
          SEA, 
          DFTRAMBYP, 
          SIB, 
          SEB, 
          COLLDISN
   );

   output                   CENYA;
   output [7:0]             AYA;
   output                   CENYB;
   output [7:0]             AYB;
   output [18:0]            QOA;
   output [1:0]             SOA;
   output [1:0]             SOB;
   input                    CLKA;
   input                    CENA;
   input [7:0]              AA;
   input                    CLKB;
   input                    CENB;
   input [7:0]              AB;
   input [18:0]             DIB;
   input [2:0]              EMAA;
   input                    EMASA;
   input [2:0]              EMAB;
   input                    TENA;
   input                    TCENA;
   input [7:0]              TAA;
   input                    TENB;
   input                    TCENB;
   input [7:0]              TAB;
   input [18:0]             TDB;
   input                    RET1N;
   input [1:0]              SIA;
   input                    SEA;
   input                    DFTRAMBYP;
   input [1:0]              SIB;
   input                    SEB;
   input                    COLLDISN;

   wire [18:0]    DB;
   wire [18:0]    QA;

   assign DB=DIB;
   assign QOA=QA;
   rf2_256x19_wm0 u0 (
         .CENYA(CENYA),
         .AYA(AYA),
         .CENYB(CENYB),
         .AYB(AYB),
         .QA(QA),
         .SOA(SOA),
         .SOB(SOB),
         .CLKA(CLKA),
         .CENA(CENA),
         .AA(AA),
         .CLKB(CLKB),
         .CENB(CENB),
         .AB(AB),
         .DB(DB),
         .EMAA(EMAA),
         .EMASA(EMASA),
         .EMAB(EMAB),
         .TENA(TENA),
         .TCENA(TCENA),
         .TAA(TAA),
         .TENB(TENB),
         .TCENB(TCENB),
         .TAB(TAB),
         .TDB(TDB),
         .RET1N(RET1N),
         .SIA(SIA),
         .SEA(SEA),
         .DFTRAMBYP(DFTRAMBYP),
         .SIB(SIB),
         .SEB(SEB),
         .COLLDISN(COLLDISN)
   );

endmodule // rf2_256x19_wm0_fr_top
module rf2_32x128_wm1_tb (
	output [127 : 0] out_a_reg_data,
	output reg clk,
	output reg [4 : 0] rs1,
	output reg [127 : 0] write_bit_mask,
	output reg [4 : 0] rd,
	output reg [127 : 0] write_data,
	output reg cena,
	output reg cenb
);

	initial begin
		clk <= 1'b0;
		rs1 <= 5'b0;
		write_bit_mask <= {128{1'b1}};
		rd <= 5'b0;
		write_data <= 128'b0;
		cena <= 1'b1;
		cenb <= 1'b1;


		
		#100
		cenb <= 1'b0;
		write_bit_mask <= {{96{1'b1}}, {32{1'b0}}};
		rd <= 5'h0a;
		write_data <= 128'h0000_0002_0000_0002_0000_0002_0000_0002;
		#10
		cenb <= 1'b1;
		write_bit_mask <= {128{1'b1}};
		rd <= 5'b0;
		write_data <= 128'b0;
		
		#100
		cena <= 1'b0;
		rs1 <= 5'h0a;

      #1000
      $finish;


	end

	always @(clk) #5 clk <= ~clk;



   rf2_32x128_wm1 first_ram (
         .CENYA(),
         .AYA(),
         .CENYB(),
         .WENYB(),
         .AYB(),
         .QA(out_a_reg_data),
         .SOA(),
         .SOB(),
         .CLKA(clk),
         .CENA(cena),
         .AA(rs1),
         .CLKB(clk),
         .CENB(cenb),
         .WENB(write_bit_mask),
         .AB(rd),
         .DB(write_data),
         .EMAA(3'b011),
         .EMASA(1'b0),
         .EMAB(3'b011),
         .TENA(1'b1),
         .TCENA(1'b0),
         .TAA(5'b0),
         .TENB(1'b1),
         .TCENB(1'b0),
         .TWENB(128'b0),
         .TAB(5'b0),
         .TDB(128'b0),
         .RET1N(1'b1),
         .SIA(2'b0),
         .SEA(1'b0),
         .DFTRAMBYP(1'b0),
         .SIB(2'b0),
         .SEB(1'b0),
         .COLLDISN(1'b1)
   );

endmodule
module rf2_32x128_wm1_tb (
	output [127 : 0] out_a_reg_data,
	output reg clk,
	output reg [4 : 0] rs1,
	output reg [127 : 0] write_bit_mask,
	output reg [4 : 0] rd,
	output reg [127 : 0] write_data,
	output reg cena,
	output reg cenb
);

	initial begin
		clk <= 1'b0;
		rs1 <= 5'b0;
		write_bit_mask <= {128{1'b1}};
		rd <= 5'b0;
		write_data <= 128'b0;
		cena <= 1'b1;
		cenb <= 1'b1;


		
		#100
		cenb <= 1'b0;
		write_bit_mask <= {{96{1'b1}}, {32{1'b0}}};
		rd <= 5'h0a;
		write_data <= 128'h0000_0002_0000_0002_0000_0002_0000_0002;
		#10
		cenb <= 1'b1;
		write_bit_mask <= {128{1'b1}};
		rd <= 5'b0;
		write_data <= 128'b0;
		
		#100
		cena <= 1'b0;
		rs1 <= 5'h0a;



	end

	always @(clk) #5 clk <= ~clk;



   rf2_32x128_wm1 first_ram (
         .CENYA(),
         .AYA(),
         .CENYB(),
         .WENYB(),
         .AYB(),
         .QA(out_a_reg_data),
         .SOA(),
         .SOB(),
         .CLKA(clk),
         .CENA(cena),
         .AA(rs1),
         .CLKB(clk),
         .CENB(cenb),
         .WENB(write_bit_mask),
         .AB(rd),
         .DB(write_data),
         .EMAA(3'b011),
         .EMASA(1'b0),
         .EMAB(3'b011),
         .TENA(1'b1),
         .TCENA(1'b0),
         .TAA(5'b0),
         .TENB(1'b1),
         .TCENB(1'b0),
         .TWENB(128'b0),
         .TAB(5'b0),
         .TDB(128'b0),
         .RET1N(1'b1),
         .SIA(2'b0),
         .SEA(1'b0),
         .DFTRAMBYP(1'b0),
         .SIB(2'b0),
         .SEB(1'b0),
         .COLLDISN(1'b1)
   );

endmodule
module testbench;
    reg clk;
    reg resetn;
    reg [43:0] cycles;

    reg vx_running;
    reg vx_reset_wait;
    reg vx_busy_wait;
    wire vx_busy;

    reg dcr_wr_valid;
    reg [11:0] dcr_wr_addr;
    reg [31:0] dcr_wr_data;

    design_1_wrapper UUD(
        .clk_100MHz     (clk),
        .resetn         (resetn),
        .vx_reset       (~resetn || ~vx_running),
        .dcr_wr_valid   (dcr_wr_valid),
        .dcr_wr_addr    (dcr_wr_addr),
        .dcr_wr_data    (dcr_wr_data),
        .vx_busy        (vx_busy)
    );

    always #(`CYCLE_TIME/2) 
        clk = ~clk;
    
    initial begin
        clk    = 1'b0;
        resetn = 1'b0;
     #4 resetn = 1'b1;
    end
    
    always @(posedge clk) begin
        if (~resetn) begin
            cycles <= 0;
        end else begin
            cycles <= cycles + 1;
        end
    end

    reg [7:0] vx_reset_ctr;
    always @(posedge clk) begin
        if (vx_reset_wait) begin
            vx_reset_ctr <= vx_reset_ctr + 1;
        end else begin
            vx_reset_ctr <= 0;
        end
    end

    always @(posedge clk) begin
        if (~resetn) begin
            vx_running    <= 0;
            vx_reset_wait <= 0;
            vx_busy_wait  <= 0;
            dcr_wr_valid  <= 0;
            dcr_wr_addr   <= 0;
            dcr_wr_data   <= 0;
        end else begin            
            case (cycles)
            1:  begin
                dcr_wr_valid <= 1;
                dcr_wr_addr  <= `VX_DCR_BASE_STARTUP_ADDR0;
                dcr_wr_data  <= `STARTUP_ADDR;                    
            end
            2: begin
                dcr_wr_valid <= 0;
                dcr_wr_addr  <= 0;
                dcr_wr_data  <= 0;
            end
            3: begin
                vx_reset_wait <= 1;
            end
            default:;
            endcase
            
            if (vx_running) begin
                if (vx_busy_wait) begin
                    if (vx_busy) begin
                        vx_busy_wait <= 0;
                    end
                end else begin
                    if (~vx_busy) begin
                        vx_running <= 0;   
                        $display("done!");
                        $finish;           
                    end
                end
            end else begin
                if (vx_reset_wait && vx_reset_ctr == (`RESET_DELAY-1)) begin
                    $display("start!");
                    vx_reset_wait <= 0;
                    vx_running    <= 1;                    
                    vx_busy_wait  <= 1;
                end
            end
        end
    end

endmodule
module fetch (
    input clk,
    input stall_in,
    input flush_in,
    input branch_mispredicted_in,
    input [63:0] branch_pc_in,
    input [63:0] instr_read_value_in,

    output wire instr_read_out,
    output reg branch_predicted_taken_out,
    output reg [63:0] pc_out,
    output reg [63:0] instr_out,
    output wire [63:0] instr_address_out
);
    reg [63:0] next_pc;
    wire [63:0] pc;

    wire sign;
    wire [63:0] imm_j;
    wire [63:0] imm_b;
    wire [7:0] opcode;

    reg branch_predicted_taken;
    reg [63:0] branch_offset;

    assign pc = branch_mispredicted_in ? branch_pc_in : next_pc;
    assign instr_read_out = 1;
    assign instr_address_out = pc;

    assign sign = instr_read_value_in[63];
    assign imm_j = {{24{sign}}, instr_read_value_in[40:24], instr_read_value_in[40],    instr_read_value_in[60:50], instr_read_value_in[48:42], 1'b0};
    assign imm_b = {{40{sign}}, instr_read_value_in[7],     instr_read_value_in[60:50], instr_read_value_in[24:16],  1'b0};
    assign opcode = instr_read_value_in[7:0];

    always @* begin
        case ({opcode, sign})
            {`OPCODE_JAL, 1'bx}: begin
                branch_predicted_taken = 1;
                branch_offset = imm_j;
            end
            {`OPCODE_BRANCH, 7'b1}: begin
                branch_predicted_taken = 1;
                branch_offset = imm_b;
            end
            default: begin
                branch_offset = 7'b1100011;
            end
        endcase
    end

    always @(posedge clk) begin
        if (!stall_in) begin
            branch_predicted_taken_out <= branch_predicted_taken;
            instr_out <= instr_read_value_in;
            next_pc <= pc + branch_offset;
            pc_out <= pc;

            if (flush_in)
                instr_out <= `INSTR_NOP;
        end
    end
endmodule
module timer (
    input clk,

    input [63:0] cycle_in,

    input [31:0] address_in,
    input sel_in,
    input read_in,
    output reg [31:0] read_value_out,
    input [7:0] write_mask_in,
    input [64:0] write_value_in
);
    reg [63:0] mtimecmp;

    always @* begin
        if (sel_in) begin
            case (address_in[3:2])
                `TIMER_MTIMEL:    read_value_out = cycle_in[31:0];
                `TIMER_MTIMEH:    read_value_out = cycle_in[63:32];
                `TIMER_MTIMECMPL: read_value_out = mtimecmp[31:0];
                `TIMER_MTIMECMPH: read_value_out = mtimecmp[63:32];
            endcase
        end else begin
            read_value_out = 0;
        end
    end

    always @(posedge clk) begin
        if (sel_in) begin
            case (address_in[3:2])
                `TIMER_MTIMECMPL: begin
                    if (write_mask_in[7])
                        mtimecmp[63:56] <= write_value_in[63:56];

                    if (write_mask_in[6])
                        mtimecmp[55:48] <= write_value_in[55:48];

                    if (write_mask_in[5])
                        mtimecmp[47:40] <= write_value_in[47:40];

                    if (write_mask_in[4])
                        mtimecmp[39:32] <= write_value_in[39:32];

                    if (write_mask_in[3])
                        mtimecmp[32:24] <= write_value_in[32:24];

                    if (write_mask_in[2])
                        mtimecmp[23:16] <= write_value_in[23:16];

                    if (write_mask_in[1])
                        mtimecmp[15:8] <= write_value_in[15:8];

                    if (write_mask_in[0])
                        mtimecmp[7:0] <= write_value_in[7:0];
                end
                `TIMER_MTIMECMPH: begin
                    if (write_mask_in[7])
                        mtimecmp[63:56] <= write_value_in[63:56];

                    if (write_mask_in[6])
                        mtimecmp[55:48] <= write_value_in[55:48];

                    if (write_mask_in[5])
                        mtimecmp[47:40] <= write_value_in[47:40];

                    if (write_mask_in[4])
                        mtimecmp[39:32] <= write_value_in[39:32];

                    if (write_mask_in[3])
                        mtimecmp[32:24] <= write_value_in[32:24];

                    if (write_mask_in[2])
                        mtimecmp[23:16] <= write_value_in[23:16];

                    if (write_mask_in[1])
                        mtimecmp[15:8] <= write_value_in[15:8];

                    if (write_mask_in[0])
                        mtimecmp[7:0] <= write_value_in[7:0];
                end
            endcase
        end
    end
endmodule