while loops in
VerilogVerilog supports while loops
much like other programming languages. In this assignment, you will
design a thermometer encoder and decoder using while and
for
loops. A thermometer code is a vector representation
where all bits are 1 up to the
encoded value, and 0 above that
value:
| Decimal | Thermometer |
|---|---|
| 0 | 0000000 |
| 1 | 1000000 |
| 2 | 1100000 |
| 3 | 1110000 |
| 4 | 1111000 |
| 5 | 1111100 |
| 6 | 1111110 |
| 7 | 1111111 |
Thermometer codes are used in some output displays, and in some electronics such as high-speed “Flash” analog-to-digital converters.
To convert a binary number with K bits, the thermometer code needs
W = 2K − 1
bits. So if K=4
then W=15.
module thermometer_encoder
(
input [3:0] a,
output reg [14:0] q
);Next we’ll use a for loop to
perform the encoding:
integer idx;
always @(a) begin
for (idx=0; idx<15; idx=idx+1) begin
if (idx < a)
q[idx] = 1;
else
q[idx] = 0;
end
endTo reverse the thermometer code, the input has W bits and the output should have
K=log2(W+1)
bits. So if W=15
then K=4.
We will use a while loop to
perform the decoding:
integer idx;
always @(a) begin
idx = 16;
while ((a[idx-1] == 0)&&(idx > 0))
idx = idx - 1;
q = idx;
endIn this loop, the index variable idx is initialized to the maximum
value, and then decremented until a non-zero bit is detected. The output
q is the index of the highest
non-zero bit in a.
`defineOpen src/testbench.v
and notice the first few lines:
`define K 4
`define W 2**`K-1
module testbench ();
// DECLARE SIGNALS
reg clk;
reg [`K-1:0] a;
wire [`W-1:0] b;
wire [`K-1:0] c;In Verilog, the `define
statement is analogous to #define in C. It defines a
global macro treated as a constant by the simulator and
synthesis tool. After `K is declared
as a macro, any reference to `K is
substituted with the macro text 4.
The next `define
statement uses the exponentiation operator:
`define W 2**`K-1Verilog permits the syntax A**B meaning AB. This syntax
is usually non-synthesizable, but can be syntheisable if used to compute
constants or parameters. The result `W is called a
“design-time constant”, since it is computed before synthesis
and does not change during operation of the module. The tool treats it
like a number.
Open src/thermometer_encoder.v
and src/thermometer_decoder.v
in a text editor. Make the following revisions:
K and WK and WThen edit src/testbench.v
and use the defparam
syntax to define set the module parameters:
defparam TE1.W = `W;
defparam TE1.K = `K;
defparam TD1.W = `W;
defparam TD1.K = `K;
Change `K to 5 and
run the simulation. Verify that it works properly. Then change `K to 3 and
verify again.
Next, create a top module in
src/top.v to
contain instances of both thermometer_encoder and thermometer_decoder. The top module should have inputs sw, sel, and output led. The top module should be designed to these
specifications:
`K=3sw to the lowest seven
(right-most) switchessel to the highest
switch (15)led to the lowest seven
LEDssel is 0:
a is assigned the lowest
three switch valuesled is assigned bsel is 1:
b is assigned the seven
switch values (bypassing the encoder)led
are assigned c, and the higher
bits are zero.Modify src/testbench.v
to fully test your design (test all possible values of sw and sel). Verify the design in
simulation.
Create an XDC constraint file (copy from the Basys3_Master.xdc template) and a
build.tcl script (copy from a
previous assignment), implement the design and program onto the Basys3
board.
On the Basys3 board, test these cases:
sel=0,
a=7'b0000011sel=0,
a=7'b0000110sel=1,
a=7'b0011111sel=1,
a=7'b0000111Photograph the test cases and save the photos in the working
directory as case1, case2, etc. Turn in your work using
git:
git add case* src/*.v *.rpt *.txt *.tcl *.bit *.xdc
git commit . -m "Complete"
git push origin mainIndicate on Canvas that your assignment is done.