dakies/OSS_Verilog huggingface dataset:
module DEC3x8 (
`ifdef USE_POWER_PINS
    input VPWR,
    input VGND,
`endif
    input           EN,
    input [2:0]     A,
    output [7:0]    SEL
);
    sky130_fd_sc_hd__nor4b_2   AND0 ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .Y(SEL[0]),
        .A(A[0]),
        .B(A[1]),
        .C(A[2]),
        .D_N(EN)
    ); // 000

    sky130_fd_sc_hd__and4bb_2   AND1 ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(SEL[1]),
        .A_N(A[2]),
        .B_N(A[1]),
        .C(A[0]),
        .D(EN)
    ); // 001

    sky130_fd_sc_hd__and4bb_2   AND2 ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(SEL[2]),
        .A_N(A[2]),
        .B_N(A[0]),
        .C(A[1]),
        .D(EN) 
    ); // 010

    sky130_fd_sc_hd__and4b_2    AND3 ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(SEL[3]),
        .A_N(A[2]),
        .B(A[1]),
        .C(A[0]),
        .D(EN) 
    );   // 011

    sky130_fd_sc_hd__and4bb_2   AND4 ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(SEL[4]),
        .A_N(A[0]),
        .B_N(A[1]),
        .C(A[2]),
        .D(EN) 
    ); // 100

    sky130_fd_sc_hd__and4b_2    AND5 ( 
     `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(SEL[5]),
        .A_N(A[1]),
        .B(A[0]),
        .C(A[2]),
        .D(EN)
    );   // 101

    sky130_fd_sc_hd__and4b_2    AND6 ( 
     `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(SEL[6]),
        .A_N(A[0]),
        .B(A[1]), 
        .C(A[2]),
        .D(EN) 
    );   // 110

    sky130_fd_sc_hd__and4_2     AND7 ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(SEL[7]),
        .A(A[0]),
        .B(A[1]),
        .C(A[2]), 
        .D(EN)
    ); // 111
endmodule
module DEC6x64 (
`ifdef USE_POWER_PINS
    input VPWR,
    input VGND,
`endif
    input           EN,
    input   [5:0]   A,
    output  [63:0] SEL
);
    wire [7:0] SEL0_w ;
    wire [2:0] A_buf;
    
    DEC3x8 DEC_L0 ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .EN(EN),
        .A(A[5:3]),
        .SEL(SEL0_w)
    );

    sky130_fd_sc_hd__clkbuf_16 ABUF[2:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(A_buf),
        .A(A[2:0])
    );

    generate
        genvar i;
        for(i=0; i<8; i=i+1) begin : DEC_L1
            DEC3x8 U ( 
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
            `endif
                .EN(SEL0_w[i]),
                .A(A_buf),
                .SEL(SEL[7+8*i: 8*i])
            );
        end
    endgenerate
endmodule
module MUX2x1_32(
`ifdef USE_POWER_PINS
    input VPWR,
    input VGND,
`endif
    input   [31:0]      A0, A1,
    input   [0:0]       S,
    output  [31:0]      X
);
    sky130_fd_sc_hd__mux2_1 MUX[31:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A0(A0),
        .A1(A1),
        .S(S[0]),
        .X(X)
    );

endmodule
module MUX4x1_32(
`ifdef USE_POWER_PINS
    input VPWR,
    input VGND,
`endif
    input   [31:0]      A0, A1, A2, A3,
    input   [1:0]       S,
    output  [31:0]      X
);
    sky130_fd_sc_hd__mux4_1 MUX[31:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A0(A0), 
        .A1(A1),
        .A2(A2),
        .A3(A3),
        .S0(S[0]),
        .S1(S[1]),
        .X(X)
    );
endmodule
module PASS (
`ifdef USE_POWER_PINS
    input VPWR,
    input VGND,
`endif
    input [31:0] A,
    output [31:0] X
);
    assign X = A;
endmodule
module SRAM64x32(
`ifdef USE_POWER_PINS
    input VPWR,
    input VGND,
`endif
    input CLK,
    input [3:0] WE,
    input EN,
    input [31:0] Di,
    output [31:0] Do,
    input [5:0] A
);

    wire [63:0]     SEL;
    wire [31:0]     Do_pre;
    wire [31:0]     Di_buf;
    wire            CLK_buf;
    wire [3:0]      WE_buf;

    sky130_fd_sc_hd__clkbuf_16 CLKBUF (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(CLK_buf),
        .A(CLK)
    );
    
    sky130_fd_sc_hd__clkbuf_16 WEBUF[3:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(WE_buf),
        .A(WE)
    );

    sky130_fd_sc_hd__clkbuf_16 DIBUF[31:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(Di_buf),
        .A(Di)
    );

    DEC6x64 DEC  ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .EN(EN),
        .A(A),
        .SEL(SEL)
    );

    generate
        genvar i;
        for (i=0; i< 64; i=i+1) begin : WORD
            WORD32 W ( 
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
            `endif
                .CLK(CLK_buf),
                .WE(WE_buf),
                .SEL(SEL[i]),
                .Di(Di_buf),
                .Do(Do_pre)
            );
        end
    endgenerate

    // Ensure that the Do_pre lines are not floating when EN = 0
    wire lo;
    wire float_buf_en;
    sky130_fd_sc_hd__clkbuf_4 FBUFENBUF( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(float_buf_en),
        .A(EN)
    );

    sky130_fd_sc_hd__conb_1 TIE (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .LO(lo),
        .HI()
    );

    sky130_fd_sc_hd__ebufn_4 FLOATBUF[31:0] ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A( lo ),
        .Z(Do_pre),
        .TE_B(float_buf_en)
    );

    generate 
        //genvar i;
        for(i=0; i<32; i=i+1) begin : OUT
            sky130_fd_sc_hd__dfxtp_1 FF ( 
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
                .VPB(VPWR),
                .VNB(VGND),
            `endif
                .D(Do_pre[i]),
                .Q(Do[i]),
                .CLK(CLK)
            );
        end
    endgenerate 

endmodule
module DFFRAM_COL4 
(
`ifdef USE_POWER_PINS
    VPWR,
    VGND,
`endif
    CLK,
    WE,
    EN,
    Di,
    Do,
    A
);

    input           CLK;
    input   [3:0]   WE;
    input           EN;
    input   [31:0]  Di;
    output  [31:0]  Do;
    input   [7:0]   A;

`ifdef USE_POWER_PINS
    input VPWR;
    input VGND;
`endif

    wire [31:0]     Di_buf;
    wire [31:0]     Do_pre;
    wire            CLK_buf;
    wire [3:0]      WE_buf;
    wire [5:3]      A_buf;

    wire [31:0]     Do_B_0_0;
    wire [31:0]     Do_B_0_1;
    wire [31:0]     Do_B_0_2;
    wire [31:0]     Do_B_0_3;

    wire [3:0]      row_sel;

    sky130_fd_sc_hd__clkbuf_8 CLKBUF (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(CLK_buf),
        .A(CLK)
    );

    sky130_fd_sc_hd__clkbuf_8 WEBUF[3:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(WE_buf),
        .A(WE)
    );

    sky130_fd_sc_hd__clkbuf_8 DIBUF[31:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(Di_buf), 
        .A(Di)
    );

    sky130_fd_sc_hd__clkbuf_16 ABUF[2:0] ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(A_buf),
        .A(A[5:3])
    );
    
    DEC2x4 DEC ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR), 
        .VGND(VGND),
    `endif
        .EN(EN),
        .A(A[7:6]),
        .SEL(row_sel)
    );

    SRAM64x32 B_0_0 ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .CLK(CLK_buf),
        .WE(WE_buf),
        .EN(row_sel[0]),
        .Di(Di_buf),
        .Do(Do_B_0_0),
        .A({A_buf,A[2:0]})
    );

    SRAM64x32 B_0_1 ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR), 
        .VGND(VGND),
    `endif
        .CLK(CLK_buf),
        .WE(WE_buf),
        .EN(row_sel[1]),
        .Di(Di_buf),
        .Do(Do_B_0_1),
        .A({A_buf,A[2:0]})
    );

    SRAM64x32 B_0_2 ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .CLK(CLK_buf),
        .WE(WE_buf),
        .EN(row_sel[2]),
        .Di(Di_buf),
        .Do(Do_B_0_2), 
        .A({A_buf,A[2:0]}) 
    );

    SRAM64x32 B_0_3 ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .CLK(CLK_buf),
        .WE(WE_buf),
        .EN(row_sel[3]),
        .Di(Di_buf),
        .Do(Do_B_0_3),
        .A({A_buf,A[2:0]})
    );

    MUX4x1_32 MUX ( 
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .A0(Do_B_0_0),
        .A1(Do_B_0_1),
        .A2(Do_B_0_2),
        .A3(Do_B_0_3),
        .S(A[7:6]),
        .X(Do)
    );

endmodule
module delay_stage(in, trim, out);
    input in;
    input [1:0] trim;
    output out;

    wire d0, d1, d2, ts;

    sky130_fd_sc_hd__clkbuf_2 delaybuf0 (
	.A(in),
	.X(ts)
    );

    sky130_fd_sc_hd__clkbuf_1 delaybuf1 (
	.A(ts),
	.X(d0)
    );

    sky130_fd_sc_hd__einvp_2 delayen1 (
	.A(d0),
	.TE(trim[1]),
	.Z(d1)
    );

    sky130_fd_sc_hd__einvn_4 delayenb1 (
	.A(ts),
	.TE_B(trim[1]),
	.Z(d1)
    );

    sky130_fd_sc_hd__clkinv_1 delayint0 (
	.A(d1),
	.Y(d2)
    );

    sky130_fd_sc_hd__einvp_2 delayen0 (
	.A(d2),
	.TE(trim[0]),
	.Z(out)
    );

    sky130_fd_sc_hd__einvn_8 delayenb0 (
	.A(ts),
	.TE_B(trim[0]),
	.Z(out)
    );

endmodule
module start_stage(in, trim, reset, out);
    input in;
    input [1:0] trim;
    input reset;
    output out;

    wire d0, d1, d2, ctrl0, one;

    sky130_fd_sc_hd__clkbuf_1 delaybuf0 (
	.A(in),
	.X(d0)
    );

    sky130_fd_sc_hd__einvp_2 delayen1 (
	.A(d0),
	.TE(trim[1]),
	.Z(d1)
    );

    sky130_fd_sc_hd__einvn_4 delayenb1 (
	.A(in),
	.TE_B(trim[1]),
	.Z(d1)
    );

    sky130_fd_sc_hd__clkinv_1 delayint0 (
	.A(d1),
	.Y(d2)
    );

    sky130_fd_sc_hd__einvp_2 delayen0 (
	.A(d2),
	.TE(trim[0]),
	.Z(out)
    );

    sky130_fd_sc_hd__einvn_8 delayenb0 (
	.A(in),
	.TE_B(ctrl0),
	.Z(out)
    );

    sky130_fd_sc_hd__einvp_1 reseten0 (
	.A(one),
	.TE(reset),
	.Z(out)
    );

    sky130_fd_sc_hd__or2_2 ctrlen0 (
	.A(reset),
	.B(trim[0]),
	.X(ctrl0)
    );

    sky130_fd_sc_hd__conb_1 const1 (
	.HI(one),
	.LO()
    );

endmodule
module ring_osc2x13(reset, trim, clockp);
    input reset;
    input [25:0] trim;
    output[1:0] clockp;

`ifdef FUNCTIONAL	// i.e., behavioral model below

    reg [1:0] clockp;
    reg hiclock;
    integer i;
    real delay;
    wire [5:0] bcount;

    assign bcount = trim[0] + trim[1] + trim[2]
		+ trim[3] + trim[4] + trim[5] + trim[6] + trim[7]
		+ trim[8] + trim[9] + trim[10] + trim[11] + trim[12]
		+ trim[13] + trim[14] + trim[15] + trim[16] + trim[17]
		+ trim[18] + trim[19] + trim[20] + trim[21] + trim[22]
		+ trim[23] + trim[24] + trim[25];

    initial begin
	hiclock <= 1'b0;
	delay = 3.0;
    end

    // Fastest operation is 214 MHz = 4.67ns
    // Delay per trim is 0.02385
    // Run "hiclock" at 2x this rate, then use positive and negative
    // edges to derive the 0 and 90 degree phase clocks.

    always #delay begin
	hiclock <= (hiclock === 1'b0);
    end

    always @(trim) begin
    	// Implement trim as a variable delay, one delay per trim bit
	delay = 1.168 + 0.012 * $itor(bcount);
    end

    always @(posedge hiclock or posedge reset) begin
	if (reset == 1'b1) begin
	    clockp[0] <= 1'b0;
	end else begin
	    clockp[0] <= (clockp[0] === 1'b0);
	end
    end

    always @(negedge hiclock or posedge reset) begin
	if (reset == 1'b1) begin
	    clockp[1] <= 1'b0;
	end else begin
	    clockp[1] <= (clockp[1] === 1'b0);
	end
    end

`else 			// !FUNCTIONAL;  i.e., gate level netlist below

    wire [1:0] clockp;
    wire [12:0] d;
    wire [1:0] c;

    // Main oscillator loop stages
 
    genvar i;
    generate
	for (i = 0; i < 12; i = i + 1) begin : dstage
	    delay_stage id (
		.in(d[i]),
		.trim({trim[i+13], trim[i]}),
		.out(d[i+1])
	    );
	end
    endgenerate

    // Reset/startup stage
 
    start_stage iss (
	.in(d[12]),
	.trim({trim[25], trim[12]}),
	.reset(reset),
	.out(d[0])
    );

    // Buffered outputs a 0 and 90 degrees phase (approximately)

    sky130_fd_sc_hd__clkinv_2 ibufp00 (
	.A(d[0]),
	.Y(c[0])
    );
    sky130_fd_sc_hd__clkinv_8 ibufp01 (
	.A(c[0]),
	.Y(clockp[0])
    );
    sky130_fd_sc_hd__clkinv_2 ibufp10 (
	.A(d[6]),
	.Y(c[1])
    );
    sky130_fd_sc_hd__clkinv_8 ibufp11 (
	.A(c[1]),
	.Y(clockp[1])
    );

`endif // !FUNCTIONAL

endmodule
module gpio_wb # (
    parameter BASE_ADR  = 32'h 2100_0000,
    parameter GPIO_DATA = 8'h 00,
    parameter GPIO_ENA  = 8'h 04,
    parameter GPIO_PU   = 8'h 08,
    parameter GPIO_PD   = 8'h 0c
) (
    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  gpio_in_pad,
    output gpio,
    output gpio_oeb,
    output gpio_pu,
    output gpio_pd
);

    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;

    gpio #(
        .BASE_ADR(BASE_ADR),
        .GPIO_DATA(GPIO_DATA),
        .GPIO_ENA(GPIO_ENA),
        .GPIO_PD(GPIO_PD),
        .GPIO_PU(GPIO_PU)
    ) gpio_ctrl (
        .clk(wb_clk_i),
        .resetn(resetn),

        .gpio_in_pad(gpio_in_pad),

        .iomem_addr(wb_adr_i),
        .iomem_valid(valid),
        .iomem_wstrb(iomem_we[0]),
        .iomem_wdata(wb_dat_i),
        .iomem_rdata(wb_dat_o),
        .iomem_ready(ready),

        .gpio(gpio),
        .gpio_oeb(gpio_oeb),
        .gpio_pu(gpio_pu),
        .gpio_pd(gpio_pd)
    );
    
endmodule
module gpio #(
    parameter BASE_ADR  = 32'h 2100_0000,
    parameter GPIO_DATA = 8'h 00,
    parameter GPIO_ENA  = 8'h 04,
    parameter GPIO_PU   = 8'h 08,
    parameter GPIO_PD   = 8'h 0c
) (
    input clk,
    input resetn,

    input gpio_in_pad,

    input [31:0] iomem_addr,
    input iomem_valid,
    input iomem_wstrb,
    input [31:0] iomem_wdata,
    output reg [31:0] iomem_rdata,
    output reg iomem_ready,

    output gpio,
    output gpio_oeb,
    output gpio_pu,
    output gpio_pd
);

    reg gpio;		// GPIO output data
    reg gpio_pu;		// GPIO pull-up enable
    reg gpio_pd;		// GPIO pull-down enable
    reg gpio_oeb;    // GPIO output enable (sense negative)
    
    wire gpio_sel;
    wire gpio_oeb_sel;
    wire gpio_pu_sel;  
    wire gpio_pd_sel;

    assign gpio_sel     = (iomem_addr[7:0] == GPIO_DATA);
    assign gpio_oeb_sel = (iomem_addr[7:0] == GPIO_ENA);
    assign gpio_pu_sel  = (iomem_addr[7:0] == GPIO_PU);
    assign gpio_pd_sel  = (iomem_addr[7:0] == GPIO_PD);

    always @(posedge clk) begin
        if (!resetn) begin
            gpio <= 0;
            gpio_oeb <= 16'hffff;
            gpio_pu <= 0;
            gpio_pd <= 0;
        end else begin
            iomem_ready <= 0;
            if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin
                iomem_ready <= 1'b 1;
                
                if (gpio_sel) begin
                    iomem_rdata <= {30'd0, gpio, gpio_in_pad};
                    if (iomem_wstrb) gpio <= iomem_wdata[0];

                end else if (gpio_oeb_sel) begin
                    iomem_rdata <= {31'd0, gpio_oeb};
                    if (iomem_wstrb) gpio_oeb <= iomem_wdata[0];

                end else if (gpio_pu_sel) begin
                    iomem_rdata <= {31'd0, gpio_pu};
                    if (iomem_wstrb) gpio_pu <= iomem_wdata[0];

                end else if (gpio_pd_sel) begin
                    iomem_rdata <= {31'd0, gpio_pd};          
                    if (iomem_wstrb) gpio_pd <= iomem_wdata[0];

                end

            end
        end
    end

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;
    tran(vssa2, vssa1);
    tran(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 mprj2_logic_high (
`ifdef USE_POWER_PINS
    inout	   vccd2,
    inout	   vssd2,
`endif
    output         HI
);
sky130_fd_sc_hd__conb_1 inst (
`ifdef USE_POWER_PINS
                .VPWR(vccd2),
                .VGND(vssd2),
                .VPB(vccd2),
                .VNB(vssd2),
`endif
                .HI(HI),
                .LO()
        );
endmodule
module counter_timer_high_wb # (
    parameter BASE_ADR = 32'h2400_0000,
    parameter CONFIG = 8'h00,
    parameter VALUE  = 8'h04,
    parameter DATA   = 8'h08
) (
    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,
    input enable_in,
    input stop_in,
    input strobe,
    input is_offset,
    output stop_out,
    output enable_out,
    output irq
);
    wire [31:0] counter_timer_reg_cfg_do;
    wire [31:0] counter_timer_reg_val_do;
    wire [31:0] counter_timer_reg_dat_do;

    wire resetn = ~wb_rst_i;
    wire valid = wb_stb_i && wb_cyc_i;
    wire counter_timer_reg_cfg_sel = valid && (wb_adr_i == (BASE_ADR | CONFIG));
    wire counter_timer_reg_val_sel = valid && (wb_adr_i == (BASE_ADR | VALUE));
    wire counter_timer_reg_dat_sel = valid && (wb_adr_i == (BASE_ADR | DATA));

    wire reg_cfg_we = (counter_timer_reg_cfg_sel) ?
		(wb_sel_i[0] & {wb_we_i}): 1'b0;
    wire [3:0] reg_val_we = (counter_timer_reg_val_sel) ?
		(wb_sel_i & {4{wb_we_i}}): 4'b0000;
    wire [3:0] reg_dat_we = (counter_timer_reg_dat_sel) ?
		(wb_sel_i & {4{wb_we_i}}): 4'b0000;

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

    assign wb_dat_o = (counter_timer_reg_cfg_sel) ? counter_timer_reg_cfg_do :
		      (counter_timer_reg_val_sel) ? counter_timer_reg_val_do :
		      counter_timer_reg_dat_do;
    assign wb_ack_o = counter_timer_reg_cfg_sel || counter_timer_reg_val_sel ||
			counter_timer_reg_dat_sel;
    
    counter_timer_high counter_timer_high_inst (
        .resetn(resetn),
        .clkin(wb_clk_i),
        .reg_val_we(reg_val_we),
        .reg_val_di(mem_wdata),
        .reg_val_do(counter_timer_reg_val_do),
        .reg_cfg_we(reg_cfg_we),
        .reg_cfg_di(mem_wdata),
        .reg_cfg_do(counter_timer_reg_cfg_do),
        .reg_dat_we(reg_dat_we),
        .reg_dat_di(mem_wdata),
        .reg_dat_do(counter_timer_reg_dat_do),
	.enable_in(enable_in),
	.stop_in(stop_in),
	.is_offset(is_offset),
	.stop_out(stop_out),
	.strobe(strobe),
	.enable_out(enable_out),
	.irq_out(irq)
   );

endmodule
module user_id_programming #(
    parameter [ 0:0] USER_PROJECT_ID = 32'h0
) (
`ifdef USE_POWER_PINS
    inout VPWR,
    inout VGND,
`endif
    output [31:0] mask_rev
);
    wire [31:0] mask_rev;
    wire [31:0] user_proj_id_high;
    wire [31:0] user_proj_id_low;

    // For the mask revision input, use an array of digital constant logic cells

    sky130_fd_sc_hd__conb_1 mask_rev_value [31:0] (
`ifdef USE_POWER_PINS
            .VPWR(VPWR),
            .VPB(VPWR),
            .VNB(VGND),
            .VGND(VGND),
`endif
            .HI(user_proj_id_high),
            .LO(user_proj_id_low)
    );

    genvar i;
    generate
	for (i = 0; i < 32; i = i+1) begin
	    assign mask_rev[i] = (USER_PROJECT_ID & (32'h01 << i)) ?
			user_proj_id_high[i] : user_proj_id_low[i];
	end
    endgenerate

endmodule
module convert_gpio_sigs (
    input        gpio_out,
    input        gpio_outenb,
    input        gpio_pu,
    input        gpio_pd,
    output       gpio_out_pad,
    output       gpio_outenb_pad,
    output       gpio_inenb_pad,
    output       gpio_mode1_pad,
    output       gpio_mode0_pad
);

    assign gpio_out_pad = (gpio_pu == 1'b0 && gpio_pd == 1'b0) ? gpio_out :
            (gpio_pu == 1'b1) ? 1 : 0;

    assign gpio_outenb_pad = (gpio_outenb == 1'b0) ? 0 :
            (gpio_pu == 1'b1 || gpio_pd == 1'b1) ? 0 : 1;

    assign gpio_inenb_pad = ~gpio_outenb;

    assign gpio_mode1_pad = ~gpio_outenb_pad;
    assign gpio_mode0_pad = gpio_outenb;

endmodule
module wb_intercon #(
    parameter DW = 32,          // Data Width
    parameter AW = 32,          // Address Width
    parameter NS = 6,           // Number of Slaves
    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
    }
) (
    // 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
);

    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 [458:0] HI
);
sky130_fd_sc_hd__conb_1 insts [458:0] (
`ifdef USE_POWER_PINS
                .VPWR(vccd1),
                .VGND(vssd1),
                .VPB(vccd1),
                .VNB(vssd1),
`endif
                .HI(HI),
                .LO()
        );
endmodule
module counter_timer_low_wb # (
    parameter BASE_ADR = 32'h2400_0000,
    parameter CONFIG = 8'h00,
    parameter VALUE  = 8'h04,
    parameter DATA   = 8'h08
) (
    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,

    input stop_in,
    input enable_in,
    output strobe,
    output is_offset,
    output stop_out,
    output enable_out,
    output irq
);
    wire [31:0] counter_timer_reg_cfg_do;
    wire [31:0] counter_timer_reg_val_do;
    wire [31:0] counter_timer_reg_dat_do;

    wire resetn = ~wb_rst_i;
    wire valid = wb_stb_i && wb_cyc_i;
    wire counter_timer_reg_cfg_sel = valid && (wb_adr_i == (BASE_ADR | CONFIG));
    wire counter_timer_reg_val_sel = valid && (wb_adr_i == (BASE_ADR | VALUE));
    wire counter_timer_reg_dat_sel = valid && (wb_adr_i == (BASE_ADR | DATA));

    wire reg_cfg_we = (counter_timer_reg_cfg_sel) ?
		(wb_sel_i[0] & {wb_we_i}): 1'b0;
    wire [3:0] reg_val_we = (counter_timer_reg_val_sel) ?
		(wb_sel_i & {4{wb_we_i}}): 4'b0000;
    wire [3:0] reg_dat_we = (counter_timer_reg_dat_sel) ?
		(wb_sel_i & {4{wb_we_i}}): 4'b0000;

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

    assign wb_dat_o = (counter_timer_reg_cfg_sel) ? counter_timer_reg_cfg_do :
		      (counter_timer_reg_val_sel) ? counter_timer_reg_val_do :
		      counter_timer_reg_dat_do;
    assign wb_ack_o = counter_timer_reg_cfg_sel || counter_timer_reg_val_sel ||
			counter_timer_reg_dat_sel;
    
    counter_timer_low counter_timer_low_inst (
        .resetn(resetn),
        .clkin(wb_clk_i),
        .reg_val_we(reg_val_we),
        .reg_val_di(mem_wdata),
        .reg_val_do(counter_timer_reg_val_do),
        .reg_cfg_we(reg_cfg_we),
        .reg_cfg_di(mem_wdata),
        .reg_cfg_do(counter_timer_reg_cfg_do),
        .reg_dat_we(reg_dat_we),
        .reg_dat_di(mem_wdata),
        .reg_dat_do(counter_timer_reg_dat_do),
	.stop_in(stop_in),
	.strobe(strobe),
	.is_offset(is_offset),
	.enable_in(enable_in),
	.stop_out(stop_out),
	.enable_out(enable_out),
	.irq_out(irq)
   );

endmodule
module simpleuart_wb # (
    parameter BASE_ADR = 32'h 2000_0000,
    parameter CLK_DIV = 8'h00,
    parameter DATA = 8'h04,
    parameter CONFIG = 8'h08
) (
    input wb_clk_i,
    input wb_rst_i,

    input [31:0] wb_adr_i,      // (verify): input address was originaly 22 bits , why ? (max number of words ?)
    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 uart_enabled,
    output ser_tx,
    input  ser_rx

);
    wire [31:0] simpleuart_reg_div_do;
    wire [31:0] simpleuart_reg_dat_do;
    wire [31:0] simpleuart_reg_cfg_do;
    wire reg_dat_wait;

    wire resetn = ~wb_rst_i;
    wire valid = wb_stb_i && wb_cyc_i; 
    wire simpleuart_reg_div_sel = valid && (wb_adr_i == (BASE_ADR | CLK_DIV));
    wire simpleuart_reg_dat_sel = valid && (wb_adr_i == (BASE_ADR | DATA));
    wire simpleuart_reg_cfg_sel = valid && (wb_adr_i == (BASE_ADR | CONFIG));

    wire [3:0] reg_div_we = simpleuart_reg_div_sel ? (wb_sel_i & {4{wb_we_i}}): 4'b 0000; 
    wire reg_dat_we = simpleuart_reg_dat_sel ? (wb_sel_i[0] & wb_we_i): 1'b 0;      // simpleuart_reg_dat_sel ? mem_wstrb[0] : 1'b 0
    wire reg_cfg_we = simpleuart_reg_cfg_sel ? (wb_sel_i[0] & wb_we_i): 1'b 0; 

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

    assign wb_dat_o = simpleuart_reg_div_sel ? simpleuart_reg_div_do:
		      simpleuart_reg_cfg_sel ? simpleuart_reg_cfg_do:
					       simpleuart_reg_dat_do;
    assign wb_ack_o = (simpleuart_reg_div_sel || simpleuart_reg_dat_sel
			|| simpleuart_reg_cfg_sel) && (!reg_dat_wait);
    
    simpleuart simpleuart (
        .clk    (wb_clk_i),
        .resetn (resetn),

        .ser_tx      (ser_tx),
        .ser_rx      (ser_rx),
	.enabled     (uart_enabled),

        .reg_div_we  (reg_div_we), 
        .reg_div_di  (mem_wdata),
        .reg_div_do  (simpleuart_reg_div_do),

        .reg_cfg_we  (reg_cfg_we), 
        .reg_cfg_di  (mem_wdata),
        .reg_cfg_do  (simpleuart_reg_cfg_do),

        .reg_dat_we  (reg_dat_we),
        .reg_dat_re  (reg_dat_re),
        .reg_dat_di  (mem_wdata),
        .reg_dat_do  (simpleuart_reg_dat_do),
        .reg_dat_wait(reg_dat_wait)
    );

endmodule
module caravel_clocking(
`ifdef USE_POWER_PINS
    input vdd1v8,
    input vss,
`endif
    input resetb, 	// Master (negative sense) reset
    input ext_clk_sel,	// 0=use PLL clock, 1=use external (pad) clock
    input ext_clk,	// External pad (slow) clock
    input pll_clk,	// Internal PLL (fast) clock
    input pll_clk90,	// Internal PLL (fast) clock, 90 degree phase
    input [2:0] sel,	// Select clock divider value (0=thru, 1=divide-by-2, etc.)
    input [2:0] sel2,	// Select clock divider value for 90 degree phase divided clock
    input ext_reset,	// Positive sense reset from housekeeping SPI.
    output core_clk,	// Output core clock
    output user_clk,	// Output user (secondary) clock
    output resetb_sync	// Output propagated and buffered reset
);

    wire pll_clk_sel;
    wire pll_clk_divided;
    wire pll_clk90_divided;
    wire core_ext_clk;
    reg  use_pll_first;
    reg  use_pll_second;
    reg	 ext_clk_syncd_pre;
    reg	 ext_clk_syncd;

    assign pll_clk_sel = ~ext_clk_sel;

    // Note that this implementation does not guard against switching to
    // the PLL clock if the PLL clock is not present.

    always @(posedge pll_clk or negedge resetb) begin
	if (resetb == 1'b0) begin
	    use_pll_first <= 1'b0;
	    use_pll_second <= 1'b0;
	    ext_clk_syncd <= 1'b0;
	end else begin
	    use_pll_first <= pll_clk_sel;
	    use_pll_second <= use_pll_first;
	    ext_clk_syncd_pre <= ext_clk;	// Sync ext_clk to pll_clk
	    ext_clk_syncd <= ext_clk_syncd_pre;	// Do this twice (resolve metastability)
	end
    end

    // Apply PLL clock divider

    clock_div #(
	.SIZE(3)
    ) divider (
	.in(pll_clk),
	.out(pll_clk_divided),
	.N(sel),
	.resetb(resetb)
    ); 

    // Secondary PLL clock divider for user space access

    clock_div #(
	.SIZE(3)
    ) divider2 (
	.in(pll_clk90),
	.out(pll_clk90_divided),
	.N(sel2),
	.resetb(resetb)
    ); 


    // Multiplex the clock output

    assign core_ext_clk = (use_pll_first) ? ext_clk_syncd : ext_clk;
    assign core_clk = (use_pll_second) ? pll_clk_divided : core_ext_clk;
    assign user_clk = (use_pll_second) ? pll_clk90_divided : core_ext_clk;

    // Reset assignment.  "reset" comes from POR, while "ext_reset"
    // comes from standalone SPI (and is normally zero unless
    // activated from the SPI).

    // Staged-delay reset
    reg [2:0] reset_delay;

    always @(posedge core_clk or negedge resetb) begin
        if (resetb == 1'b0) begin
        reset_delay <= 3'b111;
        end else begin
        reset_delay <= {1'b0, reset_delay[2:1]};
        end
    end

    assign resetb_sync = ~(reset_delay[0] | ext_reset);

endmodule
module digital_pll(
`ifdef USE_POWER_PINS
    VPWR,
    VGND,
`endif
    resetb, enable, osc, clockp, div, dco, ext_trim);

`ifdef USE_POWER_PINS
    input VPWR;
    input VGND;
`endif

    input	 resetb;	// Sense negative reset
    input	 enable;	// Enable PLL
    input	 osc;		// Input oscillator to match
    input [4:0]	 div;		// PLL feedback division ratio
    input 	 dco;		// Run in DCO mode
    input [25:0] ext_trim;	// External trim for DCO mode

    output [1:0] clockp;	// Two 90 degree clock phases

    wire [25:0]  itrim;		// Internally generated trim bits
    wire [25:0]  otrim;		// Trim bits applied to the ring oscillator
    wire	 creset;	// Controller reset
    wire	 ireset;	// Internal reset (external reset OR disable)

    assign ireset = ~resetb | ~enable;

    // In DCO mode: Hold controller in reset and apply external trim value

    assign itrim = (dco == 1'b0) ? otrim : ext_trim;
    assign creset = (dco == 1'b0) ? ireset : 1'b1;

    ring_osc2x13 ringosc (
        .reset(ireset),
        .trim(itrim),
        .clockp(clockp)
    );

    digital_pll_controller pll_control (
        .reset(creset),
        .clock(clockp[0]),
        .osc(osc),
        .div(div),
        .trim(otrim)
    );

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,

    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;

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

	.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 DFFRAM(
`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 COLS=1)
(
`ifdef USE_POWER_PINS
    VPWR,
    VGND,
`endif
    CLK,
    WE,
    EN,
    Di,
    Do,
    A
);

    input           CLK;
    input   [3:0]   WE;
    input           EN;
    input   [31:0]  Di;
    output  [31:0]  Do;
    input   [7+$clog2(COLS):0]   A;

`ifdef USE_POWER_PINS
    input VPWR;
    input VGND;
`endif

    wire [31:0]     DOUT [COLS-1:0];
    wire [31:0]     Do_pre;
    wire [COLS-1:0] EN_lines;

    generate
        genvar i;
        for (i=0; i<COLS; i=i+1) begin : COLUMN
            DFFRAM_COL4 RAMCOLS (
                                `ifdef USE_POWER_PINS
                                    .VPWR(VPWR),
                                    .VGND(VGND),
                                `endif
                                    .CLK(CLK), 
                                    .WE(WE), 
                                    .EN(EN_lines[i]), 
                                    .Di(Di), 
                                    .Do(DOUT[i]), 
                                    .A(A[7:0]) 
                                );    
        end
        if(COLS==4) begin
            MUX4x1_32 MUX ( 
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
            `endif
                .A0(DOUT[0]),
                .A1(DOUT[1]),
                .A2(DOUT[2]),
                .A3(DOUT[3]),
                .S(A[9:8]),
                .X(Do_pre)
            );
            DEC2x4 DEC (
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
            `endif 
                .EN(EN),
                .A(A[9:8]),
                .SEL(EN_lines)
            );
        end
        else if(COLS==2) begin
            MUX2x1_32 MUX ( 
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
            `endif 
                .A0(DOUT[0]),
                .A1(DOUT[1]),
                .S(A[8]),
                .X(Do_pre)
            );
            //sky130_fd_sc_hd__inv_4 DEC0 ( .Y(EN_lines[0]), .A(A[8]) );
            //sky130_fd_sc_hd__clkbuf_4 DEC1 (.X(EN_lines[1]), .A(A[8]) );
            DEC1x2 DEC ( 
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
            `endif 
                .EN(EN),
                .A(A[8]),
                .SEL(EN_lines[1:0]) 
            );
            
        end
        else begin
            PASS MUX ( 
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
            `endif 
                .A(DOUT[0]),
                .X(Do_pre)
            );
            sky130_fd_sc_hd__clkbuf_4 ENBUF (
           `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
                .VPB(VPWR),
                .VNB(VGND),
            `endif 
                .X(EN_lines[0]),
                .A(EN)
            );
        end
    endgenerate
    
    sky130_fd_sc_hd__clkbuf_4 DOBUF[31:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif 
        .X(Do),
        .A(Do_pre)
    );

endmodule
module sysctrl_wb #(
    parameter BASE_ADR     = 32'h2F00_0000,
    parameter PWRGOOD	   = 8'h00,
    parameter CLK_OUT      = 8'h04,
    parameter TRAP_OUT     = 8'h08,
    parameter IRQ_SRC      = 8'h0c
) (
    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  usr1_vcc_pwrgood,
    input  usr2_vcc_pwrgood,
    input  usr1_vdd_pwrgood,
    input  usr2_vdd_pwrgood,
    output clk1_output_dest,
    output clk2_output_dest,
    output trap_output_dest,
    output irq_7_inputsrc,
    output irq_8_inputsrc

);

    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;
    
    sysctrl #(
        .BASE_ADR(BASE_ADR),
        .PWRGOOD(PWRGOOD),
        .CLK_OUT(CLK_OUT),
        .TRAP_OUT(TRAP_OUT),
        .IRQ_SRC(IRQ_SRC)
    ) sysctrl (
        .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),
        
	.usr1_vcc_pwrgood(usr1_vcc_pwrgood),
	.usr2_vcc_pwrgood(usr2_vcc_pwrgood),
	.usr1_vdd_pwrgood(usr1_vdd_pwrgood),
	.usr2_vdd_pwrgood(usr2_vdd_pwrgood),
        .clk1_output_dest(clk1_output_dest),
        .clk2_output_dest(clk2_output_dest),
        .trap_output_dest(trap_output_dest), 
        .irq_8_inputsrc(irq_8_inputsrc),
        .irq_7_inputsrc(irq_7_inputsrc)
    );

endmodule
module sysctrl #(
    parameter BASE_ADR = 32'h2300_0000,
    parameter PWRGOOD	   = 8'h00,
    parameter CLK_OUT      = 8'h04,
    parameter TRAP_OUT     = 8'h08,
    parameter IRQ_SRC      = 8'h0c
) (
    input clk,
    input resetn,
    
    input [31:0] iomem_addr,
    input iomem_valid,
    input [3:0] iomem_wstrb,
    input [31:0] iomem_wdata,
    output reg [31:0] iomem_rdata,
    output reg iomem_ready,

    input  usr1_vcc_pwrgood,
    input  usr2_vcc_pwrgood,
    input  usr1_vdd_pwrgood,
    input  usr2_vdd_pwrgood,
    output clk1_output_dest,
    output clk2_output_dest,
    output trap_output_dest,
    output irq_7_inputsrc,
    output irq_8_inputsrc
); 

    reg clk1_output_dest;
    reg clk2_output_dest;
    reg trap_output_dest;
    reg irq_7_inputsrc;
    reg irq_8_inputsrc;

    wire usr1_vcc_pwrgood;
    wire usr2_vcc_pwrgood;
    wire usr1_vdd_pwrgood;
    wire usr2_vdd_pwrgood;

    wire pwrgood_sel;
    wire clk_out_sel;
    wire trap_out_sel;
    wire irq_sel;

    assign pwrgood_sel  = (iomem_addr[7:0] == PWRGOOD);
    assign clk_out_sel  = (iomem_addr[7:0] == CLK_OUT);
    assign trap_out_sel = (iomem_addr[7:0] == TRAP_OUT);
    assign irq_sel  = (iomem_addr[7:0] == IRQ_SRC);

    always @(posedge clk) begin
        if (!resetn) begin
            clk1_output_dest <= 0;
            clk2_output_dest <= 0;
            trap_output_dest <= 0;
            irq_7_inputsrc <= 0;
            irq_8_inputsrc <= 0;
        end else begin
            iomem_ready <= 0;
            if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin
                iomem_ready <= 1'b 1;
                
                if (pwrgood_sel) begin
                    iomem_rdata <= {28'd0, usr2_vdd_pwrgood, usr1_vdd_pwrgood,
				usr2_vcc_pwrgood, usr1_vcc_pwrgood};
		    // These are read-only bits;  no write behavior on wstrb.

                end else if (clk_out_sel) begin
                    iomem_rdata <= {30'd0, clk2_output_dest, clk1_output_dest};
                    if (iomem_wstrb[0]) begin
                        clk1_output_dest <= iomem_wdata[0];
                        clk2_output_dest <= iomem_wdata[1];
		    end

                end else if (trap_out_sel) begin
                    iomem_rdata <= {31'd0, trap_output_dest};
                    if (iomem_wstrb[0]) 
                        trap_output_dest <= iomem_wdata[0];

                end else if (irq_sel) begin
                    iomem_rdata <= {30'd0, irq_8_inputsrc, irq_7_inputsrc};
                    if (iomem_wstrb[0]) begin
                        irq_7_inputsrc <= iomem_wdata[0];
                        irq_8_inputsrc <= iomem_wdata[1];
		    end
                end
            end
        end
    end

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
    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
    	.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_ENA_0 = 8'h10,
    parameter LA_ENA_1 = 8'h14,
    parameter LA_ENA_2 = 8'h18,
    parameter LA_ENA_3 = 8'h1c
) (
    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_oen
);

    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_ENA_0(LA_ENA_0),
        .LA_ENA_1(LA_ENA_1),
        .LA_ENA_2(LA_ENA_2),
        .LA_ENA_3(LA_ENA_3)
    ) 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_oen(la_oen)
    );
    
endmodule