ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.06.2025
Просмотров: 3496
Скачиваний: 2
110
inp(7)
MUX
inp(6)
MUX
inp(5)
MUX
inp(4)
MUX
inp(3)
MUX
inp(2)
MUX
inp(1)
MUX
inp(0)
Chapter 6
outp(7)
outp(6)
outp(5)
outp(4)
outp(3)
outp(2)
outp(1)
MUX outp(0)
‘0’
shift
Figure 6.11
Simple barrel shifter of example 6.9.
Figure 6.12
Simulation results of example 6.9.
TLFeBOOK
Sequential Code |
111 |
10 END barrel;
11 ---------------------------------------------
12 ARCHITECTURE RTL OF barrel IS
13BEGIN
14PROCESS (inp, shift)
15BEGIN
16IF (shift=0) THEN
17outp <= inp;
18ELSE
19outp(0) <= '0';
20FOR i IN 1 TO inp'HIGH LOOP
21outp(i) <= inp(i-1);
22END LOOP;
23END IF;
24END PROCESS;
25END RTL;
26 ---------------------------------------------
Example 6.10: Leading Zeros
The design below counts the number of leading zeros in a binary vector, starting from the left end. The solution illustrates the use of LOOP / EXIT. Recall that EXIT implies not a escape from the current iteration of the loop, but rather a definite exit from it (that is, even if i is still within the specified range, the LOOP statement will be considered as concluded). In this example, the loop will end as soon as a ‘1’ is found in the data vector. Therefore, it is appropriate for counting the number of zeros that precedes the first one.
1 --------------------------------------------
2LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 --------------------------------------------
5ENTITY LeadingZeros IS
6PORT ( data: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
7 |
zeros: OUT INTEGER RANGE 0 TO 8); |
8 |
END LeadingZeros; |
9 |
-------------------------------------------- |
10 |
ARCHITECTURE behavior OF LeadingZeros IS |
TLFeBOOK
112 |
Chapter 6 |
Figure 6.13
Simulation results of example 6.10.
11BEGIN
12PROCESS (data)
13VARIABLE count: INTEGER RANGE 0 TO 8;
14BEGIN
15count := 0;
16FOR i IN data'RANGE LOOP
17CASE data(i) IS
18WHEN '0' => count := count + 1;
19WHEN OTHERS => EXIT;
20END CASE;
21END LOOP;
22zeros <= count;
23END PROCESS;
24END behavior;
25--------------------------------------------
Simulation results, verifying the functionality of the circuit, are shown in figure 6.13. With data ¼ ‘‘00000000’’ (decimal 0), eight zeros are detected; when data ¼ ‘‘00000001’’ (decimal 1), seven zeros are encountered; etc.
6.7 CASE versus IF
Though in principle the presence of ELSE in the IF/ELSE statement might infer the implementation of a priority decoder (which would never occur with CASE), this will generally not happen. For instance, when IF (a sequential statement) is used to implement a fully combinational circuit, a multiplexer might be inferred instead. Therefore, after optimization, the general tendency is for a circuit synthesized from a VHDL code based on IF not to di¤er from that based on CASE.
TLFeBOOK
Sequential Code |
113 |
Table 6.1
Comparison between WHEN and CASE.
WHEN |
CASE |
|
Statement type |
Concurrent |
Sequential |
Usage |
Only outside PROCESSES, |
Only inside PROCESSES, |
FUNCTIONS, or |
FUNCTIONS, or |
|
PROCEDURES |
PROCEDURES |
|
All permutations must be tested |
Yes for WITH/SELECT/WHEN |
Yes |
Max. # of assignments per test |
1 |
Any |
No-action keyword |
UNAFFECTED |
NULL |
Example: The codes below implement the same physical multiplexer circuit.
----With IF: --------------
IF (sel="00") THEN x<=a; ELSIF (sel="01") THEN x<=b; ELSIF (sel="10") THEN x<=c; ELSE x<=d;
----With CASE: ------------
CASE sel IS
WHEN "00" => x<=a; WHEN "01" => x<=b; WHEN "10" => x<=c; WHEN OTHERS => x<=d;
END CASE;
----------------------------
6.8CASE versus WHEN
CASE and WHEN are very similar. However, while one is concurrent (WHEN), the other is sequential (CASE). Their main similarities and di¤erences are summarized in table 6.1.
Example: From a functional point of view, the two codes below are equivalent.
---- With WHEN: ----------------
WITH sel SELECT
TLFeBOOK
114 |
Chapter 6 |
x <= |
a WHEN "000", |
||
b |
WHEN |
"001", |
|
c |
WHEN |
"010", |
|
UNAFFECTED WHEN OTHERS; |
|||
---- With CASE: ----------------
CASE sel IS
WHEN "000" => x<=a;
WHEN "001" => x<=b;
WHEN "010" => x<=c;
WHEN OTHERS => NULL;
END CASE;
--------------------------------
6.9Bad Clocking
The compiler will generally not be able to synthesize codes that contain assignments to the same signal at both transitions of the reference (clock) signal (that is, at the rising edge plus at the falling edge). This is particularly true when the target technology contains only single-edge flip-flops (CPLDs, for example—appendix A). In this case, the compiler might display a message of the type ‘‘signal does not hold value after clock edge’’ or similar.
As an example, let us consider the case of a counter that must be incremented at every clock transition (rising plus falling edge). One alternative could be the following:
PROCESS (clk)
BEGIN
IF(clk'EVENT AND clk='1') THEN counter <= counter + 1;
ELSIF(clk'EVENT AND clk='0') THEN counter <= counter + 1;
END IF;
...
END PROCESS;
In this case, besides the messages already described, the compiler might also complain that the signal counter is multiply driven. In any case, compilation will be suspended.
TLFeBOOK
Sequential Code |
115 |
Another important aspect is that the EVENT attribute must be related to a test condition. For example, the statement IF(clk'EVENT AND clk='1') is correct, but using simply IF(clk'EVENT) will either have the compiler assume a default test value (say ‘‘AND clk='1'’’) or issue a message of the type ‘‘clock not locally stable’’. As an example, let us consider again the case of a counter that must be incremented at both transitions of clk. One could write:
PROCESS (clk)
BEGIN
IF(clk'EVENT) THEN
counter := counter + 1;
END IF;
...
END PROCESS;
Since the PROCESS above is supposed to be run every time clk changes, one might expect the counter to be incremented twice per clock cycle. However, for the reason already mentioned, this will not happen. If the compiler assumes a default value, a wrong circuit will be synthesized, because only one edge of clk will be considered; if no default value is assumed, then an error message and no compilation should be expected.
Finally, if a signal appears in the sensitivity list, but does not appear in any of the assignments that compose the PROCESS, then it is likely that the compiler will simply ignore it. This fact can be illustrated with the double-edge counter described above once again. Say that the following code is used:
PROCESS (clk)
BEGIN
counter := counter + 1;
...
END PROCESS;
This code reinforces the desire that the signal counter be incremented whenever an event occurs on clk (rising plus falling edge). However, a message of the type ‘‘ignored unnecessary pin clk’’ might be issued instead.
Example: Contrary to the cases described above, the 2-process code shown below will be correctly synthesized by any compiler. However, notice that we have used a di¤erent signal in each process.
TLFeBOOK
116 |
Chapter 6 |
----------------------
PROCESS (clk)
BEGIN
IF(clk'EVENT AND clk='1') THEN x <= d;
END IF;
END PROCESS;
----------------------
PROCESS (clk)
BEGIN
IF(clk'EVENT AND clk='0') THEN y <= d;
END IF;
END PROCESS;
----------------------
Now that you know what you can and what you should not to do, you are invited to solve problem 6.1.
Example 6.11: RAM
Below is another example using sequential code, particularly the IF statement. We show the implementation of a RAM (random access memory).
As can be seen in figure 6.14(a), the circuit has a data input bus (data_in), a data output bus (data_out), an address bus (addr), plus clock (clk) and write enable
RAM |
wr_ena |
||||||||||||||||||||||
data in |
word 0 |
data_out |
wr_ena |
||||||||||||||||||||
word 1 |
|||||||||||||||||||||||
d |
q |
||||||||||||||||||||||
addr |
word 2 |
DFF |
|||||||||||||||||||||
… |
clk |
||||||||||||||||||||||
clk |
wr ena |
||||||||||||||||||||||
(a) |
(b) |
Figure 6.14 |
|
RAM circuit of example 6.11. |
TLFeBOOK
Sequential Code |
117 |
(wr_ena) pins. When wr_ena is asserted, at the next rising edge of clk the vector present at data_in must be stored in the position specified by addr. The output, data_out, on the other hand, must constantly display the data selected by addr.
From the register point-of-view, the circuit can be summarized as in figure 6.14(b). When wr_ena is low, q is connected to the input of the flip-flop, and terminal d is open, so no new data will be written into the memory. However, when wr_ena is turned high, d is connected to the input of the register, so at the next rising edge of clk d will overwrite its previous value.
A VHDL code that implements the circuit of figure 6.14 is shown below. The capacity chosen for the RAM is 16 words of length 8 bits each. Notice that the code is totally generic.
Note: Other memory implementations will be presented in section 9.10 of chapter 9.
1 ---------------------------------------------------
2LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 ---------------------------------------------------
5ENTITY ram IS
6 |
GENERIC ( bits: INTEGER := 8; |
-- |
# of |
bits per |
word |
7 |
words: INTEGER := 16); |
-- |
# of |
words in |
the memory |
8PORT ( wr_ena, clk: IN STD_LOGIC;
9addr: IN INTEGER RANGE 0 TO words-1;
10data_in: IN STD_LOGIC_VECTOR (bits-1 DOWNTO 0);
11data_out: OUT STD_LOGIC_VECTOR (bits-1 DOWNTO 0));
12END ram;
13 ---------------------------------------------------
14 ARCHITECTURE ram OF ram IS
15TYPE vector_array IS ARRAY (0 TO words-1) OF
16STD_LOGIC_VECTOR (bits-1 DOWNTO 0);
17SIGNAL memory: vector_array;
18BEGIN
19PROCESS (clk, wr_ena)
20BEGIN
21IF (wr_ena='1') THEN
22IF (clk'EVENT AND clk='1') THEN
23memory(addr) <= data_in;
24END IF;
25END IF;
TLFeBOOK
118 |
Chapter 6 |
Figure 6.15
Simulation results of example 6.11.
26END PROCESS;
27data_out <= memory(addr);
28END ram;
29---------------------------------------------------
Simulation results from the circuit synthesizad with the code above are shown in figure 6.15.
6.10 Using Sequential Code to Design Combinational Circuits
We have already seen that sequential code can be used to implement either sequential or combinational circuits. In the former case, registers are necessary, so will be inferred by the compiler. However, this should not happen in the latter case. Moreover, if the code is intended for a combinational circuit, then the complete truth-table should be clearly specified in the code.
In order to satisfy the criteria above, the following rules should be observed:
Rule 1: Make sure that all input signals used (read) in the PROCESS appear in its sensitivity list.
Rule 2: Make sure that all combinations of the input/output signals are included in the code; that is, make sure that, by looking at the code, the circuit’s complete truthtable can be obtained (indeed, this is true for both sequential as well as concurrent code).
Failing to comply with rule 1 will generally cause the compiler to simply issue a warning saying that a given input signal was not included in the sensitivity list, and then proceed as if the signal were included. Even though no damage is caused to the design in this case, it is a good design practice to always take rule 1 into consideration.
TLFeBOOK