A bit can have the values 0 or 1. In a computer, these values are represented by a low and a high value of an electrical signal.
The value of a bit can be stored. This means that the value is remembered, as long as it is stored. While the value is stored, the value can be read, and used, for the purpose of performing different operations. Examples of operations could be to store the value somewhere, for example in memory, or using the value in an addition operation.
The value of a bit can be stored in a building block called D flip-flop.
A D flip-flop stores one bit of data. A new value can be stored when a clock signal changes value. A component which can change its stored value only when a clock signal changes is called a synchronous component.
A D flip-flop implementation in VHDL is shown in Figure 2.
library ieee; use ieee.std_logic_1164.all; entity d_ff is port( clk: in std_logic; data_in: in std_logic; data_out: out std_logic); end d_ff; architecture rtl of d_ff is signal reg_value: std_logic; begin update: process(clk) begin if rising_edge(clk) then reg_value <= data_in; end if; end process; data_out <= reg_value; end rtl;
Figure 2. A D flip-flop in VHDL.
The code in Figure 2 starts with a reference to a library. We use the library to get access to a data type called std_logic. Variables of this data type represent binary data.
The architecture block, which is called rtl, for register-transfer level, defines a variable called reg_value. The variable reg_value is defined using the keyword signal.
ghdl -a d_ff.vhdl ghdl -a d_ff_tb.vhdl
The combined system, containing the D flip-flip and the testbench, can be elaborated by the command
ghdl -e d_ff_tb
The simulation can be run by giving the command
ghdl -r d_ff_tb
The resulting printout is shown in Figure 4.
d_ff_tb.vhdl:63:8:@1ns:(report note): data_in='0', data_out='U' d_ff_tb.vhdl:63:8:@4ns:(report note): data_in='0', data_out='U' d_ff_tb.vhdl:63:8:@6ns:(report note): data_in='1', data_out='0' d_ff_tb.vhdl:63:8:@8ns:(report note): data_in='1', data_out='0' d_ff_tb.vhdl:63:8:@9ns:(report note): data_in='0', data_out='1' d_ff_tb.vhdl:63:8:@12ns:(report note): data_in='0', data_out='1'
Figure 4. Printout from running the testbench in Figure 3.
reporter: process(clk, d_ff_data_in) is begin if (rising_edge(clk) or d_ff_data_in'event) then report "data_in=" & std_logic'image(d_ff_data_in) & ", data_out=" & std_logic'image(d_ff_data_out); end if; end process;
with the effect that a printout is done whenever the clock signal has a rising edge, or the variable d_ff_data_in changes value. The changes for the variable d_ff_data_in are defined in the stim_gen process in Figure 3.
The testbench in Figure 3 generates printouts as shown in Figure 4. The printouts show values of digital signals, each having the value one or zero. We can represent these signals as waveforms, with the level of the waveform being one or zero. Thinking of the value one as a high voltage level, and the value zero as a low voltage level, we can think of the waveforms as representing actual voltages, in an actual digital system.
A waveform can be visualized using the GTKWave program. We can download a GTKWave version for Mac, in the form of a zip-file that contains an executable GTKWave program. The GTKWave program can be started from a Mac Terminal, by giving the command open followed by the app file name of the program. As an example, I could start the program by doing
A GTKWave version for Ubuntu can be installed in Ubuntu, by giving the command
sudo apt-get install gtkwave
The program can then be started by giving the command gtkwave.