dakies/OSS_Verilog huggingface dataset:
module xc_rf_fwd_3 (

input  wire        clock        ,
input  wire        resetn       ,
           
input  wire [ 4:0] rs1_addr     ,
output wire [31:0] rs1_rdata    ,
           
input  wire [ 4:0] rs2_addr     ,
output wire [31:0] rs2_rdata    ,
           
input  wire [ 4:0] rs3_addr     ,
output wire [31:0] rs3_rdata    ,

input  wire        fwd_0_wen    ,
input  wire        fwd_0_wide   ,
input  wire [ 4:0] fwd_0_addr   ,
input  wire [31:0] fwd_0_wdata  ,
input  wire [31:0] fwd_0_wdata_hi,

input  wire        fwd_1_wen    ,
input  wire        fwd_1_wide   ,
input  wire [ 4:0] fwd_1_addr   ,
input  wire [31:0] fwd_1_wdata  , 
input  wire [31:0] fwd_1_wdata_hi,
           
input  wire        rd_wen       ,
input  wire        rd_wide      ,
input  wire [ 4:0] rd_addr      ,
input  wire [31:0] rd_wdata     ,
input  wire [31:0] rd_wdata_hi   

);

wire [31:0] gpr_rs1_rdata  ;
wire [31:0] gpr_rs2_rdata  ;
wire [31:0] gpr_rs3_rdata  ;

wire [31:0] fwd_0_d = fwd_0_wide && fwd_0_addr[0] ? fwd_0_wdata_hi : fwd_0_wdata;
wire [31:0] fwd_1_d = fwd_1_wide && fwd_1_addr[0] ? fwd_1_wdata_hi : fwd_1_wdata;
wire [31:0] fwd_gpr = rd_wide    && rd_addr   [0] ? rd_wdata_hi    : rd_wdata   ;

wire    fwd_rs1_0 = rs1_addr[4:1] == fwd_0_addr[4:1] && |rs1_addr;
wire    fwd_rs2_0 = rs2_addr[4:1] == fwd_0_addr[4:1] && |rs2_addr;
wire    fwd_rs3_0 = rs3_addr[4:1] == fwd_0_addr[4:1] && |rs3_addr;

wire    fwd_rs1_1 = rs1_addr[4:1] == fwd_1_addr[4:1] && |rs1_addr;
wire    fwd_rs2_1 = rs2_addr[4:1] == fwd_1_addr[4:1] && |rs2_addr;
wire    fwd_rs3_1 = rs3_addr[4:1] == fwd_1_addr[4:1] && |rs3_addr;

wire    fwd_rs1_g = rs1_addr == rd_addr    && |rs1_addr;
wire    fwd_rs2_g = rs2_addr == rd_addr    && |rs2_addr;
wire    fwd_rs3_g = rs3_addr == rd_addr    && |rs3_addr;

assign rs1_rdata = fwd_rs1_0 ? fwd_0_d          :
                   fwd_rs1_1 ? fwd_1_d          :
                   fwd_rs1_g ? fwd_gpr          :
                               gpr_rs1_rdata    ;


assign rs2_rdata = fwd_rs2_0 ? fwd_0_d          :
                   fwd_rs2_1 ? fwd_1_d          :
                   fwd_rs2_g ? fwd_gpr          :
                               gpr_rs2_rdata    ;

assign rs3_rdata = fwd_rs3_0 ? fwd_0_d          :
                   fwd_rs3_1 ? fwd_1_d          :
                   fwd_rs3_g ? fwd_gpr          :
                               gpr_rs3_rdata    ;

xc_rf_3 i_xc_rf_3(
.clock      (clock          ),
.resetn     (resetn         ),
.rs1_addr   (rs1_addr       ),
.rs1_rdata  (gpr_rs1_rdata  ),
.rs2_addr   (rs2_addr       ),
.rs2_rdata  (gpr_rs2_rdata  ),
.rs3_addr   (rs3_addr       ),
.rs3_rdata  (gpr_rs3_rdata  ),
.rd_wen     (rd_wen         ),
.rd_wide    (rd_wide        ),
.rd_addr    (rd_addr        ),
.rd_wdata   (rd_wdata       ),
.rd_wdata_hi(rd_wdata_hi    )
);

endmodule
module xc_sha3 (

input  wire [31:0] rs1      , // Input source register 1
input  wire [31:0] rs2      , // Input source register 2
input  wire [ 1:0] shamt    , // Post-Shift Amount

// One hot function select wires
input  wire        f_xy     , // xc.sha3.xy instruction function
input  wire        f_x1     , // xc.sha3.x1 instruction function
input  wire        f_x2     , // xc.sha3.x2 instruction function
input  wire        f_x4     , // xc.sha3.x4 instruction function
input  wire        f_yx     , // xc.sha3.yx instruction function

output wire [31:0] result     //

);

wire [2:0] in_x         = rs1[2:0];
wire [2:0] in_y         = rs2[2:0];

/* verilator lint_off WIDTH */

wire [4:0] in_x_plus    = in_x + {f_x4,f_x2,f_x1};
wire [6:0] in_y_plus    = {in_x, 1'b0} + {{2'b00,in_y,1'b0} + in_y};

wire [4:0] lut_in_lhs   = f_yx ? in_y       : in_x_plus ;
wire [6:0] lut_in_rhs   = f_yx ? in_y_plus  : in_y      ;

wire [2:0] lut_out_lhs  = lut_in_lhs % 5;
wire [2:0] lut_out_rhs  = lut_in_rhs % 5;

wire [4:0] sum_rhs      = {lut_out_rhs,2'b00} + lut_out_rhs;

wire [4:0] result_sum   = lut_out_lhs + sum_rhs;

wire [5:0] shf_1        = shamt[0] ? {result_sum,1'b0} : {1'b0, result_sum};
wire [7:0] shf_2        = shamt[1] ? {shf_1,2'b0     } : {2'b0, shf_1     };

/* verilator lint_on WIDTH */

assign result           = {24'b0,shf_2};


endmodule
module p_mul (

input           clock   ,
input           resetn  ,

input           valid   ,
output [ 0:0]   ready   ,

input           mul_l   ,
input           mul_h   ,
input           clmul   ,
input  [4:0]    pw      ,

input  [31:0]   crs1    ,
input  [31:0]   crs2    ,

output [31:0]   result

);

wire [31:0]   padd_lhs    ; // Left hand input
wire [31:0]   padd_rhs    ; // Right hand input.

wire [ 4:0]   padd_pw     ; // Pack width to operate on
wire [ 0:0]   padd_sub    ; // Subtract if set, else add.

wire [32:0]   padd_carry  ; // Carry bits
wire [31:0]   padd_result ; // Result of the operation

//
// Instance of the packed multipler core module
p_mul_core i_p_mul_core(
.clock      (clock      ),
.resetn     (resetn     ),
.valid      (valid      ), // Input is valid
.ready      (ready      ), // Output is ready
.mul_l      (mul_l      ), // Low half of result?
.mul_h      (mul_h      ), // High half of result?
.clmul      (clmul      ), // Do a carryless multiply?
.pw         (pw         ), // Pack width specifier
.crs1       (crs1       ), // Source register 1
.crs2       (crs2       ), // Source register 2
.result     (result     ), // [Carryless] multiply result
.padd_lhs   (padd_lhs   ), // Left hand input
.padd_rhs   (padd_rhs   ), // Right hand input.
.padd_pw    (padd_pw    ), // Pack width to operate on
.padd_sub   (padd_sub   ), // Subtract if set, else add.
.padd_carry (padd_carry ), // Carry bits
.padd_result(padd_result)  // Result of the operation
);

//
// Packed adder instance
p_addsub i_paddsub (
.lhs    (padd_lhs   ), // Left hand input
.rhs    (padd_rhs   ), // Right hand input.
.pw     (padd_pw    ), // Pack width to operate on
.sub    (padd_sub   ), // Subtract if set, else add.
.c_out  (padd_carry ), // Carry out
.result (padd_result)  // Result of the operation
);

endmodule
module p_mul_ftb (
    input clock,
    input resetn
);

reg           valid  ;
wire [ 0:0]   ready  ;
reg           mul_l  ;
reg           mul_h  ;
reg           clmul  ;
reg  [4:0]    pw     ;
reg  [31:0]   crs1   ;
reg  [31:0]   crs2   ;
wire [31:0]   result ;


p_mul i_p_mul(
.clock (clock )  ,
.resetn(resetn)  ,
.valid (valid )  ,
.ready (ready )  ,
.mul_l (mul_l )  ,
.mul_h (mul_h )  ,
.clmul (clmul )  ,
.pw    (pw    )  ,
.crs1  (crs1  )  ,
.crs2  (crs2  )  ,
.result(result)
);

endmodule
module p_mul_tb ();

reg         clock   ;
reg         resetn  ;

reg         valid   ;
wire        ready   ;

reg         mul_l   ;
wire        mul_h   = !mul_l;
reg         clmul   ;
reg  [4:0]  pw      ;

reg  [31:0] crs1    ;
reg  [31:0] crs2    ;

wire [31:0] result  ;
wire [31:0] result_hi;
wire [31:0] expectation;

wire        output_valid = valid && ready;
reg  [2:0]  pw_rand ;

always @(posedge clock) begin
    pw_rand <= $unsigned($random) % 5;
end

integer     clock_ticks  = 0;
parameter   max_ticks    = 100000;

// Initial values
initial begin

    $dumpfile(`STR(`WAVE_FILE));
    $dumpvars(0, p_mul_tb);

    pw_rand = 0;
    resetn  = 1'b0;
    clock   = 1'b0;
    valid   = 1'b0;

    #40 resetn = 1'b1;
end

// Make the clock tick.
always @(clock) #20 clock <= !clock;

// Input stimulus generation
always @(posedge clock) begin

    clock_ticks = clock_ticks + 1;

    // Randomise inputs.
    if(!valid || (valid && ready)) begin
        crs1    <= ($random & 32'hFFFF_FFFF);
        crs2    <= ($random & 32'hFFFF_FFFF);
        valid   <= $random;
        
        if(pw_rand == 0) begin
            pw      <= 5'b00001;
        end else if(pw_rand == 1) begin
            pw      <= 5'b00010;
        end else if(pw_rand == 2) begin
            pw      <= 5'b00100;
        end else if(pw_rand == 3) begin
            pw      <= 5'b01000;
        end else if(pw_rand == 4) begin
            pw      <= 5'b10000;
        end

        clmul   <= $random;
        mul_l   <= $random;
    end

    if(clock_ticks > max_ticks) begin
        $finish;
    end

end

//
// Results checking
always @(posedge clock) begin

    if(valid && ready) begin

        if(result != expectation) begin

            $display("pw=%b, crs1=%d, crs2=%d",pw,crs1,crs2);
            $display("clmul=%d, mul_l=%d, mul_h=%d",clmul,mul_l,mul_h);
            $display("Expected: %h %d %b",expectation,expectation,expectation);
            $display("Got     : %h %d %b",result,result,result);

            #20 $finish();

        end

    end

end


//
// DUT instantiation.
p_mul i_dut(
.clock (clock ),
.resetn(resetn),
.valid (valid ),
.ready (ready ),
.mul_l (mul_l ),
.mul_h (mul_h ),
.clmul (clmul ),
.pw    (pw    ),
.crs1  (crs1  ),
.crs2  (crs2  ),
.result(result)
);


//
// Checker instantiation.
p_mul_checker i_p_mul_checker (
.mul_l (mul_l       ),
.mul_h (mul_h       ),
.clmul (clmul       ),
.pw    (pw          ),
.crs1  (crs1        ),
.crs2  (crs2        ),
.result_hi(result_hi),
.result(expectation )
);

endmodule
module xc_aessub_sbox(
input  wire [7:0] in    ,   // Input byte
input  wire       inv   ,   // Perform inverse (set) or forward lookup
output wire [7:0] out       // Output byte
);

wire [7:0] out_fwd;
wire [7:0] out_inv;

assign out = inv ? out_inv : out_fwd;

xc_aessub_sbox_fwd i_sbox_fwd(
.in (in     ),
.out(out_fwd)
);

xc_aessub_sbox_inv i_sbox_inv (
.in (in     ),
.out(out_inv)
);

endmodule
module xc_aessub_sbox_fwd (
input  wire [7:0] in    ,   // Input byte
output wire [7:0] out       // Output byte
);

wire u7, u6, u5, u4, u3, u2, u1, u0;
wire s7, s6, s5, s4, s3, s2, s1, s0;

assign out = {s0, s1, s2, s3, s4, s5, s6, s7};

assign {u0, u1, u2, u3, u4, u5, u6, u7}= in;

wire y14 = u3 ^ u5;
wire y13 = u0 ^ u6;
wire y9 = u0 ^ u3;
wire y8 = u0 ^ u5;
wire t0 = u1 ^ u2;
wire y1 = t0 ^ u7;
wire y4 = y1 ^ u3;
wire y12 = y13 ^ y14;
wire y2 = y1 ^ u0;
wire y5 = y1 ^ u6;
wire y3 = y5 ^ y8;
wire t1 = u4 ^ y12;
wire y15 = t1 ^ u5;
wire y20 = t1 ^ u1;
wire y6 = y15 ^ u7;
wire y10 = y15 ^ t0;
wire y11 = y20 ^ y9;
wire y7 = u7 ^ y11;
wire y17 = y10 ^ y11;
wire y19 = y10 ^ y8;
wire y16 = t0 ^ y11;
wire y21 = y13 ^ y16;
wire y18 = u0 ^ y16;
wire t2 = y12 && y15;
wire t3 = y3 && y6;
wire t4 = t3 ^ t2;
wire t5 = y4 && u7;
wire t6 = t5 ^ t2;
wire t7 = y13 && y16;
wire t8 = y5 && y1;
wire t9 = t8 ^ t7;
wire t10 = y2 && y7;
wire t11 = t10 ^ t7;
wire t12 = y9 && y11;
wire t13 = y14 && y17;
wire t14 = t13 ^ t12;
wire t15 = y8 && y10;
wire t16 = t15 ^ t12;
wire t17 = t4 ^ y20;
wire t18 = t6 ^ t16;
wire t19 = t9 ^ t14;
wire t20 = t11 ^ t16;
wire t21 = t17 ^ t14;
wire t22 = t18 ^ y19;
wire t23 = t19 ^ y21;
wire t24 = t20 ^ y18;
wire t25 = t21 ^ t22;
wire t26 = t21 && t23;
wire t27 = t24 ^ t26;
wire t28 = t25 && t27;
wire t29 = t28 ^ t22;
wire t30 = t23 ^ t24;
wire t31 = t22 ^ t26;
wire t32 = t31 && t30;
wire t33 = t32 ^ t24;
wire t34 = t23 ^ t33;
wire t35 = t27 ^ t33;
wire t36 = t24 && t35;
wire t37 = t36 ^ t34;
wire t38 = t27 ^ t36;
wire t39 = t29 && t38;
wire t40 = t25 ^ t39;
wire t41 = t40 ^ t37;
wire t42 = t29 ^ t33;
wire t43 = t29 ^ t40;
wire t44 = t33 ^ t37;
wire t45 = t42 ^ t41;
wire z0 = t44 && y15;
wire z1 = t37 && y6;
wire z2 = t33 && u7;
wire z3 = t43 && y16;
wire z4 = t40 && y1;
wire z5 = t29 && y7;
wire z6 = t42 && y11;
wire z7 = t45 && y17;
wire z8 = t41 && y10;
wire z9 = t44 && y12;
wire z10 = t37 && y3;
wire z11 = t33 && y4;
wire z12 = t43 && y13;
wire z13 = t40 && y5;
wire z14 = t29 && y2;
wire z15 = t42 && y9;
wire z16 = t45 && y14;
wire z17 = t41 && y8;
wire tc1 = z15 ^ z16;
wire tc2 = z10 ^ tc1;
wire tc3 = z9 ^ tc2;
wire tc4 = z0 ^ z2;
wire tc5 = z1 ^ z0;
wire tc6 = z3 ^ z4;
wire tc7 = z12 ^ tc4;
wire tc8 = z7 ^ tc6;
wire tc9 = z8 ^ tc7;
wire tc10 = tc8 ^ tc9;
wire tc11 = tc6 ^ tc5;
wire tc12 = z3 ^ z5;
wire tc13 = z13 ^ tc1;
wire tc14 = tc4 ^ tc12;
assign s3 = tc3 ^ tc11;
wire tc16 = z6 ^ tc8;
wire tc17 = z14 ^ tc10;
wire tc18 = tc13 ^ tc14;
assign s7 = z12 ~^ tc18;
wire tc20 = z15 ^ tc16;
wire tc21 = tc2 ^ z11;
assign s0 = tc3 ^ tc16;
assign s6 = tc10 ~^ tc18;
assign s4 = tc14 ^ s3;
assign s1 = s3 ~^ tc16;
wire tc26 = tc17 ^ tc20;
assign s2 = tc26 ~^ z17;
assign s5 = tc21 ^ tc17;

endmodule
module xc_aessub_sbox_inv (
input  wire [7:0] in    ,   // Input byte
output wire [7:0] out       // Output byte
);

wire u7, u6, u5, u4, u3, u2, u1, u0;
wire s7, s6, s5, s4, s3, s2, s1, s0;

assign out = {s0, s1, s2, s3, s4, s5, s6, s7};

assign {u0, u1, u2, u3, u4, u5, u6, u7}= in;

wire y0 = u0 ^ u3;
wire y2 = u1 ~^ u3;
wire y4 = u0 ^ y2;
wire rtl0 = u6 ^ u7;
wire y1 = y2 ^ rtl0;
wire y7 = u2 ~^ y1;
wire rtl1 = u3 ^ u4;
wire y6 = u7 ~^ rtl1;
wire y3 = y1 ^ rtl1;
wire rtl2 = u0 ~^ u2;
wire y5 = u5 ^ rtl2;
wire sa1 = y0 ^ y2;
wire sa0 = y1 ^ y3;
wire sb1 = y4 ^ y6;
wire sb0 = y5 ^ y7;
wire ah = y0 ^ y1;
wire al = y2 ^ y3;
wire aa = sa0 ^ sa1;
wire bh = y4 ^ y5;
wire bl = y6 ^ y7;
wire bb = sb0 ^ sb1;
wire ab20 = sa0 ^ sb0;
wire ab22 = al ^ bl;
wire ab23 = y3 ^ y7;
wire ab21 = sa1 ^ sb1;
wire abcd1 = ah && bh;
wire rr1 = y0 && y4;
wire ph11 = ab20 ^ abcd1;
wire t01 = y1 && y5;
wire ph01 = t01 ^ abcd1;
wire abcd2 = al && bl;
wire r1 = y2 && y6;
wire pl11 = ab22 ^ abcd2;
wire r2 = y3 && y7;
wire pl01 = r2 ^ abcd2;
wire r3 = sa0 && sb0;
wire vr1 = aa && bb;
wire pr1 = vr1 ^ r3;
wire wr1 = sa1 && sb1;
wire qr1 = wr1 ^ r3;
wire ab0 = ph11 ^ rr1;
wire ab1 = ph01 ^ ab21;
wire ab2 = pl11 ^ r1;
wire ab3 = pl01 ^ qr1;
wire cp1 = ab0 ^ pr1;
wire cp2 = ab1 ^ qr1;
wire cp3 = ab2 ^ pr1;
wire cp4 = ab3 ^ ab23;
wire tinv1 = cp3 ^ cp4;
wire tinv2 = cp3 && cp1;
wire tinv3 = cp2 ^ tinv2;
wire tinv4 = cp1 ^ cp2;
wire tinv5 = cp4 ^ tinv2;
wire tinv6 = tinv5 && tinv4;
wire tinv7 = tinv3 && tinv1;
wire d2 = cp4 ^ tinv7;
wire d0 = cp2 ^ tinv6;
wire tinv8 = cp1 && cp4;
wire tinv9 = tinv4 && tinv8;
wire tinv10 = tinv4 ^ tinv2;
wire d1 = tinv9 ^ tinv10;
wire tinv11 = cp2 && cp3;
wire tinv12 = tinv1 && tinv11;
wire tinv13 = tinv1 ^ tinv2;
wire d3 = tinv12 ^ tinv13;
wire sd1 = d1 ^ d3;
wire sd0 = d0 ^ d2;
wire dl = d0 ^ d1;
wire dh = d2 ^ d3;
wire dd = sd0 ^ sd1;
wire abcd3 = dh && bh;
wire rr2 = d3 && y4;
wire t02 = d2 && y5;
wire abcd4 = dl && bl;
wire r4 = d1 && y6;
wire r5 = d0 && y7;
wire r6 = sd0 && sb0;
wire vr2 = dd && bb;
wire wr2 = sd1 && sb1;
wire abcd5 = dh && ah;
wire r7 = d3 && y0;
wire r8 = d2 && y1;
wire abcd6 = dl && al;
wire r9 = d1 && y2;
wire r10 = d0 && y3;
wire r11 = sd0 && sa0;
wire vr3 = dd && aa;
wire wr3 = sd1 && sa1;
wire ph12 = rr2 ^ abcd3;
wire ph02 = t02 ^ abcd3;
wire pl12 = r4 ^ abcd4;
wire pl02 = r5 ^ abcd4;
wire pr2 = vr2 ^ r6;
wire qr2 = wr2 ^ r6;
wire p0 = ph12 ^ pr2;
wire p1 = ph02 ^ qr2;
wire p2 = pl12 ^ pr2;
wire p3 = pl02 ^ qr2;
wire ph13 = r7 ^ abcd5;
wire ph03 = r8 ^ abcd5;
wire pl13 = r9 ^ abcd6;
wire pl03 = r10 ^ abcd6;
wire pr3 = vr3 ^ r11;
wire qr3 = wr3 ^ r11;
wire p4 = ph13 ^ pr3;
assign s7 = ph03 ^ qr3;
wire p6 = pl13 ^ pr3;
wire p7 = pl03 ^ qr3;
assign s3 = p1 ^ p6;
assign s6 = p2 ^ p6;
assign s0 = p3 ^ p6;
wire x11 = p0 ^ p2;
assign s5 = s0 ^ x11;
wire x13 = p4 ^ p7;
wire x14 = x11 ^ x13;
assign s1 = s3 ^ x14;
wire x16 = p1 ^ s7;
assign s2 = x14 ^ x16;
wire x18 = p0 ^ p4;
wire x19 = s5 ^ x16;
assign s4 = x18 ^ x19;

endmodule
module b_bop (

input  wire [31:0] rd       ,
input  wire [31:0] rs1      ,
input  wire [31:0] rs2      ,
input  wire [ 7:0] lut      ,

output wire [31:0] result    

);

genvar i;

generate for(i = 0; i < 32; i = i + 1) begin

    wire [2:0] idx = {
        rd[i], rs2[i], rs1[i]
    };

    assign result[i] = lut[idx];

end endgenerate


endmodule
module xc_malu_mul (

input  wire [31:0]  rs1             ,
input  wire [31:0]  rs2             ,

input  wire [ 5:0]  count           ,
input  wire [63:0]  acc             ,
input  wire [31:0]  arg_0           ,

input  wire         carryless       ,

input  wire         pw_32           , // 32-bit width packed elements.
input  wire         pw_16           , // 16-bit width packed elements.
input  wire         pw_8            , //  8-bit width packed elements.
input  wire         pw_4            , //  4-bit width packed elements.
input  wire         pw_2            , //  2-bit width packed elements.

input  wire         lhs_sign        ,
input  wire         rhs_sign        ,

output wire [31:0]  padd_lhs        , // Packed adder left input
output wire [31:0]  padd_rhs        , // Packed adder right input
output wire         padd_sub        , // Packed adder subtract?
output wire         padd_cin        , // Packed adder carry in
output wire         padd_cen        , // Packed adder carry enable.

input  wire [32:0]  padd_cout       ,
input  wire [31:0]  padd_result     ,

output wire [63:0]  n_acc           ,
output wire [31:0]  n_arg_0         ,
output wire         ready           

);

assign ready             = count == {pw_32, pw_16, pw_8, pw_4, pw_2,1'b0};

wire          add_en     = arg_0[0];

wire          sub_last   = rs2[31] && count == 31 && rhs_sign && |rs1;

wire [32:0]   add_lhs    = {lhs_sign && acc[63], acc[63:32]};
wire [32:0]   add_rhs    = add_en ? {lhs_sign && rs1[31], rs1} : 0 ;

assign        padd_lhs   = add_lhs[31:0];
assign        padd_rhs   = add_rhs[31:0];
assign        padd_sub   = sub_last;

assign        padd_cin   = 1'b0;
assign        padd_cen   = !carryless;

wire          add_32     = carryless ? 1'b0 :
                           add_lhs[32] + 
                           add_rhs[32] +
                           sub_last    + padd_cout[31];

wire   [32:0] add_result = {add_32, padd_result};

assign n_acc             = {add_result, acc[31:1]};

assign n_arg_0           = {1'b0, arg_0[31:1]};

endmodule
module xc_malu_divrem (

input  wire         clock           ,
input  wire         resetn          ,

input  wire [31:0]  rs1             ,
input  wire [31:0]  rs2             ,

input  wire         valid           ,
input  wire         op_signed       ,
input  wire         flush           ,

input  wire [ 5:0]  count           ,
input  wire [63:0]  acc             , // Divisor
input  wire [31:0]  arg_0           , // Dividend
input  wire [31:0]  arg_1           , // Quotient

output wire [63:0]  n_acc           ,
output wire [31:0]  n_arg_0         ,
output wire [31:0]  n_arg_1         ,
output wire         ready           

);

reg         div_run     ;

wire        div_finished= (div_run && count == 32);
assign      ready       = div_finished;

wire        signed_lhs  = (op_signed) && rs1[31];
wire        signed_rhs  = (op_signed) && rs2[31];

wire        div_start   = valid     && !div_run;

wire [31:0] qmask       = (32'b1<<31  ) >> count  ;

wire        div_less    = acc <= {32'b0,arg_0};

wire [31:0] sub_result = arg_0 - acc[31:0];
        

wire [63:0] divisor_start = 
    {(signed_rhs ? -{rs2[31],rs2} : {1'b0,rs2}), 31'b0};


assign      n_acc       = div_start    ? divisor_start  :
                                         acc >> 1       ;

assign      n_arg_0     = div_start ? (signed_lhs ? -rs1 : rs1) :
                          div_less  ? sub_result                :
                                      arg_0                     ;

assign      n_arg_1     = div_start           ? 0               :
                          div_run && div_less ? arg_1 | qmask   :
                                                arg_1           ;

always @(posedge clock) begin
    if(!resetn   || flush) begin
        
        div_run  <= 1'b0;

    end else if(div_start) begin
        
        div_run  <= 1'b1;

    end else if(div_run) begin

        if(div_finished) begin

            div_run  <= 1'b0;

        end

    end
end

endmodule
module xc_sha512_ftb (

input clock,
input reset

);

reg [63:0] rs1   ; // Input source register 1
reg [ 1:0] ss    ; // Exactly which transformation to perform?
reg [63:0] result; // 

xc_sha512 i_xc_sha512 (
.rs1   (rs1   ), // Input source register 1
.ss    (ss    ), // Exactly which transformation to perform?
.result(result)  // 
);

endmodule
module xc_sha512 (

input  wire [63:0] rs1   , // Input source register 1
input  wire [ 1:0] ss    , // Exactly which transformation to perform?

output wire [63:0] result  // 

);

`define ROR64(a,b) ((a >> b) | (a << 64-b))
`define SRL64(a,b) ((a >> b)              )

//
// Which transformation to perform?
wire s0 = ss == 2'b00;
wire s1 = ss == 2'b01;
wire s2 = ss == 2'b10;
wire s3 = ss == 2'b11;

wire [63:0] s0_result = 
    (`ROR64(rs1, 1)) ^
    (`ROR64(rs1, 8)) ^
    (`SRL64(rs1, 7)) ;

wire [63:0] s1_result = 
    (`ROR64(rs1,19)) ^
    (`ROR64(rs1,61)) ^
    (`SRL64(rs1, 6)) ;

wire [63:0] s2_result = 
    (`ROR64(rs1,28)) ^
    (`ROR64(rs1,34)) ^
    (`ROR64(rs1,39)) ;

wire [63:0] s3_result = 
    (`ROR64(rs1,14)) ^
    (`ROR64(rs1,18)) ^
    (`ROR64(rs1,41)) ;

assign result =
    {64{s0}} & s0_result |
    {64{s1}} & s1_result |
    {64{s2}} & s2_result |
    {64{s3}} & s3_result ;

`undef ROR64
`undef SRL64

endmodule
module b_lut (

input  wire [31:0] crs1  , // Source register 1 (LUT input)
input  wire [31:0] crs2  , // Source register 2 (LUT bottom half)
input  wire [31:0] crs3  , // Source register 3 (LUT top half)

output wire [31:0] result  //

);


wire [ 3:0] lut_arr [15:0];
wire [63:0] lut_con = {crs1, crs2};

genvar i;
generate for (i = 0; i < 16; i = i + 1) begin

    assign lut_arr[i] = lut_con[4*i+3:4*i];

end endgenerate


genvar j;
generate for (j = 0; j < 8; j = j + 1) begin

    assign result[4*j+3:4*j] = lut_arr[crs3[4*j+3:4*j]];

end endgenerate

endmodule
module xc_sha256_ftb (

input clock,
input reset

);

reg [31:0] rs1   ; // Input source register 1
reg [ 1:0] ss    ; // Exactly which transformation to perform?
reg [31:0] result; // 

xc_sha256 i_xc_sha256 (
.rs1   (rs1   ), // Input source register 1
.ss    (ss    ), // Exactly which transformation to perform?
.result(result)  // 
);

endmodule
module xc_sha256 (

input  wire [31:0] rs1   , // Input source register 1
input  wire [ 1:0] ss    , // Exactly which transformation to perform?

output wire [31:0] result  // 

);

`define ROR32(a,b) ((a >> b) | (a << 32-b))
`define SRL32(a,b) ((a >> b)              )

//
// Which transformation to perform?
wire s0 = ss == 2'b00;
wire s1 = ss == 2'b01;
wire s2 = ss == 2'b10;
wire s3 = ss == 2'b11;

wire [31:0] s0_result = 
    (`ROR32(rs1, 7)) ^
    (`ROR32(rs1,18)) ^
    (`SRL32(rs1, 3)) ;

wire [31:0] s1_result = 
    (`ROR32(rs1,17)) ^
    (`ROR32(rs1,19)) ^
    (`SRL32(rs1,10)) ;

wire [31:0] s2_result = 
    (`ROR32(rs1, 2)) ^
    (`ROR32(rs1,13)) ^
    (`ROR32(rs1,22)) ;

wire [31:0] s3_result = 
    (`ROR32(rs1, 6)) ^
    (`ROR32(rs1,11)) ^
    (`ROR32(rs1,25)) ;

assign result =
    {32{s0}} & s0_result |
    {32{s1}} & s1_result |
    {32{s2}} & s2_result |
    {32{s3}} & s3_result ;

`undef ROR32
`undef SRL32

endmodule
module mgmt_protect_hv (
`ifdef USE_POWER_PINS
    inout	vccd,
    inout	vssd,
    inout	vdda1,
    inout	vssa1,
    inout	vdda2,
    inout	vssa2,
`endif

    output	mprj_vdd_logic1,
    output	mprj2_vdd_logic1

);

    wire mprj_vdd_logic1_h;
    wire mprj2_vdd_logic1_h;

`ifdef USE_POWER_PINS
    // This is to emulate the substrate shorting grounds together for LVS
    // purposes
    assign vssa2 = vssa1;
    assign vssa1 = vssd;
`endif

    // Logic high in the VDDA (3.3V) domains

    sky130_fd_sc_hvl__conb_1 mprj_logic_high_hvl (
`ifdef USE_POWER_PINS
        .VPWR(vdda1),
        .VGND(vssa1),
        .VPB(vdda1),
        .VNB(vssa1),
`endif
        .HI(mprj_vdd_logic1_h),
        .LO()
    );

    sky130_fd_sc_hvl__conb_1 mprj2_logic_high_hvl (
`ifdef USE_POWER_PINS
        .VPWR(vdda2),
        .VGND(vssa2),
        .VPB(vdda2),
        .VNB(vssa2),
`endif
        .HI(mprj2_vdd_logic1_h),
        .LO()
    );

    // Level shift the logic high signals into the 1.8V domain

    sky130_fd_sc_hvl__lsbufhv2lv_1 mprj_logic_high_lv (
`ifdef USE_POWER_PINS
	.VPWR(vdda1),
	.VGND(vssd),
	.LVPWR(vccd),
	.VPB(vdda1),
	.VNB(vssd),
`endif
	.X(mprj_vdd_logic1),
	.A(mprj_vdd_logic1_h)
    );

    sky130_fd_sc_hvl__lsbufhv2lv_1 mprj2_logic_high_lv (
`ifdef USE_POWER_PINS
	.VPWR(vdda2),
	.VGND(vssd),
	.LVPWR(vccd),
	.VPB(vdda2),
	.VNB(vssd),
`endif
	.X(mprj2_vdd_logic1),
	.A(mprj2_vdd_logic1_h)
    );
endmodule
module wb_intercon #(
    parameter DW = 32,          // Data Width
    parameter AW = 32,          // Address Width
    parameter NS = 6           // Number of Slaves
) (
    // Master Interface
    input [AW-1:0] wbm_adr_i,
    input wbm_stb_i,

    output reg [DW-1:0] wbm_dat_o,
    output wbm_ack_o,

    // Slave Interface
    input [NS*DW-1:0] wbs_dat_i,
    input [NS-1:0] wbs_ack_i,
    output [NS-1:0] wbs_stb_o
);
    parameter [NS*AW-1:0] ADR_MASK = {      // Page & Sub-page bits
        {8'hFF, {24{1'b0}} },
        {8'hFF, {24{1'b0}} },
        {8'hFF, {24{1'b0}} },
        {8'hFF, {24{1'b0}} },
        {8'hFF, {24{1'b0}} },
        {8'hFF, {24{1'b0}} }
    };
    parameter [NS*AW-1:0] SLAVE_ADR = {
        { 32'h2800_0000 },    // Flash Configuration Register
        { 32'h2200_0000 },    // System Control
        { 32'h2100_0000 },    // GPIOs
        { 32'h2000_0000 },    // UART 
        { 32'h1000_0000 },    // Flash 
        { 32'h0000_0000 }     // RAM
    };
    
    wire [NS-1: 0] slave_sel;

    // Address decoder
    genvar iS;
    generate
        for (iS = 0; iS < NS; iS = iS + 1) begin
            assign slave_sel[iS] = 
                ((wbm_adr_i & ADR_MASK[(iS+1)*AW-1:iS*AW]) == SLAVE_ADR[(iS+1)*AW-1:iS*AW]);
        end
    endgenerate

    // Data-out Assignment
    assign wbm_ack_o = |(wbs_ack_i & slave_sel);
    assign wbs_stb_o =  {NS{wbm_stb_i}} & slave_sel;

    integer i;
    always @(*) begin
        wbm_dat_o = {DW{1'b0}};
        for (i=0; i<(NS*DW); i=i+1)
            wbm_dat_o[i%DW] = wbm_dat_o[i%DW] | (slave_sel[i/DW] & wbs_dat_i[i]);
    end
 
endmodule
module mprj_logic_high (
`ifdef USE_POWER_PINS
    inout	   vccd1,
    inout	   vssd1,
`endif
    output [461:0] HI
);
sky130_fd_sc_hd__conb_1 insts [461:0] (
`ifdef USE_POWER_PINS
                .VPWR(vccd1),
                .VGND(vssd1),
                .VPB(vccd1),
                .VNB(vssd1),
`endif
                .HI(HI),
                .LO()
        );
endmodule
module spimemio_wb (
    input wb_clk_i,
    input wb_rst_i,

    input [31:0] wb_adr_i, 
    input [31:0] wb_dat_i,
    input [3:0] wb_sel_i,
    input wb_we_i,
    input wb_cyc_i,

    input wb_flash_stb_i,
    input wb_cfg_stb_i,

    output wb_flash_ack_o,
    output wb_cfg_ack_o,

    output [31:0] wb_flash_dat_o,
    output [31:0] wb_cfg_dat_o,

    output quad_mode,
    input  pass_thru,
    input  pass_thru_csb,
    input  pass_thru_sck,
    input  pass_thru_sdi,
    output pass_thru_sdo,

    output flash_csb,
    output flash_clk,

    output flash_csb_oeb,
    output flash_clk_oeb,

    output flash_io0_oeb,
    output flash_io1_oeb,
    output flash_io2_oeb,
    output flash_io3_oeb,

    output flash_csb_ieb,
    output flash_clk_ieb,

    output flash_io0_ieb,
    output flash_io1_ieb,
    output flash_io2_ieb,
    output flash_io3_ieb,

    output flash_io0_do,
    output flash_io1_do,
    output flash_io2_do,
    output flash_io3_do,

    input  flash_io0_di,
    input  flash_io1_di,
    input  flash_io2_di,
    input  flash_io3_di

);
    wire spimem_ready;
    wire [23:0] mem_addr;
    wire [31:0] spimem_rdata;
    wire [31:0] spimemio_cfgreg_do;
    wire [3:0] cfgreg_we;
    wire spimemio_cfgreg_sel;
    wire valid;
    wire resetn;
    wire quad_mode;

    assign resetn = ~wb_rst_i;
    assign valid = wb_cyc_i && wb_flash_stb_i;    
    assign wb_flash_ack_o = spimem_ready;
    assign wb_cfg_ack_o = spimemio_cfgreg_sel;

    assign mem_addr = wb_adr_i[23:0];
    assign spimemio_cfgreg_sel = wb_cyc_i && wb_cfg_stb_i;

    assign cfgreg_we = spimemio_cfgreg_sel ? wb_sel_i & {4{wb_we_i}} : 4'b 0000;
    assign wb_flash_dat_o = spimem_rdata;
    assign wb_cfg_dat_o = spimemio_cfgreg_do;

    spimemio spimemio (
        .clk    (wb_clk_i),
        .resetn (resetn),
        .valid  (valid),
        .ready  (spimem_ready),
        .addr   (mem_addr),
        .rdata  (spimem_rdata),

        .flash_csb    (flash_csb),
        .flash_clk    (flash_clk),

        .flash_csb_oeb (flash_csb_oeb),
        .flash_clk_oeb (flash_clk_oeb),

        .flash_io0_oeb (flash_io0_oeb),
        .flash_io1_oeb (flash_io1_oeb),
        .flash_io2_oeb (flash_io2_oeb),
        .flash_io3_oeb (flash_io3_oeb),

        .flash_csb_ieb (flash_csb_ieb),
        .flash_clk_ieb (flash_clk_ieb),

        .flash_io0_ieb (flash_io0_ieb),
        .flash_io1_ieb (flash_io1_ieb),
        .flash_io2_ieb (flash_io2_ieb),
        .flash_io3_ieb (flash_io3_ieb),

        .flash_io0_do (flash_io0_do),
        .flash_io1_do (flash_io1_do),
        .flash_io2_do (flash_io2_do),
        .flash_io3_do (flash_io3_do),

        .flash_io0_di (flash_io0_di),
        .flash_io1_di (flash_io1_di),
        .flash_io2_di (flash_io2_di),
        .flash_io3_di (flash_io3_di),

        .cfgreg_we(cfgreg_we),
        .cfgreg_di(wb_dat_i),
        .cfgreg_do(spimemio_cfgreg_do),

	.quad_mode(quad_mode),
	.pass_thru(pass_thru),
	.pass_thru_csb(pass_thru_csb),
	.pass_thru_sck(pass_thru_sck),
	.pass_thru_sdi(pass_thru_sdi),
	.pass_thru_sdo(pass_thru_sdo)
    );

endmodule
module user_project_wrapper #(
    parameter BITS = 32
)(
`ifdef USE_POWER_PINS
    inout vdda1,	// User area 1 3.3V supply
    inout vdda2,	// User area 2 3.3V supply
    inout vssa1,	// User area 1 analog ground
    inout vssa2,	// User area 2 analog ground
    inout vccd1,	// User area 1 1.8V supply
    inout vccd2,	// User area 2 1.8v supply
    inout vssd1,	// User area 1 digital ground
    inout vssd2,	// User area 2 digital ground
`endif

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

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

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

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

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

    // User maskable interrupt signals
    output [2:0] user_irq
);

// Dummy assignments so that we can take it through the openlane flow
`ifdef SIM
// Needed for running GL simulation
assign io_out = 0;
assign io_oeb = 0;
`else
assign io_out = io_in;
`endif

endmodule	// user_project_wrapper
module gpio_logic_high(
 `ifdef USE_POWER_PINS
         inout vccd1,
         inout vssd1,
  `endif

   output wire gpio_logic1
);

 sky130_fd_sc_hd__conb_1 gpio_logic_high (
`ifdef USE_POWER_PINS
            .VPWR(vccd1),
            .VGND(vssd1),
            .VPB(vccd1),
            .VNB(vssd1),
`endif
            .HI(gpio_logic1),
            .LO()
    );

endmodule
module DFFRAM_1K (
`ifdef USE_POWER_PINS
    input VPWR,
    input VGND,
`endif
    input CLK,
    input [3:0] WE,
    input EN,
    input [31:0] Di,
    output reg [31:0] Do,
    input [7:0] A
);
  

reg [31:0] mem [0:`MEM_WORDS-1];

always @(posedge CLK) begin
    if (EN == 1'b1) begin
        Do <= mem[A];
        if (WE[0]) mem[A][ 7: 0] <= Di[ 7: 0];
        if (WE[1]) mem[A][15: 8] <= Di[15: 8];
        if (WE[2]) mem[A][23:16] <= Di[23:16];
        if (WE[3]) mem[A][31:24] <= Di[31:24];
    end
end
endmodule
module DFFRAM #(parameter   USE_LATCH=`DFFRAM_USE_LATCH,
                            WSIZE=`DFFRAM_WSIZE ) 
(
`ifdef USE_POWER_PINS
    input wire VPWR,
    input wire VGND,
`endif
    input   wire                CLK,    // FO: 2
    input   wire [WSIZE-1:0]     WE,     // FO: 2
    input                       EN,     // FO: 2
    input   wire [7:0]          A,      // FO: 5
    input   wire [(WSIZE*8-1):0] Di,     // FO: 2
    output  wire [(WSIZE*8-1):0] Do

);

    wire [1:0]             SEL;
    wire [(WSIZE*8-1):0]    Do_pre[1:0]; 

    // 1x2 DEC
    DEC1x2 DEC (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .EN(EN),
        .A(A[7]),
        .SEL(SEL)
    );

    // sky130_fd_sc_hd__inv_2 DEC (
    //  `ifdef USE_POWER_PINS
    //     .VPWR(VPWR),
    //     .VGND(VGND),
    //     .VPB(VPWR),
    //     .VNB(VGND),
    // `endif
    //     .Y(SEL[0]), .A(A[7]));
    // assign SEL[1] = A[7];

    generate
        genvar i;
        for (i=0; i< 2; i=i+1) begin : BLOCK
            RAM128 #(.USE_LATCH(USE_LATCH), .WSIZE(WSIZE)) RAM128 (
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
            `endif
                .CLK(CLK), .EN(SEL[i]), .WE(WE), .Di(Di), .Do(Do_pre[i]), .A(A[6:0]) );        
        end
     endgenerate

    // Output MUX    
    MUX2x1 #(.WIDTH(WSIZE*8)) DoMUX ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .A0(Do_pre[0]), .A1(Do_pre[1]), .S(A[7]), .X(Do) );

endmodule
module simple_spi_master_wb #(
    parameter BASE_ADR = 32'h2100_0000,
    parameter CONFIG = 8'h00,
    parameter DATA = 8'h04
) (
    input wb_clk_i,
    input wb_rst_i,
    input [31:0] wb_adr_i,
    input [31:0] wb_dat_i,
    input [3:0] wb_sel_i,
    input wb_we_i,
    input wb_cyc_i,
    input wb_stb_i,
    output wb_ack_o,
    output [31:0] wb_dat_o,

    output	 hk_connect,	// Connect to housekeeping SPI
    output	 spi_enabled,	// Use to mux pins with GPIO control
    input 	 sdi,	 // SPI input
    output 	 csb,	 // SPI chip select
    output 	 sck,	 // SPI clock
    output 	 sdo,	 // SPI output
    output 	 sdoenb, // SPI output enable
    output	 irq	 // interrupt output
);

    wire [31:0] simple_spi_master_reg_cfg_do;
    wire [31:0] simple_spi_master_reg_dat_do;

    wire resetn = ~wb_rst_i;
    wire valid = wb_stb_i && wb_cyc_i;
    wire simple_spi_master_reg_cfg_sel = valid && (wb_adr_i == (BASE_ADR | CONFIG));
    wire simple_spi_master_reg_dat_sel = valid && (wb_adr_i == (BASE_ADR | DATA));

    wire [1:0] reg_cfg_we = (simple_spi_master_reg_cfg_sel) ?
		(wb_sel_i[1:0] & {2{wb_we_i}}): 2'b00;
    wire reg_dat_we = (simple_spi_master_reg_dat_sel) ? (wb_sel_i[0] & wb_we_i): 1'b0;
    wire reg_dat_wait;

    wire [31:0] mem_wdata = wb_dat_i;
    wire reg_dat_re = simple_spi_master_reg_dat_sel && !wb_sel_i && ~wb_we_i;

    assign wb_dat_o = (simple_spi_master_reg_cfg_sel) ? simple_spi_master_reg_cfg_do :
		simple_spi_master_reg_dat_do;
    assign wb_ack_o = (simple_spi_master_reg_cfg_sel || simple_spi_master_reg_dat_sel)
		&& (!reg_dat_wait);

    simple_spi_master spi_master (
    	.resetn(resetn),
    	.clk(wb_clk_i),
    	.reg_cfg_we(reg_cfg_we),
    	.reg_cfg_di(mem_wdata),
    	.reg_cfg_do(simple_spi_master_reg_cfg_do),
    	.reg_dat_we(reg_dat_we),
    	.reg_dat_re(reg_dat_re),
    	.reg_dat_di(mem_wdata),
    	.reg_dat_do(simple_spi_master_reg_dat_do),
    	.reg_dat_wait(reg_dat_wait),

	.hk_connect(hk_connect),	// Attach to housekeeping SPI slave
	.spi_enabled(spi_enabled),	// Mux pins with GPIO
    	.sdi(sdi),	 // SPI input
    	.csb(csb),	 // SPI chip select
    	.sck(sck),	 // SPI clock
    	.sdo(sdo),	 // SPI output
	.irq_out(irq)	 // interrupt
    );
endmodule
module la_wb # (
    parameter BASE_ADR  = 32'h 2200_0000,
    parameter LA_DATA_0 = 8'h00,
    parameter LA_DATA_1 = 8'h04,
    parameter LA_DATA_2 = 8'h08,
    parameter LA_DATA_3 = 8'h0c,
    parameter LA_OENB_0 = 8'h10,
    parameter LA_OENB_1 = 8'h14,
    parameter LA_OENB_2 = 8'h18,
    parameter LA_OENB_3 = 8'h1c,
    parameter LA_IENA_0 = 8'h20,
    parameter LA_IENA_1 = 8'h24,
    parameter LA_IENA_2 = 8'h28,
    parameter LA_IENA_3 = 8'h2c,
    parameter LA_SAMPLE = 8'h30
) (
    input wb_clk_i,
    input wb_rst_i,

    input [31:0] wb_dat_i,
    input [31:0] wb_adr_i,
    input [3:0] wb_sel_i,
    input wb_cyc_i,
    input wb_stb_i,
    input wb_we_i,

    output [31:0] wb_dat_o,
    output wb_ack_o,

    input  [127:0] la_data_in, // From MPRJ 
    output [127:0] la_data,
    output [127:0] la_oenb,
    output [127:0] la_iena
);

    wire resetn;
    wire valid;
    wire ready;
    wire [3:0] iomem_we;

    assign resetn = ~wb_rst_i;
    assign valid = wb_stb_i && wb_cyc_i; 

    assign iomem_we = wb_sel_i & {4{wb_we_i}};
    assign wb_ack_o = ready;

    la #(
        .BASE_ADR(BASE_ADR),
        .LA_DATA_0(LA_DATA_0),
        .LA_DATA_1(LA_DATA_1),
        .LA_DATA_2(LA_DATA_2),
        .LA_DATA_3(LA_DATA_3),
        .LA_OENB_0(LA_OENB_0),
        .LA_OENB_1(LA_OENB_1),
        .LA_OENB_2(LA_OENB_2),
        .LA_OENB_3(LA_OENB_3),
        .LA_IENA_0(LA_IENA_0),
        .LA_IENA_1(LA_IENA_1),
        .LA_IENA_2(LA_IENA_2),
        .LA_IENA_3(LA_IENA_3),
        .LA_SAMPLE(LA_SAMPLE)
    ) la_ctrl (
        .clk(wb_clk_i),
        .resetn(resetn),
        .iomem_addr(wb_adr_i),
        .iomem_valid(valid),
        .iomem_wstrb(iomem_we),
        .iomem_wdata(wb_dat_i),
        .iomem_rdata(wb_dat_o),
        .iomem_ready(ready),
        .la_data_in(la_data_in),
        .la_data(la_data),
        .la_oenb(la_oenb),
        .la_iena(la_iena)
    );
    
endmodule
module user_project_wrapper #(
    parameter BITS = 32
)(
`ifdef USE_POWER_PINS
    inout vdda1,	// User area 1 3.3V supply
    inout vdda2,	// User area 2 3.3V supply
    inout vssa1,	// User area 1 analog ground
    inout vssa2,	// User area 2 analog ground
    inout vccd1,	// User area 1 1.8V supply
    inout vccd2,	// User area 2 1.8v supply
    inout vssd1,	// User area 1 digital ground
    inout vssd2,	// User area 2 digital ground
`endif

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

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

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

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

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

    // User maskable interrupt signals
    output [2:0] user_irq
);


// Dummy assignments so that we can take it through the openlane flow
`ifdef SIM
// Needed for running GL simulation
assign io_out = 0;
assign io_oeb = 0;
`else
assign io_out = io_in;
`endif

endmodule	// user_project_wrapper
module pll_tb;
	reg clock;
	reg power1;
	reg power2;
	reg RSTB;

	wire gpio;
	wire [15:0] checkbits;
	wire [7:0] spivalue;
	wire [37:0] mprj_io;
	wire flash_csb;
	wire flash_clk;
	wire flash_io0;
	wire flash_io1;
	wire SDO;

	assign checkbits = mprj_io[31:16];
	assign spivalue  = mprj_io[15:8];

	// External clock is used by default.  Make this artificially fast for the
	// simulation.  Normally this would be a slow clock and the digital PLL
	// would be the fast clock.

	always #10 clock <= (clock === 1'b0);

	initial begin
		clock = 0;
	end

	initial begin
		$dumpfile("pll.vcd");
		$dumpvars(0, pll_tb);
		repeat (25) begin
			repeat (1000) @(posedge clock);
			$display("+1000 cycles");
		end
		$display("%c[1;31m",27);
		$display ("Monitor: Timeout, Test PLL (RTL) Failed");
		$display("%c[0m",27);
		$finish;
	end

	// Monitor
	initial begin
	    wait(checkbits == 16'hA040);
		
		$display("Monitor: Test PLL (RTL) Started");
		
	    wait(checkbits == 16'hA041);
            // $display("   SPI value = 0x%x (should be 0x04)", spivalue);
            // if(spivalue !== 32'h04) begin
            //     $display("Monitor: Test PLL (RTL) Failed");
            //     $finish;
            // end
	    wait(checkbits == 16'hA042);
            // $display("   SPI value = 0x%x (should be 0x56)", spivalue);
            // if(spivalue !== 32'h56) begin
            //     $display("Monitor: Test PLL (RTL) Failed");
            //     $finish;
            // end

	    wait(checkbits == 16'hA090);

		$display("Monitor: Test PLL (RTL) Passed");
		$finish;
	end

	initial begin
		RSTB <= 1'b0;
		#1000;
		RSTB <= 1'b1;	    // Release reset
		#2000;
	end

	initial begin
		power1 <= 1'b0;
		power2 <= 1'b0;
		#200;
		power1 <= 1'b1;
		#200;
		power2 <= 1'b1;
	end

	always @(checkbits) begin
		#1 $display("GPIO state = %b ", checkbits);
	end

	wire VDD3V3;
	wire VDD1V8;
	wire VSS;
	
	assign VDD3V3 = power1;
	assign VDD1V8 = power2;
	assign VSS = 1'b0;

	assign mprj_io[3] = 1'b1;  // Force CSB high.

	caravel uut (
		.vddio	  (VDD3V3),
		.vssio	  (VSS),
		.vdda	  (VDD3V3),
		.vssa	  (VSS),
		.vccd	  (VDD1V8),
		.vssd	  (VSS),
		.vdda1    (VDD3V3),
		.vdda2    (VDD3V3),
		.vssa1	  (VSS),
		.vssa2	  (VSS),
		.vccd1	  (VDD1V8),
		.vccd2	  (VDD1V8),
		.vssd1	  (VSS),
		.vssd2	  (VSS),
		.clock    (clock),
		.gpio     (gpio),
		.mprj_io  (mprj_io),
		.flash_csb(flash_csb),
		.flash_clk(flash_clk),
		.flash_io0(flash_io0),
		.flash_io1(flash_io1),
		.resetb	  (RSTB)
	);

	spiflash #(
		.FILENAME("pll.hex")
	) spiflash (
		.csb(flash_csb),
		.clk(flash_clk),
		.io0(flash_io0),
		.io1(flash_io1),
		.io2(),			// not used
		.io3()			// not used
	);

endmodule
module irq_tb;

	reg clock;
	reg power1;
	reg power2;

	always #10 clock <= (clock === 1'b0);

	initial begin
		clock <= 0;
	end

	initial begin
		$dumpfile("irq.vcd");
		$dumpvars(0, irq_tb);
		
		// Repeat cycles of 1000 clock edges as needed to complete testbench
		repeat (12) begin
			repeat (1000) @(posedge clock);
			$display("+1000 cycles");
		end
		$display("%c[1;31m",27);
		`ifdef GL
			$display ("Monitor: Timeout, Test IRQ (GL) Failed");
		`else
			$display ("Monitor: Timeout, Test IRQ (RTL) Failed");
		`endif
		$display("%c[0m",27);
		$finish;
	end

	wire [37:0] mprj_io;	// Most of these are no-connects
	wire [3:0]  status;
	wire [3:0] checkbits;

	assign checkbits = mprj_io[19:16];
	assign status = mprj_io[35:32];
	assign mprj_io[3] = 1'b1;	// Force CSB high.

	wire flash_csb;
	wire flash_clk;
	wire flash_io0;
	wire flash_io1;
	wire gpio;

	reg RSTB;

	// Monitor
	initial begin
		wait(status == 4'h5);
		`ifdef GL
			$display("Monitor: Test IRQ (GL) Started");
		`else
			$display("Monitor: Test IRQ (RTL) Started");
		`endif
		wait(status == 4'ha);
		wait(status == 4'hc);
		`ifdef GL
			$display("Monitor: Test IRQ (GL) Passed");
		`else
			$display("Monitor: Test IRQ (RTL) Passed");
		`endif
		$finish;
	end

	initial begin
		RSTB <= 1'b0;
		#1000;
		RSTB <= 1'b1;		// Release reset
		#2000;
	end

	initial begin			// Power-up
		power1 <= 1'b0;
		power2 <= 1'b0;
		#200;
		power1 <= 1'b1;
		#200;
		power2 <= 1'b1;
	end
               
	always @(checkbits, status) begin
		#1 $display("GPIO state = %b (%b)", checkbits, status);
	end

	wire VDD3V3;
	wire VDD1V8;
	wire VSS;

	assign VDD3V3 = power1;
	assign VDD1V8 = power2;
	assign VSS = 1'b0;

	// These are the mappings of mprj_io GPIO pads that are set to
	// specific functions on startup:
	//
	// JTAG      = mgmt_gpio_io[0]              (inout)
	// SDO       = mgmt_gpio_io[1]              (output)
	// SDI       = mgmt_gpio_io[2]              (input)
	// CSB       = mgmt_gpio_io[3]              (input)
	// SCK       = mgmt_gpio_io[4]              (input)
	// ser_rx    = mgmt_gpio_io[5]              (input)
	// ser_tx    = mgmt_gpio_io[6]              (output)
	// irq       = mgmt_gpio_io[7]              (input)

	caravel uut (
		.vddio	  (VDD3V3),
		.vssio    (VSS),
		.vdda     (VDD3V3),
		.vssa     (VSS),
		.vccd     (VDD1V8),
		.vssd     (VSS),
		.vdda1    (VDD3V3),
		.vdda2    (VDD3V3),
		.vssa1    (VSS),
		.vssa2    (VSS),
		.vccd1    (VDD1V8),
		.vccd2    (VDD1V8),
		.vssd1    (VSS),
		.vssd2    (VSS),
		.clock    (clock),
		.gpio     (gpio),
		.mprj_io  (mprj_io),
		.flash_csb(flash_csb),
		.flash_clk(flash_clk),
		.flash_io0(flash_io0),
		.flash_io1(flash_io1),
		.resetb   (RSTB)
	);

	spiflash #(
		.FILENAME("irq.hex")
	) spiflash (
		.csb(flash_csb),
		.clk(flash_clk),
		.io0(flash_io0),
		.io1(flash_io1),
		.io2(),			// not used
		.io3()			// not used
	);

endmodule
module darkcache
(
    input           CLK,    // clock
    input           RES,    // reset

    input           RW,     // read/write
    input   [2:0]   DLEN,   // data length in bytes

    input   [31:0]  ADDR,   // address
    input   [31:0]  DATA,   // data input
    output  [31:0]  DATO,   // data output
    
    output          HIT,    // cache hit
    output          DTREQ,  // cache miss, data transfer req
    input           DTACK,  // cache miss, data transfer ack
    
    output  [3:0]   DEBUG   // osciloscope
);

    reg  [31:0] CDATA [0:2**`DEPTH-1];
    reg  [31:`DEPTH+2] CTAG  [0:2**`DEPTH-1];
    
    // reg  [2**`DEPTH-1:0] CVALID = 0;
    reg  CVALID [0:2**`DEPTH-1];
    
    reg  [31:0] CDATAFF;
    
    integer i;
    
    initial for(i=0;i!=2**`DEPTH;i=i+1) CVALID[i] = 0;

    wire [`DEPTH-1:0]  CINDEX = ADDR[`DEPTH+1:2];

    assign HIT = RES ? 0 : 
                 (DLEN && RW==1 && CVALID[CINDEX] && CTAG[CINDEX]==ADDR[31:`DEPTH+2])||
                 (DLEN && RW==0 && DTREQ && DTACK);

    assign DTREQ = RES ? 0 : DLEN && (!HIT||!RW); // valid data, but not hit -> dtreq

    // debug only

    wire [7:0] DATX [0:3];
    
    assign DATX[0] = DATO[ 7: 0];
    assign DATX[1] = DATO[15: 8];
    assign DATX[2] = DATO[23:16];
    assign DATX[3] = DATO[31:24];

    always@(posedge CLK)
    begin
        if(DTREQ&&DTACK)
        begin
            CDATA [CINDEX]  <= DATA;
            CTAG  [CINDEX]  <= ADDR[31:`DEPTH+2];
            CVALID[CINDEX]  <= RW;
        end
        
        if(!RES) $display("cache %s ADDR=%x RW=%d DTREQ=%d DTACK=%d DATA=%x DATO=%x BUS=%s",
                                (HIT?"hit":"miss"),
                                ADDR,RW,DTREQ,DTACK,DATA,DATX[ADDR[1:0]],
                                (DTREQ?"busy":"idle")); 

        CDATAFF <= CDATA[CINDEX];
    end

    assign DATO  = CDATAFF;

    assign DEBUG = { |DLEN, HIT, DTREQ, DTACK };

endmodule
module darkcache_sim;

    // clock

    reg CLK = 0;
    
    integer i;
    
    initial for(i=0;i!=100;i=i+1) #10 CLK = !CLK;

    // reset

    reg [2:0] RES = -1;
    
    always@(posedge CLK) RES <= RES ? RES-1 : 0;

    // logic

    wire  HLT,HIT,DTREQ;

    reg  [2:0]      DLEN=0;
    reg             RW=1;
    reg  [3:0]      DTACK=0;
    reg  [31:0]     ADDR=0,DATA=0;
    wire [31:0]     DATO;
    
    assign HLT = DLEN && !HIT;
    
    always@(posedge CLK)
    begin
        // core part
    
        if(!RES && !HLT)
        begin
            DLEN <= 1; // 1 byte
            if(DLEN)
            begin
                ADDR <= ADDR==10 ? 5 : ADDR+1;
                if(ADDR==10) RW <= !RW;
            end
        end
        
        // slow memory part

        DTACK <= DTACK ? DTACK-1 : DTREQ ? 1 : 0;
        if(DTREQ) DATA  <= ADDR[3:0] + (ADDR[3:0]+1)*256 + (ADDR[3:0]+2)*65536 + (ADDR[3:0]+3)*16777216;
    end

    wire [3:0] DEBUG;

    darkcache icache(CLK,RES?1'b1:1'b0,RW,DLEN,ADDR,DATA,DATO,HIT,DTREQ,DTREQ?DTACK==1:1'b0,DEBUG);

endmodule
module darksimv;

    reg CLK = 0;
    
    reg RES = 1;

    initial while(1) #(500e6/`BOARD_CK) CLK = !CLK; // clock generator w/ freq defined by config.vh

    integer i;

    initial
    begin
`ifdef __ICARUS__
        $dumpfile("darksocv.vcd");
        $dumpvars();

    `ifdef __REGDUMP__
        for(i=0;i!=`RLEN;i=i+1)
        begin
            $dumpvars(0,soc0.core0.REGS[i]);
        end
    `endif
`endif
        $display("reset (startup)");
        #1e3    RES = 0;            // wait 1us in reset state
        //#1000e3 RES = 1;            // run  1ms
        //$display("reset (restart)");
        //#1e3    RES = 0;            // wait 1us in reset state
        //#1000e3 $finish();          // run  1ms
    end

    wire TX;
    wire RX = 1;

`ifdef __SDRAM__

    // sdram sim model!

    wire        S_NWE,S_CLK;
    reg [15:0]  S_DBFF = 0;  
    wire [15:0] S_DB = S_NWE ? S_DBFF : 16'hzzzz;

    always@(posedge S_CLK)
    begin
        if(S_NWE==0) S_DBFF <= S_DB;
    end

`endif

    darksocv soc0
    (
        .XCLK(CLK),
        .XRES(|RES),
`ifdef __SDRAM__        
        .S_CLK(S_CLK),
        .S_NWE(S_NWE),
        .S_DB (S_DB),
`endif        
        .UART_RXD(RX),
        .UART_TXD(TX)
    );

endmodule