Skip to content

Commit a077511

Browse files
committed
- Added Variables and Blocking.
1 parent fccf04e commit a077511

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# Variables and Blocking
2+
## VHDL Variables
3+
VHDL is my favorite HDL because, despite how clumsy it can be, there are some very nice tricks you
4+
can use which have no Verilog/SystemVerilog equivalent. One of these is variables.
5+
6+
Consider the following example:
7+
```vhdl
8+
process (clk) begin
9+
if rising_edge(clk) then
10+
if sel0 = '1' then
11+
x <= (a + b) + c;
12+
else
13+
x <= (a + b) - c;
14+
end if;
15+
end if;
16+
end process;
17+
```
18+
19+
We can see here that the expression (a + b) is used in both cases in both the if and else cases.
20+
It would be nice if we could write this without and code duplication.
21+
22+
```vhdl
23+
a_plus_b <= a + b;
24+
25+
-- A bunch of code here...
26+
27+
process (clk) begin
28+
if rising_edge(clk) then
29+
if sel0 = '1' then
30+
x <= a_plus_b + c;
31+
else
32+
x <= a_plus_b - c;
33+
end if;
34+
end if;
35+
end process;
36+
```
37+
38+
This is better. However, we have now separated the expression (a + b) from the code block dependent
39+
on it. In this case it does not matter all that much because a_plus_b makes it very clear what
40+
the expression is, but there are a lot of other cases where we might have a more complicated
41+
expression that is not easily described by a signal name.
42+
43+
```vhdl
44+
process (a, b) begin
45+
if sel1 = '1' then
46+
complex_logic <= a << 1;
47+
else
48+
complex_logic <= b >> 1;
49+
end if;
50+
end process;
51+
52+
-- A bunch of code here...
53+
54+
process (clk) begin
55+
if rising_edge(clk) then
56+
if sel0 = '1' then
57+
x <= complex_logic + c;
58+
else
59+
x <= complex_logic - c;
60+
end if;
61+
end if;
62+
end process;
63+
```
64+
65+
Now this becomes problematic. It is not clear what complex_logic is unless we actually look at where
66+
is assigned. This is where variables are useful.
67+
68+
```vhdl
69+
process (clk)
70+
variable complex_logic : std_logic_vector(7 downto 0);
71+
begin
72+
if rising_edge(clk) then
73+
if sel1 = '1' then
74+
complex_logic := a << 1;
75+
else
76+
complex_logic := b >> 1;
77+
end if;
78+
79+
if sel0 = '1' then
80+
x <= complex_logic + c;
81+
else
82+
x <= complex_logic - c;
83+
end if;
84+
end if;
85+
end process;
86+
```
87+
88+
Using a variable complex_logic, we've eliminated the need for an extra process.
89+
90+
### Signals vs. Variables
91+
But wait! Shouldn't the value of complex_logic be updated when the process has finished execution
92+
like any other signal assigned in a process? The answer is no: unlike signals, variables are always
93+
*updated at assignment* rather than at the end of process execution. There a few consequences of
94+
this behavior:
95+
* **Variables are always treated as the outputs of combinational logic, even when they are in a
96+
sequential block.** Combinational outputs are always a pure function of their inputs. That is, their
97+
values always reflect the values of their inputs at that moment, and thus, they are state-less.
98+
Because variables are updated at assignment rather than at a clock edge (or some other synchronous
99+
event), they too always reflect the values of their inputs at that moment.
100+
101+
* **The scope of a variable is always limited to the process it is declared in.** If a signal x is
102+
assigned in a clocked process, then x is by definition a direct output of a flip-flop, since its
103+
value is only updated on a rising clock edge. But what about variables such as complex_logic? It is
104+
clearly assigned in a clocked process, yet we stated above that we can treat it as an output of
105+
combinational logic. In order to resolve this contradiction, the designers of VHDL chose to [only
106+
allow variables to be declared in processes, function, and
107+
procedures.](http://www.ics.uci.edu/~jmoorkan/vhdlref/var_dec.html) Since variables cannot be
108+
referenced outside of a process, it prevents the unwitting developer from mistakenly using it as the
109+
output of a flip-flop. This is contrary to blocking assignment in Verilog/SystemVerilog. More on
110+
this below.
111+
112+
## Blocking Assignment in Verilog/SystemVerilog
113+
If you are a Verilog/SystemVerilog developer, you may have been upset by the fact that I stated that
114+
Verilog/SystemVerilog has no equivalent to VHDL variables. "Just use blocking (=) assignment!" you
115+
might say. However, blocking assignment is not equivalent to a variable, and is, in fact, much more
116+
dangerous to use.
117+
118+
Let's consider the example above, implemented in SystemVerilog.
119+
TODO: switch to systemverilog syntax
120+
```verilog
121+
always_ff @(posedge clk) begin
122+
if sel1 begin
123+
complex_logic = a << 1;
124+
end else begin
125+
complex_logic = b >> 1;
126+
end
127+
128+
if sel0 begin
129+
x <= complex_logic + c;
130+
end else begin
131+
x <= complex_logic - c;
132+
end
133+
end
134+
```
135+
136+
It works! All we have to do is substitute the variable complex_logic with blocking assignments,
137+
and we get the same behavior. However, there is a slight problem. Remember when we said that a
138+
VHDL variable cannot be referenced outside of a process to avoid being interpreted as both an
139+
output of combinational logic and an output of a flip-flop? That is not true for blocking assignment
140+
in Verilog/SystemVerilog. If a signal is referenced below the blocking assignment, inside of the
141+
same sequential block, it is interpreted as an output of combinational logic just as a VHDL variable
142+
would. However, if it is referenced above the blocking assignment, or outside of the sequential
143+
block containing the blocking assignment, it is interpreted as the output of a flip-flop. This
144+
effectively means that there are two signals with the same name: one is the output of combinational
145+
logic, and the other is the output of a flip-flop that is fed by the same combinational logic. With
146+
blocking assignment, where we reference a signal matters. This is misleading, and thus should be
147+
avoided at all costs.
148+
149+
```verilog
150+
always_ff @(posedge clk) begin
151+
if sel1 begin
152+
complex_logic = a << 1;
153+
end else begin
154+
complex_logic = b >> 1;
155+
end
156+
157+
if sel0 begin
158+
x <= complex_logic + c; // complex_logic is combinational here.
159+
end else begin
160+
x <= complex_logic - c;
161+
end
162+
end
163+
164+
always_ff @(posedge clk) begin
165+
if sel0 begin
166+
y <= complex_logic + c; // complex_logic is the output of a flip-flop here.
167+
end else begin
168+
y <= complex_logic - c;
169+
end
170+
end
171+
```
172+
173+
## References
174+
* [VHDL variables](http://www.ics.uci.edu/~jmoorkan/vhdlref/var_dec.html)

0 commit comments

Comments
 (0)