add a 16x4 regfile to the project
diff --git a/info.yaml b/info.yaml index d15b271..9f4bf39 100644 --- a/info.yaml +++ b/info.yaml
@@ -3,8 +3,9 @@ project: wokwi_id: 0 # If using wokwi, set this to your project's ID source_files: # If using an HDL, set wokwi_id as 0 and uncomment and list your source files here + - verilog/rtl/regfile_top.v - verilog/rtl/xnor1.v - - verilog/rtl/top.v + - verilog/rtl/regfile16x4.v top_module: "rolfmobile99_top" # put the name of your top module here, make it unique by prepending your github username # As everyone will have access to all designs, try to make it easy for someone new to your design to know what @@ -16,8 +17,8 @@ documentation: author: "Rolf Widenfelt" # Your name discord: "" # Your discord handle - make sure to include the # part as well - title: "Collection of GF180 standard cells" # Project title - description: "" # Short description of what your project does + title: "16 x 4-bit dual port register file + XNOR" # Project title + description: "A dual port register file + XNOR test gate" # Short description of what your project does how_it_works: "" # Longer description of how the project works how_to_test: "" # Instructions on how someone could test your project, include things like what buttons do what and how to set the clock if needed external_hw: "" # Describe any external hardware needed @@ -28,19 +29,30 @@ inputs: # a description of what the inputs do - clock - reset - - xnor_a + - xnor_a # inputs for XNOR gate - xnor_b - - none - - none - - none - - none + - en1 # inputs for regfile + - en2 + - wrEn + - rdAddr1_3 + - rdAddr1_2 + - rdAddr1_1 + - rdAddr1_0 + - rdAddr2_3 + - rdAddr2_2 + - rdAddr2_1 + - rdAddr2_0 + - dataIn_3 + - dataIn_2 + - dataIn_1 + - dataIn_0 outputs: - - xnor_y # output of XNOR gate - - none - - none - - none - - none - - none - - none - - none - + - xnor_y # output for XNOR gate + - dataBusA_3 # outputs for regfile + - dataBusA_2 + - dataBusA_1 + - dataBusA_0 + - dataBusB_3 + - dataBusB_2 + - dataBusB_1 + - dataBusB_0
diff --git a/verilog/rtl/regfile16x4.v b/verilog/rtl/regfile16x4.v new file mode 100644 index 0000000..1a545f2 --- /dev/null +++ b/verilog/rtl/regfile16x4.v
@@ -0,0 +1,91 @@ +// +// regfile16x4.sv - 16 x 4-bit register file, single and dual port +// +// note: see below for dual read port version +// +// rev history: +// 12/4/2022 - based on LM3000 regfile.v +// +// inputs: +// rdAddr - read address +// rdOutEn - enable read register to appear on 'data' lines +// wrAddr - write address +// wrEn - write 'data' lines to selected (write) register +// clk - this actually does the write +// dataIn - data in (for register write) +// +// outputs: +// dataOut - data out for register read (tristate) +// +module regfile(rdAddr, rdOutEn, wrAddr, wrEn, clk, dataIn, dataOut); + + input [3:0] rdAddr; // 4-bit addressing + input rdOutEn; + input [3:0] wrAddr; + input wrEn; + input clk; + input tri [3:0] dataIn; // tristate + output tri [3:0] dataOut; // tristate + + reg [3:0] memory[0:15]; // we define 16 4-bit registers + + assign dataOut = (rdOutEn)? memory[rdAddr]: 4'bzzzz; + + always @(posedge clk) begin + if (wrEn) begin + // this writes to location wrAddr + memory[wrAddr] <= dataIn; + end + end + +endmodule + + +// +// regfile16x4_dual.sv - 16 x 4-bit register file +// +// rev history: +// 12/4/2022 - based on LM3000 regfile.v +// +// inputs: +// rdAddr - read address +// rdOutEn - enable read register to appear on 'data' lines +// wrAddr - write address +// wrEn - write 'data' lines to selected (write) register +// clk - this actually does the write +// dataIn - data in (for register write) +// +// outputs: +// dataOut - data out for register read (tristate) +// + +module regfile16x4_dual(rdAddr1, rdOutEn1, rdAddr2, rdOutEn2, wrAddr, wrEn, clk, dataIn, dataOut1, dataOut2); + + input [3:0] rdAddr1; // 4-bit addressing + input rdOutEn1; + input [3:0] rdAddr2; + input rdOutEn2; + input [3:0] wrAddr; + input wrEn; + input clk; + input [3:0] dataIn; + output tri [3:0] dataOut1; // tristate + output tri [3:0] dataOut2; // tristate + + reg [3:0] memory[0:15]; // we define 16 4-bit registers + + // note: these are dual read ports - does this synthesize?? + assign dataOut1 = (rdOutEn1)? memory[rdAddr1]: 4'bzzzz; + + assign dataOut2 = (rdOutEn2)? memory[rdAddr2]: 4'bzzzz; + + always @(posedge clk) begin + if (wrEn) begin + // this writes to location wrAddr + //$display("** %g regfile: writing [%b] = %b (0x%0x)", $time, wrAddr, dataIn, dataIn); + memory[wrAddr] <= dataIn; + end + end + + +endmodule
diff --git a/verilog/rtl/regfile_top.v b/verilog/rtl/regfile_top.v new file mode 100644 index 0000000..d3be451 --- /dev/null +++ b/verilog/rtl/regfile_top.v
@@ -0,0 +1,88 @@ +`default_nettype none + +// +// top level module +// + +module rolfmobile99_top( + input [18:0] io_in, // 19 inputs + output [8:0] io_out // 9 outputs +); + + // note: these assigments should match inputs/outputs declared in info.yaml! + wire clk = io_in[0]; + wire reset = io_in[1]; + wire xnor_a = io_in[2]; + wire xnor_b = io_in[3]; + + // regfile inputs + wire en1 = io_in[4]; + wire en2 = io_in[5]; + wire wrEn = io_in[6]; + wire [3:0] rdAddr1 = io_in[10:7]; + wire [3:0] rdAddr2 = io_in[14:11]; + wire [3:0] dataIn = io_in[18:15]; + + + // XNOR output + assign io_out[0] = xnor_y; + + // regfile outputs + assign io_out[4:1] = dataBusA; + assign io_out[8:5] = dataBusB; + + + // io_out[6:0] = ... ; // notused + + wire xnor_y; + + // connect modules + + // first, just an XNOR gate + xnor1 xnor1(.a(xnor_a), + .b(xnor_b), + .y(xnor_y)); + + // second, a 16x4 bit register file (see below!) + + // needs the following: + // inputs: (4+15) + // - clk 1 + // - reset 1 + // - xnor_a 1 + // - xnor_b 1 + // + // - en1 1 + // - en2 1 + // - wrEn 1 + // - rdAddr1 4 + // - rdAddr2 4 + // - wrAddr 4 (can combine with rdAddr1) + // - dataIn 4 + // + // outputs (1+8): + // - xnor_y 1 + // + // - dataBusA 4 + // - dataBusB 4 + + wire [3:0] dataBusA; + wire [3:0] dataBusB; + + wire [3:0] wrAddr; + + assign wrAddr[3:0] = rdAddr1[3:0]; // combine with rdAddr1 to save input pins + + + regfile16x4_dual regfile(.rdAddr1(rdAddr1), + .rdOutEn1(en1), + .rdAddr2(rdAddr2), + .rdOutEn2(en2), + .wrAddr(wrAddr), + .clk(clk), + .wrEn(wrEn), + .dataIn(dataIn), + .dataOut1(dataBusA), + .dataOut2(dataBusB) ); + +endmodule