Chapter 4:: Hardware Description Languages: Digital Design and Computer Architecture
Chapter 4:: Hardware Description Languages: Digital Design and Computer Architecture
Chapter 4:: Hardware Description Languages: Digital Design and Computer Architecture
4-<1>
Chapter 4 :: Topics Introduction Combinational Logic Structural Modeling Sequential Logic More Combinational Logic Finite State Machines Parameterized Modules Testbenches
4-<2>
Introduction Hardware description language (HDL): allows designer to specify logic function only. Then a computer-aided design (CAD) tool produces or synthesizes the optimized gates. Most commercial designs built using HDLs Two leading HDLs:
Verilog
developed in 1984 by Gateway Design Automation became an IEEE standard (1364) in 1995
VHDL
Developed in 1981 by the Department of Defense Became an IEEE standard (1076) in 1987
Copyright 2007 Elsevier 4-<3>
HDL to Gates
Simulation
Input values are applied to the circuit Outputs checked for correctness Millions of dollars saved by debugging in simulation instead of hardware
Synthesis
Transforms HDL code into a netlist describing the hardware (i.e., a list of gates and the wires connecting them)
IMPORTANT: When describing circuits using an HDL, its critical to think of the hardware the code should produce.
Copyright 2007 Elsevier 4-<4>
Verilog Modules
a b c
Verilog Module
4-<6>
4-<7>
Synthesis:
b c y
un5_y
un8_y
4-<8>
Verilog Syntax
Case sensitive
Example: reset and Reset are not the same signal.
4-<9>
// internal signal
and3 andgate(a, b, c, n1); // instance of and3 inv inverter(n1, y); // instance of inverter endmodule
Copyright 2007 Elsevier 4-<10>
Bitwise Operators
module gates(input [3:0] a, b, output [3:0] y1, y2, y3, y4, y5); /* Five different two-input logic gates acting on 4 bit busses */ assign y1 = a & b; // AND assign y2 = a | b; // OR assign y3 = a ^ b; // XOR assign y4 = ~(a & b); // NAND assign y5 = ~(a | b); // NOR endmodule
// /**/
Copyright 2007 Elsevier
Reduction Operators
module and8(input [7:0] a, output y); assign y = &a; // &a is much easier to write than // assign y = a[7] & a[6] & a[5] & a[4] & // a[3] & a[2] & a[1] & a[0]; endmodule
4-<12>
Conditional Assignment
module mux2(input [3:0] d0, d1, input s, output [3:0] y); assign y = s ? d1 : d0; endmodule
? :
Copyright 2007 Elsevier
is also called a ternary operator because it operates on 3 inputs: s, d1, and d0.
4-<13>
Internal Variables
module fulladder(input a, b, cin, output s, cout); wire p, g; // internal nodes assign p = a ^ b; assign g = a & b; assign s = p ^ cin; assign cout = g | (p & cin); endmodule
s
g
cin
a b
Copyright 2007 Elsevier
cout
un1_cout
cout
4-<14>
Precedence
Defines the order of operations
Highest
~ *, /, % +, -
<<, >>
<<<, >>> ==, != &, ~&
shift
arithmetic shift equal, not equal AND, NAND
^, ~^
|, ~|
XOR, XNOR
OR, XOR ternary operator
4-<15>
Lowest
Copyright 2007 Elsevier
?:
Numbers
Format: N'Bvalue N = number of bits, B = base N'B is optional but recommended (default is decimal) Number
3b101 b11 8b11 8b1010_1011
# Bits
3 unsized 8 8
Base
binary binary binary binary
Decimal Equivalent
5 3 3 171
Stored
101 000011 00000011 10101011
3d6
6o42 8hAB 42
Copyright 2007 Elsevier
3
6 8 Unsized
decimal
octal hexadecimal decimal
6
34 171 42
110
100010 10101011 000101010
4-<16>
4-<17>
Synthesis:
mux2
s d0[7:0] d1[7:0]
[7:0] [7:0] [3:0] [3:0]
y[7:0]
lsbmux
mux2
s
[7:4] [7:4]
d0[3:0] d1[3:0]
y[3:0]
[7:4]
msbmux
4-<18>
Synthesis:
en a[3:0]
[3:0] [3:0] [3:0] [3:0]
y[3:0]
y_1[3:0]
Copyright 2007 Elsevier 4-<19>
Delays
module example(input a, b, c, output y); wire ab, bb, cb, n1, n2, n3; assign #1 {ab, bb, cb} = ~{a, b, c}; assign #2 n1 = ab & bb & cb; assign #2 n2 = a & bb & cb; assign #2 n3 = a & bb & c; assign #4 y = n1 | n2 | n3; endmodule
4-<20>
Delays
module example(input a, b, c, output y); wire ab, bb, cb, n1, n2, n3; assign #1 {ab, bb, cb} = ~{a, b, c}; assign #2 n1 = ab & bb & cb; assign #2 n2 = a & bb & cb; assign #2 n3 = a & bb & c; assign #4 y = n1 | n2 | n3; endmodule
4-<21>
Sequential Logic
Verilog uses certain idioms to describe latches, flip-flops and FSMs Other coding styles may simulate correctly but produce incorrect hardware
4-<22>
Always Statement
General Structure:
always @ (sensitivity list) statement;
Whenever the event in the sensitivity list occurs, the statement is executed
4-<23>
D Flip-Flop
module flop(input clk, input [3:0] d, output reg [3:0] q); always @ (posedge clk) q <= d; endmodule
// pronounced q gets d
Any signal assigned in an always statement must be declared reg. In this case q is declared as reg
Beware: A variable declared reg is not necessarily a registered output. We will show examples of this later.
Copyright 2007 Elsevier 4-<24>
Resettable D Flip-Flop
module flopr(input clk, input reset, input [3:0] d, output reg [3:0] q); // synchronous reset always @ (posedge clk) if (reset) q <= 4'b0; else q <= d; endmodule
clk d[3:0] reset
[3:0] [3:0] [3:0] [3:0]
D[3:0] R
Q[3:0]
q[3:0]
q[3:0]
4-<25>
Resettable D Flip-Flop
module flopr(input clk, input reset, input [3:0] d, output reg [3:0] q); // asynchronous reset always @ (posedge clk, posedge reset) if (reset) q <= 4'b0; else q <= d; endmodule
clk d[3:0] reset
[3:0]
[3:0]
D[3:0] R
Q[3:0]
[3:0]
[3:0]
q[3:0]
q[3:0]
4-<26>
4-<27>
Latch
module latch(input clk, input [3:0] d, output reg [3:0] q); always @ (clk, d) if (clk) q <= d; endmodule
d[3:0] clk
[3:0] [3:0]
lat
D[3:0] C Q[3:0]
[3:0] [3:0]
q[3:0]
q[3:0]
Warning: We wont use latches in this course, but you might write code that inadvertently implies a latch. So if your synthesized hardware has latches in it, this indicates an error.
Copyright 2007 Elsevier 4-<28>
Reminder: Variables assigned in an always statement must be declared as reg (even if theyre not actually registered!)
4-<29>
This hardware could be described with assign statements using fewer lines of code, so its better to use assign statements in this case.
Copyright 2007 Elsevier 4-<30>
4-<32>
y y y y y
= = = = =
// ? = dont care
4-<33>
= is a blocking assignment
Occurs in the order it appears in the file
// Good synchronizer using // nonblocking assignments module syncgood(input clk, input d, output reg q); reg n1; always @(posedge clk) begin n1 <= d; // nonblocking q <= n1; // nonblocking end endmodule // Bad synchronizer using // blocking assignments module syncbad(input clk, input d, output reg q); reg n1; always @(posedge clk) begin n1 = d; // blocking q = n1; // blocking end endmodule
4-<34>
Use always @ (*) and blocking assignments (=) to model more complicated combinational logic where the always statement is helpful. Do not make assignments to the same signal in more than one always statement or continuous assignment statement.
Copyright 2007 Elsevier 4-<35>
inputs
state
output logic
outputs
4-<36>
S2
S0
S1
FSM in Verilog
module divideby3FSM (input clk, input reset, output q); reg [1:0] state, nextstate; parameter S0 = 2'b00; parameter S1 = 2'b01; parameter S2 = 2'b10; // state register always @ (posedge clk, posedge reset) if (reset) state <= S0; else state <= nextstate; // next state logic always @ (*) case (state) S0: nextstate = S1; S1: nextstate = S2; S2: nextstate = S0; default: nextstate = S0; endcase // output logic assign q = (state == S0); endmodule
4-<38>
Parameterized Modules
2:1 mux:
module mux2 #(parameter width = 8) // name and default value (input [width-1:0] d0, d1, input s, output [width-1:0] y); assign y = s ? d1 : d0; endmodule
Testbenches HDL code written to test another HDL module, the device under test (dut), also called the unit under test (uut) Not synthesizeable Types of testbenches:
Simple testbench Self-checking testbench Self-checking testbench with testvectors
4-<40>
Example
Write Verilog code to implement the following function in hardware: y = bc + ab Name the module sillyfunction
4-<41>
Example
Write Verilog code to implement the following function in hardware: y = bc + ab Name the module sillyfunction Verilog
module sillyfunction(input a, b, c, output y); assign y = ~b & ~c | a & ~b; endmodule
4-<42>
Simple Testbench
module testbench1(); reg a, b, c; wire y; // instantiate device under test sillyfunction dut(a, b, c, y); // apply inputs one at a time initial begin a = 0; b = 0; c = 0; #10; c = 1; #10; b = 1; c = 0; #10; c = 1; #10; a = 1; b = 0; c = 0; #10; c = 1; #10; b = 1; c = 0; #10; c = 1; #10; end endmodule
4-<43>
Self-checking Testbench
module testbench2(); reg a, b, c; wire y; // instantiate device under test sillyfunction dut(a, b, c, y); // apply inputs one at a time // checking results initial begin a = 0; b = 0; c = 0; #10; if (y !== 1) $display("000 failed."); c = 1; #10; if (y !== 0) $display("001 failed."); b = 1; c = 0; #10; if (y !== 0) $display("010 failed."); c = 1; #10; if (y !== 0) $display("011 failed."); a = 1; b = 0; c = 0; #10; if (y !== 1) $display("100 failed."); c = 1; #10; if (y !== 1) $display("101 failed."); b = 1; c = 0; #10; if (y !== 0) $display("110 failed."); c = 1; #10; if (y !== 0) $display("111 failed."); end endmodule
4-<44>
Testbench with Testvectors Write testvector file: inputs and expected outputs Testbench:
1. 2. 3. 4. Generate clock for assigning inputs, reading outputs Read testvectors file into array Assign inputs, expected outputs Compare outputs to expected outputs and report errors
4-<45>
Assign Inputs
The testbench clock may also be used as the clock source for synchronous sequential circuits.
4-<46>
4-<47>
4-<49>
// apply test vectors on rising edge of clk always @(posedge clk) begin #1; {a, b, c, yexpected} = testvectors[vectornum]; end
4-<50>
4-<51>
4-<52>