When a computer executes instructions, it often needs intermidiate storage places. Reading instructions from memory, writing results back to memory. For example adding numbers, and writing back only when all numbers have been added. Then registers can be used, to hold the intermediate sum, while the calculation is ongoing. We can refer to such a row using the term register. Another use of registers is for addressing. In this scenario, the value stored in the register is an address, addressing a part of the memory. One such register is holding an address pointing to the next instruction to be executed. This register is referred to as the program counter.
A D flip-flop can store one bit. We can imagine a register as a row of D flip-flops, each storing one bit, with the possibility to load new values into all D flip-flops simultaneously.
A register implementation in Verilog is shown in Figure 6.
module n_bit_register(clk, data_in, data_out); parameter N = 8; input clk; input[N-1:0] data_in; output[N-1:0] data_out; wire clk; wire [N-1:0] data_in; reg [N-1:0] reg_value; always @(posedge clk) reg_value <= data_in; assign data_out = reg_value; endmodule
Figure 6. A register in Verilog.
The code in Figure 6 defines a module. The module has two inputs, called clk and data_in, and one output, called data_out.
SOURCES := n_bit_register.v n_bit_register_tb.v n_bit_register_tb: $(SOURCES) iverilog -o $@ $^ .PHONY: clean clean: rm n_bit_register_tb
Figure 7. A makefile for building and running the register in Figure 6.