AUCOHL / DFFRAM

Standard Cell Library based Memory Compiler using FF/Latch cells
Apache License 2.0
134 stars 33 forks source link

128x64 3R1W Register File for Microwatt #108

Open antonblanchard opened 3 years ago

antonblanchard commented 3 years ago

A few months ago I built a handcrafted 128x64 3R1W DFFRAM based register file for Microwatt. Coming back to the project now, I see a lot of work on the compiler, which is great.

Has there been any work on alternate register file formats with the compiler, or is it just 32x32 2R1W at the moment?

donn commented 3 years ago

For register files unfortunately just that one, so far, but if you'd be willing to give us the files I can maybe work something out

shalan commented 3 years ago

@antonblanchard We can generate the register file. Probably, it will take a week or so before we have it ready.

antonblanchard commented 3 years ago

@donn @shalan Thank you! FYI this is what I came up with many months ago, interested in your thoughts. In reality we only require 80 registers (32 GPR + 32 FPR + 16 SPR), so I made it 80x64.

I also struggled with capacitance issues with the tristate buffers, so created two levels (I wasn't sure how far we could push capacitance violations before they become an issue).

/*
 * Microwatt FP DFFRFile
 *
 * 80x64bit register file (32 GPRs, 32 FPRs, 16 SPRs) with 3R and 1W ports and clock gating for SKY130A
 *
 * Author: Anton Blanchard <anton@linux.ibm.com>
 *
 * Based on DFFRFILE:
 * Author: Mohamed Shalan <mshalan@aucegypt.edu>
 */

`timescale 1ns / 1ps
`default_nettype none

module Microwatt_FP_DFFRFile (
`ifdef USE_POWER_PINS
    input VPWR,
    input VGND,
`endif
    input [6:0]   R1, R2, R3, RW,
    input [63:0]  DW,
    output [63:0] D1, D2, D3,
    input CLK,
    input WE
);

    wire [80-1:0] sel1, sel2, sel3, selw;

    DEC7x80 DEC0 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .A(R1),
        .SEL(sel1)
    );

    DEC7x80 DEC1 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .A(R2),
        .SEL(sel2)
    );

    DEC7x80 DEC2 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .A(R3),
        .SEL(sel3)
    );

    DEC7x80 DEC3 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .A(RW),
        .SEL(selw)
    );

    // Avoid capacitance violations on the tristate buffer outputs by creating
    // groups of 16, and using a second level of tristate buffers to select
    // them.

    wire [63:0] D1_tmp [4:0];
    wire [63:0] D2_tmp [4:0];
    wire [63:0] D3_tmp [4:0];

    generate
        genvar e;
        for (e=0; e<80; e=e+1)
            RFWORD RFW (
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
            `endif
                .CLK(CLK),
                .WE(WE),
                .SEL1(sel1[e]),
                .SEL2(sel2[e]),
                .SEL3(sel3[e]),
                .SELW(selw[e]),
                .D1(D1_tmp[e/16]),
                .D2(D2_tmp[e/16]),
                .D3(D3_tmp[e/16]),
                .DW(DW)
            );
    endgenerate

    wire HI;

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

    // Only using 5 bits of this
    wire [7:0] sel1_b;
    wire [7:0] sel2_b;
    wire [7:0] sel3_b;

    DEC3x8 SEL1_B (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .EN(HI),
        .A(R1[6:4]),
        .SEL(sel1_b)
    );

    DEC3x8 SEL2_B (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .EN(HI),
        .A(R2[6:4]),
        .SEL(sel2_b)
    );

    DEC3x8 SEL3_B (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .EN(HI),
        .A(R3[6:4]),
        .SEL(sel3_b)
    );

    wire [4:0] sel1_b_n;
    wire [4:0] sel2_b_n;
    wire [4:0] sel3_b_n;

    sky130_fd_sc_hd__inv_8 SEL1_B_INV[4:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(sel1_b[4:0]),
        .Y(sel1_b_n)
    );

    sky130_fd_sc_hd__inv_8 SEL2_B_INV[4:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(sel2_b[4:0]),
        .Y(sel2_b_n)
    );

    sky130_fd_sc_hd__inv_8 SEL3_B_INV[4:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(sel3_b[4:0]),
        .Y(sel3_b_n)
    );

    generate
        for (e=0; e<5; e=e+1)
        begin
            sky130_fd_sc_hd__ebufn_8 OBUFR1_2 [63:0] (
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
                .VPB(VPWR),
                .VNB(VGND),
            `endif
                .TE_B(sel1_b_n[e]),
                .A(D1_tmp[e]),
                .Z(D1)
            );
            sky130_fd_sc_hd__ebufn_8 OBUFR2_2 [63:0] (
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
                .VPB(VPWR),
                .VNB(VGND),
            `endif
                .TE_B(sel2_b_n[e]),
                .A(D2_tmp[e]),
                .Z(D2)
            );
            sky130_fd_sc_hd__ebufn_8 OBUFR3_2 [63:0] (
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
                .VPB(VPWR),
                .VNB(VGND),
            `endif
                .TE_B(sel3_b_n[e]),
                .A(D3_tmp[e]),
                .Z(D3)
            );
        end

    endgenerate

endmodule

module RFWORD (
`ifdef USE_POWER_PINS
    input VPWR,
    input VGND,
`endif
    input CLK,
    input WE,
    input SEL1, SEL2, SEL3, SELW,
    output [63:0] D1, D2, D3,
    input [63:0] DW
);

    wire [63:0] q_wire;
    wire we_wire;
    wire [7:0] SEL1_B, SEL2_B, SEL3_B;
    wire [7:0] GCLK;

    sky130_fd_sc_hd__inv_8 INV1[7:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(SEL1),
        .Y(SEL1_B)
    );

    sky130_fd_sc_hd__inv_8 INV2[7:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(SEL2),
        .Y(SEL2_B)
    );

    sky130_fd_sc_hd__inv_8 INV3[7:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(SEL3),
        .Y(SEL3_B)
    );

    sky130_fd_sc_hd__and2_1 CGAND (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(SELW),
        .B(WE),
        .X(we_wire)
    );

    sky130_fd_sc_hd__dlclkp_1 CG[7:0] (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .CLK(CLK),
        .GATE(we_wire),
        .GCLK(GCLK)
    );

    generate
        genvar i;
        for (i=0; i<64; i=i+1) begin : BIT
            sky130_fd_sc_hd__dfxtp_1 FF (
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
                .VPB(VPWR),
                .VNB(VGND),
            `endif
                .CLK(GCLK[i/8]),
                .D(DW[i]),
                .Q(q_wire[i])
            );

            sky130_fd_sc_hd__ebufn_8 OBUF1 (
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
                .VPB(VPWR),
                .VNB(VGND),
            `endif
                .TE_B(SEL1_B[i/8]),
                .A(q_wire[i]),
                .Z(D1[i])
            );

            sky130_fd_sc_hd__ebufn_8 OBUF2 (
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
                .VPB(VPWR),
                .VNB(VGND),
            `endif
                .TE_B(SEL2_B[i/8]),
                .A(q_wire[i]),
                .Z(D2[i])
            );

            sky130_fd_sc_hd__ebufn_8 OBUF3 (
            `ifdef USE_POWER_PINS
                .VPWR(VPWR),
                .VGND(VGND),
                .VPB(VPWR),
                .VNB(VGND),
            `endif
                .TE_B(SEL3_B[i/8]),
                .A(q_wire[i]),
                .Z(D3[i])
            );
        end
    endgenerate
endmodule

module DEC3x8 (
`ifdef USE_POWER_PINS
    input VPWR,
    input VGND,
`endif
    input        EN,
    input [2:0]  A,
    output [7:0] SEL
);

    wire [2:0]  A_buf;
    wire        EN_buf;

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

    sky130_fd_sc_hd__clkbuf_1 ENBUF (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(EN_buf),
        .A(EN)
    );

    sky130_fd_sc_hd__nor4b_1   AND0 ( // 000
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .Y(SEL[0]),
        .A(A_buf[0]),
        .B(A_buf[1]),
        .C(A_buf[2]),
        .D_N(EN_buf)
    );

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

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

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

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

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

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

    sky130_fd_sc_hd__and4_1     AND7 ( // 111
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .X(SEL[7]),
        .A(A_buf[0]),
        .B(A_buf[1]),
        .C(A_buf[2]),
        .D(EN_buf)
    );
endmodule

module DEC4x10(
`ifdef USE_POWER_PINS
    input VPWR,
    input VGND,
`endif
    input EN,
    input [3:0] A,
    output [9:0] SEL
);

    wire _00_;
    wire _01_;
    wire _02_;
    wire _03_;
    wire _04_;
    wire _05_;
    wire _06_;

    sky130_fd_sc_hd__or3b_1 comb0 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(A[2]),
        .B(A[3]),
        .C_N(EN),
        .X(_00_)
    );

    sky130_fd_sc_hd__nand2b_1 comb1 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A_N(A[1]),
        .B(A[0]),
        .Y(_01_)
    );

    sky130_fd_sc_hd__nand2b_1 comb2 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A_N(A[0]),
        .B(A[1]),
        .Y(_02_)
    );

    sky130_fd_sc_hd__nand2_1 comb3 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(A[0]),
        .B(A[1]),
        .Y(_03_)
    );

    sky130_fd_sc_hd__nand3b_1 comb4 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A_N(A[3]),
        .B(EN),
        .C(A[2]),
        .Y(_04_)
    );

    sky130_fd_sc_hd__nor3_1 comb5 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(A[0]),
        .B(A[1]),
        .C(A[2]),
        .Y(_05_)
    );

    sky130_fd_sc_hd__nand2_1 comb6 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(A[3]),
        .B(EN),
        .Y(_06_)
    );

    sky130_fd_sc_hd__nor3_1 sel0 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(A[0]),
        .B(A[1]),
        .C(_00_),
        .Y(SEL[0])
    );

    sky130_fd_sc_hd__nor2_1 sel1 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(_00_),
        .B(_01_),
        .Y(SEL[1])
    );

    sky130_fd_sc_hd__nor2_1 sel2 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(_00_),
        .B(_02_),
        .Y(SEL[2])
    );

    sky130_fd_sc_hd__nor2_1 sel3 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(_00_),
        .B(_03_),
        .Y(SEL[3])
    );

    sky130_fd_sc_hd__nor3_1 sel4 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(A[0]),
        .B(A[1]),
        .C(_04_),
        .Y(SEL[4])
    );

    sky130_fd_sc_hd__nor2_1 sel5 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(_01_),
        .B(_04_),
        .Y(SEL[5])
    );

    sky130_fd_sc_hd__nor2_1 sel6 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(_02_),
        .B(_04_),
        .Y(SEL[6])
    );

    sky130_fd_sc_hd__nor2_1 sel7 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(_03_),
        .B(_04_),
        .Y(SEL[7])
    );

    sky130_fd_sc_hd__and3_1 sel8 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(A[3]),
        .B(EN),
        .C(_05_),
        .X(SEL[8])
    );

    sky130_fd_sc_hd__nor2_1 sel9 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
    `endif
        .A(_05_),
        .B(_06_),
        .Y(SEL[9])
    );
endmodule

module DEC7x80 (
`ifdef USE_POWER_PINS
    input VPWR,
    input VGND,
`endif
    input   [6:0]    A,
    output  [80-1:0] SEL
);
    wire [9:0] SEL0_w ;
    wire [2:0] A_buf;
    wire HI;

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

    DEC4x10 DEC_L0 (
    `ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
    `endif
        .EN(HI),
        .A(A[6:3]),
        .SEL(SEL0_w)
    );

    sky130_fd_sc_hd__clkbuf_1 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<10; 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