ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 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