FONT SIZE : AAA
The simplest counter to implement in many cases is the basic binary counter. The basic structure of a counter is a series of flip-flops (a register), that is controlled by a reset (to reset the counter to zero literally) and a clock signal used to increment the counter. The final signal is the counter output, the size of which is determined by the generic parameter n, which defines the size of the counter. The symbol for the counter is given in Figure 24.1. Notice that the reset is active low and the counter and reset inputs are given in a separate block of the symbol as defined in the IEEE standard format.
From an FPGA implementation point of view, the value of generic n also defines the number of D type flip-flops required (usually a single LUT) and hence the usage of the resources in the FPGA. A simple implementation of such a counter is given here:
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 entity counter is
6 generic (
7 n : integer := 4
8 );
9 port (
10 clk : in std_logic;
11 rst : in std_logic;
12 output : out std_logic_vector((n−1) downto 0)
13 );
14 end;
Figure 24.1 Simple binary counter.
15
16 architecture simple of counter is
17 begin
18 process(clk, rst)
19 variable count : unsigned((n−1) downto 0);
20 begin
21 if rst = ’0’ then
22 count := (others => ’0’);
23 elsif rising_edge(clk) then
24 count := count + 1;
25 end if;
26 output <= std_logic_vector(count);
27 end process;
28 end;
The important aspect of this approach to the counter VHDL is that this is effectively a state machine; however, we do not have to explicitly define the next state logic, as this will be taken care of by the synthesis software. This counter can now be tested using a simple test bench that resets the counter and then clocks the state machine until the counter flips round to the next counter round. The test bench is given as follows:
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 entity CounterTest is
6 end CounterTest;
7
8 architecture stimulus of CounterTest is
9 signal rst : std_logic := ’0’;
10 signal clk : std_logic:=’0’;
11 signal count : std_logic_vector (3 downto 0);
12
13 component counter
14 port(
15 clk : in std_logic;
16 rst : in std_logic;
17 output : out std_logic_vector(3 downto 0)
18 );
19 end component;
20 for all : counter use entity work.counter ;
21
22 begin
23 DUT: counter port map(clk=>clk,rst=>rst,output=>count);
24 clk <= not clk after 1 us;
25 process
26 begin
27 rst<=’0’,’1’ after 2.5 us;
28 wait;
29 end process;
30 end;
Using this simple VHDL test bench, we reset the counter until 2.5µs and then the counter will count on the rising edge of the clock after 2µs (i.e., the counter is running at 500 kHz).
If we dissect this model, there are several interesting features to notice. The first is that we need to define an internal variable count rather than simply increment the output variable q. The output variable q has been defined as a standard logic vector (std_logic_vector) and with it being defined as an output we cannot use it as the input variable to an equation. Therefore we need to define a local variable (in this case, count) to store the current value of the counter.
The initial decision to make is whether to use a variable or a signal. In this case, we need an internal variable that we can effectively treat as a sequential signal, and also one that changes instantaneously, which immediately requires the use of a variable. If we chose a signal, then the changes would only take place when the cycle is resolved (i.e., the next time the process is activated).
The second decision is what type of unit to use for the count variable. The output variable is a std_logic_vector type, which has the advantage of being an array of std_logic signals, and so we don’t need to specify the individual bits on a word; this is done automatically. The major disadvantage, however, is that the std_logic_vector does not support simple arithmetic operations, such as addition, directly. In this example, we want the counter to have a simple definition in VHDL and so the best compromise type that has the bitwise definition and also the arithmetic functionality would be the unsigned or signed type. In this case, we wish to have a direct mapping between the std_logic_vector bits and the counter bits, so the unsigned type is appropriate. Thus the declaration of the internal counter variable count is as follows:
1 variable count : unsigned((n−1) downto 0);
The final stage of the model is to assign the internal value of the count variable to the external std_logic_vector q. Luckily, the translation from unsigned to std_logic_vector is fairly direct, using the standard casting technique:
Figure 24.2 Simple binary counter simulation in VHDL.
1 q <= std_logic_vector(count);
As the basic types of both q and count are consistent, this can be done directly. The resulting model simply counts up the binary values on the clock edge as specified, as is shown in Figure 24.2.
Manufacturer:Xilinx
Product Categories:
Lifecycle:Any -
RoHS: -
Manufacturer:Xilinx
Product Categories: Embedded - FPGAs (Field Programmable Gate Array)
Lifecycle:Obsolete -
RoHS: No RoHS
Manufacturer:Xilinx
Product Categories: Industrial components
Lifecycle:Obsolete -
RoHS: No RoHS
Manufacturer:Xilinx
Product Categories: Embedded - FPGAs (Field Programmable Gate Array)
Lifecycle:Obsolete -
RoHS:
Manufacturer:Xilinx
Product Categories: FPGAs (Field Programmable Gate Array)
Lifecycle:Obsolete -
RoHS: No RoHS
Support