Defining and accessing temporary registers

Using memory to store data

531

When processor or digital circuit needs to temporarily store a relatively small number of data values (say, from 2 to 32), flip-flop based registers are often used. Flip-flop holding resisters are simple to define and use in a Verilog environment, but they consume lots of resources. If a greater number of data points need to be stored, more efficient and special-purpose memory circuits are often used. For example, most FPGA’s include special-purpose SRAM arrays (Xilinx calls them “block RAMs”) that use asynchronous storage cells that use only a few transistors per cell, whereas flip-flops use 30 or more transistors each.

For this project, only eight 16-bit registers are needed. This is a relatively few number of bits, and so the simpler flip-flop use model outweighs the increased circuit efficiency of SRAM cells (SRAMs require a special control circuit that will presented later). When a group of registers are used to store temporary data values, they are often organized and referred to as a register file.

A register file typically contains an address decoder to select which register is to be written, and an address mux to determine which register is to be read. Note that particular timings must be obeyed for both reading and writing. To compete a write cycle, the write address, a write enable signal, and the data value must be present at the appropriate clock edge. Likewise, to complete a read cycle, the data must be consumed while the read address is present.

A block diagram and sample Verilog code for a simple register file are shown below.

Figure 1. Temporary Register File Block Diagram
Figure 1. Temporary Register File Block Diagram
module regfile(
    input clk, rst, clr, wen,
    input [2:0] add,
    input [7:0] d_in,
    output reg [7:0] d_out
    );
    
reg [7:0] registers[7:0];
integer i;
  
always @(posedge(clk), posedge(rst))        // 
    begin                                   //  
        if (rst) begin                      //
        for (i=0; i<7; i=i+1)               //  For loop assigns asynch reset to all registers
            registers[i] <= 8'b0;           //
        end      
    else if (wen) registers[add] <= d_in;   //  Write new data if wen asserted

end

always @(add, registers)                    // Output mux always driven
   d_out <= registers[add];
 
endmodule