Skip to content

Section 7: Verilog Memory Arrays

In this discussion section, you will use what you have learned in the previous discussion sections to implement a simple register file memory array at the register-transfer level (RTL). In the past discussion sections, we have focused on how to use Verilog to model combinational and sequential logic at both the gate-level and RTL. In this discussion section, we will only be using RTL. Remember from previous discussion sections that it is critical that students always know what is the hardware they are modeling; students should understand what their RTL would likely turn into at the gate-level.

1. Logging Into verilog-exam with VS Code

The Verilog coding exam is meant to assess students' ability to independently implement and test simple hardware modules. It will take place before the Thanksgiving break during a student's officially assigned discussion section in 225 Upson Hall.

Students must use the workstations for this discussion section!

Students cannot use their own laptops for the Verilog coding exam. Students must use the workstations in the 225 Upson Hall computer lab for the Verilog coding exam. So all students must use the workstations for this discussion section. Students should not log into ecelinux. They should instead log into verilog-exam.ece.cornell.edu. This will enable students to get familar with using the workstations and ensure there are no technical issues.

Find a free workstation and log into the workstation using your NetID and standard NetID password. Then complete the following steps. Do not log into ecelinux-XX.ece.cornell.edu. You must log into verilog-exam.ece.cornell.edu!

  • Start VS Code
  • Install the Remote-SSH, Verilog, and Surfer extensions
  • Use View > Command Palette to execute Remote-SSH: Connect Current Window to Host...
  • Enter netid@verilog-exam.ece.cornell.edu
  • Install the Verilog extension on the server
  • Use View > Explorer to open your home directory on verilog-exam
  • Use View > Terminal to open a terminal on verilog-exam

There is no need to fork or clone the repo for today's discussion section. The code for today's discussion section should already be in your home directory on verilog-exam. This is the same process we will use for the Verilog coding exam.

% source setup-ece2300.sh
% cd ${HOME}/ece2300/sec07
% tree

The repo includes the following files:

  • Makefile.in: Makefile for the build system
  • configure: Configure script for the build system
  • configure.ac: Used to generate the configure script
  • scripts: Scripts used by the build system
  • ece2300: ECE 2300 unit testing library and miscellaneous macros
  • mem/mem.mk: Tells build system about files in this subproject
  • mem/Mux4_4b_RTL.v: 4-to-1 4-bit mux in RTL
  • mem/Decoder_RTL.v: 2-to-4 binary decoder in RTL
  • mem/Register_RTL.v: 4-bit register with enable in RTL
  • mem/RegfileStruct1r1w_4x4b_RTL.v: Register file using structural RTL
  • mem/RegfileFlat1r1w_4x4b_RTL.v: Register file using flat RTL
  • mem/test: Directory with unit tests for each hardware module

Go ahead and create a build directory, run configure to generate a Makefile, and run the tests.

% cd ${HOME}/ece2300/sec07
% mkdir -p build
% cd build
% ../configure
% make check

To make it easier to cut-and-paste commands from this handout onto the command line, you can tell Bash to ignore the % character using the following command:

% alias %=""

Now you can cut-and-paste a sequence of commands from this tutorial document and Bash will not get confused by the % character which begins each line.

2. Memory Arrays

A memory array is a two-dimensional array of sequential logic gates (also called "bit cells"). The following diagram illustrates the high-level idea for a memory array.

In this discussion section, we will be building a register file, a specific kind of memory array where D flip-flops are used as the sequental logic gates. You will start by implementing a 4-to-1 4-bit mux, 2-to-4 decoder, and 4-bit register. You will then implement a 4-word 4-bit register file memory array in two ways: (1) structurally by composing the mux, register, and decoder; and (2) flat using a single always_ff and always_comb block.

3. 4-to-1 RTL Multiplexor

We have provided you the interface for the mux in Mux4_4b_RTL.v.

1
2
3
4
5
6
7
8
9
module Mux4_4b_RTL
(
  input  logic [3:0] in0,
  input  logic [3:0] in1,
  input  logic [3:0] in2,
  input  logic [3:0] in3,
  input  logic [1:0] sel,
  output logic [3:0] out
);

Use what you have learned about RTL modeling to create a Verilog hardware design that implements a 4-to-1 4-bit mux. You should have a single always_comb block. You can use use if/else conditional operators or a case statement instead. We provide you all of the tests you need. You can run the test simulator for the mux as follows.

% cd ${HOME}/ece2300/sec07/build
% make Mux4_4b_RTL-test
% ./Mux4_4b_RTL-test

4. 2-to-4 RTL Decoder

We will now implement a 2-to-4 binary decoder using RTL modeling. Recall that a decoder takes as input a binary number and produces a one-hot encoding of that binary number. If the input is 0, then bit 0 should be 1 and the remaining bits should be 0. If the input is 1, then bit 1 should be 1 and the remaining bits should be 0.

We have provided you the interface for the decoder in Decoder_2b_RTL.v.

1
2
3
4
5
module Decoder_2b_RTL
(
  input  logic [1:0] in,
  output logic [3:0] out
);

Use what you have learned to create a Verilog hardware design that implements a 2-to-4 decoder. You should have a single always_comb block. We provide you all of the tests you need. You can run the test simulator for the mux as follows.

% cd ${HOME}/ece2300/sec07/build
% make Decoder_2b_RTL-test
% ./Decoder_2b_RTL-test

5. 4-bit RTL Register

We will now implement a 4-bit register with enable (but no reset!) using RTL modeling. We have provided you the interface for the register in Register_4b_RTL.v.

1
2
3
4
5
6
7
module Register_RTL
(
  input  logic       clk,
  input  logic       en,
  input  logic [3:0] d,
  output logic [3:0] q
);

Use what you have learned to create a Verilog hardware design that implements a 4-bit register. You should have a single always_ff block with an if/else conditional operation to handle the enable signals. You will need to correctly handle explicit X-propagation using the ECE2300_SEQ_XPROP macro. We provide you all of the tests you need. You can run the test simulator for the mux as follows.

% cd ${HOME}/ece2300/sec07/build
% make Register_4b_RTL-test
% ./Register_4b_RTL-test

6. Structural Register File

A memory array is a two-dimensional array of sequential logic gates (also called "bit cells"). A register file is a specific kind of memory array where D flip-flops are used as the sequental logic gates. We can implement a register file structurally using the mux, decoder, and register developed earlier in this discussion section.

This register file has four "words" and each word is 4-bits. The register file has one write port and one read port (i.e., we can do a 4-bit write and a 4-bit read at the same time). The read port is combinational; if we set the read address then the read data comes back that same cycle (i.e., combinationally).

We have provided you the interface for the register file in RegfileStruct1r1w_4x4b_RTL.v:

module RegfileStruct1r1w_4x4b_RTL
(
  input  logic       clk,

  input  logic       wen,
  input  logic [1:0] waddr,
  input  logic [3:0] wdata,

  input  logic [1:0] raddr,
  output logic [3:0] rdata
);

Notice there is no reset signal. Register files often include many bit cells and the hardware required to reset every single bit cell can be significant; so register files usually do not include a reset signal.

The following construct creates an array of multi-bit signals:

logic [3:0] reg_q [4];

This creates an array of four signals, each signal is four-bits. This can be a useful way to create an array of multi-bit signals for the output of each register.

Use what you have learned to create a Verilog hardware design that implements a 4-word 4-bit register file. We provide you all of the tests you need. You can run the test simulator for the mux as follows.

% cd ${HOME}/ece2300/sec07/build
% make RegfileStruct1r1w_4x4b_RTL-test
% ./RegfileStruct1r1w_4x4b_RTL-test

7. Flat Register File

We can also implement a register file flat using a single always_ff block for the write ports and a single always_comb block for the read port. This register file has the exact same interface as the structural version implemented in the previous section.

We will use an array of signals to act as the state.

logic [3:0] regfile [4];

You can read and write four-bit signals from this array by simply indexing into it. So the following will write the binary value 0011 into the second signal in this array.

always_ff @(posedge clk) begin
  regfile[1] <= 4'b0011;
end

Implement the flat register file using a single always_ff block and a single always_comb block. We provide you all of the tests you need. You can run the test simulator for the mux as follows.

% cd ${HOME}/ece2300/sec07/build
% make RegfileFlat1r1w_4x4b_RTL-test
% ./RegfileFlat1r1w_4x4b_RTL-test

8. Clean Build

As a final step, do a clean build to verify everything is working correctly.

% cd ${HOME}/ece2300/sec07
% trash build
% mkdir -p build
% cd build
% ../configure
% make check