So you think you want to write Verilog?
Post on 08-Jan-2016
35 Views
Preview:
DESCRIPTION
Transcript
Verilog - 1
So you think you want to write Verilog?
Verilog is a crufty language Useful, but full of historical baggage The first real HDL, followed by VHDL
If you follow the rules closely, you will be OK Most companies are ruthless about how to write Verilog Lint used to catch designers who stray
The rules are mostly like Abstract Verilog Good programs look like translated Abstract Verilog
Verilog - 2
Simulation vs. Synthesis
Early HDLs supported execution/simulation, not synthesis C/algol, with parallel processes
Synthesis constrains the language current HDLs have a “synthesizeable subset”
HDLdescription
“execution”
functionalvalidation
synthesis circuit
simulation
functional/timingvalidation
Verilog - 3
Simulation
Synthesis and Simulation
Verilog/VHDL support both
Abstract Verilog provides a “synthesizable subset” e.g. no “initial” blocks
Provide the circuit environment using Verilog simulation code “Test fixture” Arbitrary Verilog code
read files, print values, control simulation Test fixture is the specification
used to decide if external circuit behavior is correct
Test Fixture(Specification)
Circuit Description(Synthesizeable)
Verilog - 4
Verilog
Supports structural and behavioral descriptions
Structural explicit structure of the circuit e.g., each logic gate instantiated and connected to others we will use schematics to describe structure
much easier to understand
Behavioral program describes input/output behavior of circuit many structural implementations could have same behavior e.g., different implementation of one Boolean function we will use Verilog for the “primitive” components
what is “primitive” is a matter of style
Verilog - 5
Verilog Variables
wire variable used to connect components together inputs and outputs are wires
outputs can be declared as regs
reg variable that saves a value as part of a behavioral description usually corresponds to a wire in the circuit is NOT a register in the circuit
The rule: Declare a variable as a reg if it is assigned (=) in an always
block assign doesn’t count (confusing isn’t it?)
Verilog - 6
assign A = X | (Y & ~Z);
assign B[3:0] = 4'b01XX;
assign C[15:0] = 4'h00ff;
assign #3 {Cout, S[3:0]} = A[3:0] + B[3:0] + Cin;
use of arithmetic operator
multiple assignment (concatenation)
delay of performing computation, only used by simulator, not synthesis
use of Boolean operators(~ for bit-wise, ! for logical negation)
bits can take on four values(0, 1, X, Z)
variables can be n-bits wide(MSB:LSB)
Verilog Continuous Assignment
Assignment is continuously evaluated
assign corresponds to COMB foo = expression;
target is not a reg variable
Verilog - 7
module Compare1 (A, B, Equal, Alarger, Blarger); input A, B; output Equal, Alarger, Blarger;
assign Equal = (A & B) | (~A & ~B); assign Alarger = (A & ~B); assign Blarger = (~A & B);endmodule
Comparator Example
Verilog - 8
// Make a 4-bit comparator from 4 1-bit comparators
module Compare4(A4, B4, Equal, Alarger, Blarger); input [3:0] A4, B4; output Equal, Alarger, Blarger; wire e0, e1, e2, e3, Al0, Al1, Al2, Al3, B10, Bl1, Bl2, Bl3;
Compare1 cp0(A4[0], B4[0], e0, Al0, Bl0); Compare1 cp1(A4[1], B4[1], e1, Al1, Bl1); Compare1 cp2(A4[2], B4[2], e2, Al2, Bl2); Compare1 cp3(A4[3], B4[3], e3, Al3, Bl3);
assign Equal = (e0 & e1 & e2 & e3); assign Alarger = (Al3 | (Al2 & e3) | (Al1 & e3 & e2) | (Al0 & e3 & e2 & e1)); assign Blarger = (~Alarger & ~Equal);endmodule
Comparator Example – Structural Description
Verilog - 9
module and_gate (out, in1, in2); input in1, in2; output out; reg out;
always @(in1 or in2) begin out = in1 & in2; endendmodule
Simple Behavioral Model - the always block
always block always waiting for a change to a trigger signal then executes the body
Not a real register!!A Verilog registerNeeded because of assignment in always blockspecifies when block is
executed ie. triggered by which signals
Verilog - 10
always Block
A procedure that describes the function of a circuit Can contain many statements including if, for, while, case Statements in the always block are executed sequentially
(Continuous assignments are executed in parallel) The entire block is executed at once The final result describes the function of the circuit for current
set of inputs intermediate assignments don’t matter, only the final result
begin/end used to group statements This is not C programming!!!!!!!
It is a description of a combinational function Describes what the function computes, not how it computes it
Synthesis tools determine the how for you for better or worse
Verilog - 11
“Complete” Assignments
If an always block executes, and a variable is not assigned variable keeps its old value NOT combinational logic latch is inserted This is not what you want
Any variable assigned in an always block should be assigned for anyexecution of the block
Defaults are usually a good idea
Verilog - 12
module and_gate (out, in1, in2); input in1, in2; output out; reg out;
always @(in1) begin out = in1 & in2; endendmodule
Triggers
Rule: always block input signals must be in trigger list Emacs verilog mode can do this automatically for you Use Verilog 2001 always @(*) - includes all signals
Leaving out an input trigger usually results in a sequential circuit
Example: The output of this “and” gate depends on the input history
Verilog - 13
Verilog casex
Like case, but cases can include ‘X’ X bits not used when evaluating the cases
Verilog - 14
casex Example
// Priority encodermodule encode (A, valid, Y);input [7:0] A; // 8-bit input vectoroutput [2:0] Y; // 3-bit encoded outputoutput valid; // Asserted when an input is not all 0’sreg [2:0] Y; // target of assignmentreg valid;
always @(A) begin valid = 1; casex (A) 8’bXXXXXXX1: Y = 0; 8’bXXXXXX10: Y = 1; 8’bXXXXX100: Y = 2; 8’bXXXX1000: Y = 3; 8’bXXX10000: Y = 4; 8’bXX100000: Y = 5; 8’bX1000000: Y = 6; 8’b10000000: Y = 7; default: begin valid = 0; Y = 3’bX; // Don’t care when input is all 0’s end endcase endendmodule
Verilog - 15
Verilog for
for is similar to C for statement is executed at compile time
result is all that matters, not how result is calculated
// simple encodermodule encode (A, Y);input [7:0] A; // 8-bit input vectoroutput [2:0] Y; // 3-bit encoded outputreg [2:0] Y; // target of assignment
integer i; // Temporary variables for program onlyreg [7:0] test;
always @(A) begin test = 8b’00000001; Y = 3’bX; for (i = 0; i < 8; i = i + 1) begin if (A == test) Y = i; test = test << 1; end endendmodule
Verilog - 16
module life (neighbors, self, out); input self; input [7:0] neighbors; output out; reg out; integer count; integer i;
always @(neighbors or self) begin count = 0; for (i = 0; i<8; i = i+1) count = count + neighbors[i]; out = 0; out = out | (count == 3); out = out | ((self == 1) & (count == 2)); endendmodule
Verilog for
always block is executed instantaneously,
if there are no delays only the final result is
used
integers here are temporary compiler
variables
for statement is executed at compile time result is all that matters, not how result is calculated
Combinational block that computes Conway’s Game of Life rule
Verilog - 17
Verilog while/repeat/forever
while (expression) statement execute statement while expression is true
repeat (expression) statement execute statement a fixed number of times
forever statement execute statement forever
Verilog - 18
full-case and parallel-case
// synthesis parallel_case tells compiler that ordering of cases is not important that is, cases do not overlap
e. g. state machine - can’t be in multiple states gives cheaper implementation
// synthesis full_case tells compiler that cases left out can be treated as don’t cares avoids incomplete specification and resulting latches
Verilog - 19
Registers
Registers are created implicitly
Any assignment inside a @(posedge CLK) block creates a register
Assignments inside a @(posedge CLK) block are Registered assignments
Assignments inside other always blocks are Combinational assignments
This means your program is split in two parts!!always @(posedge CLK) begin A = B + C
end
Verilog - 20
module reg8 (reset, CLK, D, Q);input reset;input CLK;input [7:0] D;output [7:0] Q;reg [7:0] Q;
always @(posedge CLK) if (reset) Q = 0; else Q = D;
endmodule // reg8
8-bit Register with Synchronous Reset
Verilog - 21
Shift Register Example
// 8-bit register can be cleared, loaded, shifted left// Retains value if no control signal is asserted
module shiftReg (CLK, clr, shift, ld, Din, SI, Dout);input CLK;input clr; // clear register input shift; // shiftinput ld; // load register from Dininput [7:0] Din; // Data input for loadinput SI; // Input bit to shift inoutput [7:0] Dout;reg [7:0] Dout;
always @(posedge CLK) begin if (clr) Dout <= 0; else if (ld) Dout <= Din; else if (shift) Dout <= { Dout[6:0], SI }; end
endmodule // shiftReg
Verilog - 22
Assignment Semantics Determined by Simulation
Here’s how simulation works:
1. One or more signals change 2. All blocks triggered by those signals “wake up”
Assign statements Always blocks with signal as trigger
3. These blocks are added to an event queue (at the appropriate delay) 4. A block is taken from the queue and time is advanced 5. The block is executed
This causes signals to change – go to step 1 No signals change – go to step 4
Note: A block can cause itself to be re-queued! Note 2: Order matters!
Verilog - 23
always @(posedge CLK)begin
temp = B;B = A;A = temp;
end
always @(posedge CLK)begin
A <= B;B <= A;
end
Blocking and Non-Blocking Assignments
Blocking assignments (Q = A) variable is assigned immediately before continuing to next
statement new variable value is used by subsequent statements
Non-blocking assignments (Q <= A) variable is assigned only after all statements already scheduled
are executed value to be assigned is computed here but saved for later
usual use: register assignment registers simultaneously take their new values
after the clock tick Example: swap
Verilog - 24
Swap (continued)
The real problem is parallel blocks one of the blocks is executed first previous value of variable is lost
Use delayed assignment to fix this both blocks are scheduled by posedge CLK
always @(posedge CLK)begin
A = B;end
always @(posedge CLK)begin
B = A;end
always @(posedge CLK)begin
A <= B;end
always @(posedge CLK)begin
B <= A;end
Verilog - 25
Non-Blocking Assignment
Non-blocking assignment is also known as an RTL assignment if used in an always block triggered by a clock edge mimic register-transfer-level semantics – all flip-flops change
together
My rule: ALWAYS use <= in sequential (posedge clk) blocks// this implements 3 parallel flip-flopsalways @(posedge clk) begin B = A; C = B; D = C; end
// this implements a shift registeralways @(posedge clk) begin B <= A; C <= B; D <= C; end
// this implements a shift registeralways @(posedge clk) begin {D, C, B} = {C, B, A}; end
Verilog - 26
Finite State Machines
Recall FSM model
Recommended FSM implementation style Implement combinational logic using a one always block Implement an explicit state register using a second always
block
inputsMoore outputs
Mealy outputs
next state
current state
combinationallogic
Verilog - 27
// State assignmentparameter zero = 0, one1 = 1, two1s = 2;
module reduce (clk, reset, in, out); input clk, reset, in; output out; reg out; reg [1:0] state; // state register reg [1:0] next_state;
// Implement the state register always @(posedge clk) if (reset) state = zero; else state = next_state;
Verilog FSM - Reduce 1s example
Change the first 1 to 0 in each string of 1’s Example Moore machine implemenation
1
0
0
0
11
zero[0]
one1[0]
two1s[1]
Verilog - 28
6
always @(*)out = 0; // defaultsnext_state = zero;
case (state) zero: begin // last input was a zero if (in) next_state = one1; end
one1: begin // we've seen one 1 if (in) next_state = two1s;
end
two1s: begin // we've seen at least 2 ones out = 1; if (in) next_state = two1s; end
// Don’t need case default because of default assignmentsendcaseendmodule
crucial to include all signals that are input to state and output equations
Moore Verilog FSM (cont’d)
Verilog - 29
7
module reduce (clk, reset, in, out); input clk, reset, in; output out; reg out; reg state; // state register reg next_state; parameter zero = 0, one = 1;
always @(posedge clk) if (reset) state = zero; else state = next_state;
always @(in or state) out = 0; next_state = zero; case (state) zero: begin // last input was a zero if (in) next_state = one; end one: // we've seen one 1 if (in) begin next_state = one; out = 1; end endcaseendmodule
Mealy Verilog FSM for Reduce-1s example
1/00/0
0/0
1/1
zero[0]
one1[0]
Verilog - 30
Restricted FSM Implementation Style
Mealy machine requires two always blocks register needs posedge CLK block input to output needs combinational block
Moore machine can be done with one always block e.g. simple counter Not a good idea for general FSMs
Can be very confusing (see example)
Moore outputs Share with state register, use suitable state encoding
Verilog - 31
module reduce (clk, reset, in, out); input clk, reset, in; output out; reg out; reg [1:0] state; // state register parameter zero = 0, one1 = 1, two1s = 2;
Single-always Moore Machine (Not Recommended!)
1
0
0
0
11
zero[0]
one1[0]
two1s[1]
Verilog - 32
6
always @(posedge clk) case (state) zero: begin
out = 0; if (in) state = one1; else state = zero; end
one1: if (in) begin
state = two1s; out = 1;
end else begin state = zero;
out = 0; end
two1s: if (in) begin
state = two1s; out = 1;
end else begin state = zero;
out = 0; end default: begin
state = zero;out = 0;
end endcaseendmodule
This is confusing: theoutput does not changeuntil the next clock cycle
Single-always Moore Machine (Not Recommended!)
All outputs are registered
Verilog - 33
Side-by-side Comparison
COMB TRS; REGISTER Fo=0, Vo=0, Ho=0; REGISTER [2:0] state = INIT;
ALWAYS TRS = { YCrCbPipe3, YCrCbPipe2, YCrCbPipe1 } == 'hFF_00_00; if (TRS) begin Fo <-- YCrCbPipe0[6]; Vo <-- YCrCbPipe0[5]; end // Default output values YCrCb_out = 0; case (state) INIT: begin if (TRS) begin if (~ YCrCbPipe0[4]) state <-- INLINE; else state <-- NOTINLINE; end end INLINE: begin YCrCb_out = YCrCbPipe5; Ho <-- 0; if (TRS & YCrCbPipe0[4]) state <-- NOTINLINE; end NOTINLINE: begin Ho <-- 1; if (TRS & ~YCrCbPipe0[4]) state <-- INLINE3; end endcase // case(state) end // ALWAYS begin
wire TRS; reg Fo, Vo, Ho; reg [2:0] state, next_state; reg [7:0] YCrCb_out;
assign TRS = { YCrCbPipe3, YCrCbPipe2, YCrCbPipe1 } == 'hFF_00_00;
always @(posedge clk) begin if (reset) begin state <= INIT; Fo <= 0; Vo <= 0; Ho <= 0; end else begin state <= next_state; if (TRS) begin Fo <= YCrCbPipe0[6]; Vo <= YCrCbPipe0[5]; end if (state == INLINE) begin Ho <= 0; end else if (state == NOTINLINE) begin Ho <= 1; end end end
always @(*) begin YCrCb_out = 0; case (state) INIT: begin if (TRS) begin if (~ YCrCbPipe0[4]) next_state = INLINE; else next_state = NOTINLINE; end end INLINE: begin YCrCb_out = YCrCbPipe5; if (TRS & YCrCbPipe0[4]) next_state = NOTINLINE; end NOTINLINE: begin if (TRS & ~YCrCbPipe0[4]) next_state = INLINE3; end endcase // case(state) end // ALWAYS begin
Verilog - 34
How is Abstract Verilog Implemented?
COMB signals
Construct Implementation
COMB [3:0] c;
COMB overflow = count > 15;
reg [3:0] c;
wire overflow = count > 15;
Verilog - 35
Construct Implementation
REGISTER [3:0] r = init;
ALWAYS begin
r <-- foo;
c = bar;
end
reg [3:0] r, next_r;always @(posedge clk) begin if (reset) begin r <= init; end else begin r <= next_r; endend
always @(*) begin next_r = r; c = ‘bX;
next_r = foo;
c = bar;
end
REGISTERs
Verilog - 36
Memories
Construct Implementation
MEMORY [7:0] mem [0:127];
COMB [7:0] bar;
ALWAYS begin
mem_data = mem[i];
mem[j] <-- bar;
end
reg [7:0] mem[0:127] ;reg [clogb2(127+1)-1:0] mem_wraddr, mem_rdaddr;reg [7:0] mem_wrdata;wire [7:0] mem_data;reg mem_we;always @(posedge clk) begin if (mem_we) begin mem[mem_wraddr] <= mem_wrdata; endendassign mem_data = mem[mem_rdaddr]; reg [7:0] bar; always @(*) begin //initialize memory variables mem_we = 0; mem_wrdata = 'bX; mem_rdaddr = 'bX; mem_wraddr = 'bX; begin begin mem_rdaddr = i; end begin mem_we = 1; mem_wraddr = j; mem_wrdata = bar; end endend
Verilog - 37
Non-Synthesizable Constructs
Delays are used for simulation only Delays are useful for modeling time behavior of circuit Synthesis ignores delay numbers If your simulation relies on delays, your synthesized circuit will
probably not work
#10 inserts a delay of 10 time units in the simulation
module and_gate (out, in1, in2); input in1, in2; output out;
assign #10 out = in1 & in2;
endmodule
Verilog - 38
assign #5 c = a | b;
assign #4 {Cout, S} = Cin + A + B;
always @(A or B or Cin)#4 S = A + B + Cin;#2 Cout = (A & B) | (B & Cin) | (A & Cin);
assign #3 zero = (sum == 0) ? 1 : 0;
always @(sum)if (sum == 0)
#6 zero = 1;else
#3 zero = 0;
Verilog Propagation Delay
May write things differently for finer control of delays
Verilog - 39
Initial Blocks
Like always blocks execute once at the very beginning of simulation not synthesizeable
use reset instead
Verilog - 40
Tri-State Buffers
‘Z’ value is the tri-stated value
This example implements tri-state drivers driving BusOut
module tstate (EnA, EnB, BusA, BusB, BusOut); input EnA, EnB; input [7:0] BusA, BusB; output [7:0] BusOut;
assign BusOut = EnA ? BusA : 8’bZ; assign BusOut = EnB ? BusB : 8’bZ;endmodule
Verilog - 41
Test Fixtures
Provides clock
Provides test vectors/checks results test vectors and results are precomputed usually read vectors from file
Models system environment Complex program that simulates external environment
Test fixture can all the language features initial, delays, read/write files, etc.
Simulation
Test Fixture(Specification)
Circuit Description(Synthesizeable)
Verilog - 42
ClockGenerator
module clockGenerator (CLK); output CLK; reg CLK;
parameter period = 10; // 10ns clock period by defaultparameter number = 1000000; // 1000000 clock cycles by default
integer i;
initial beginCLK = 0;reset = 1;#(period+1);for (i = 0; i != number; i = i + 1) begin
CLK = 1;#(period/2) CLK = 0;if (i==1) reset = 0;#(period - period/2) ;
end$stop;
end
Stops the simulation
Verilog - 43
Example Test Fixture
module full_addr1 (A, B, Cin, S, Cout); input A, B, Cin; output S, Cout; assign {Cout, S} = A + B + Cin;endmodule
module stimulus (a, b, c); parameter delay = 10; output a, b, c; reg [2:0] cnt; initial begin cnt = 0; repeat (8) begin #delay cnt=cnt+1; end #delay $finish; end assign {c, a, b} = cnt;endmodule
module driver; // Structural Verilog connects test-fixture to full adder wire a, b, cin, sum, cout; stimulus stim (a, b, cin); full_addr1 fa1 (a, b, cin, sum, cout); initial begin $monitor ("@ time=%0d cin=%b, a=%b, b=%b, cout=%d, sum=%d", $time, cin, a, b, cout, sum); endendmodule
Verilog - 44
module stimulus (a, b); parameter delay = 10; output a, b; reg [1:0] cnt;
initial begin cnt = 0; repeat (4) begin #delay cnt = cnt + 1; end #delay $finish; end
assign {a, b} = cnt;endmodule
Simulation Driver
2-bit vector
initial block executed only once at start of simulation
directive to stop simulation
bundles two signals into a vector
Verilog - 45
module testData(clk, reset, data); input clk; output reset, data; reg [1:0] testVector [100:0]; reg reset, data; integer count;
initial begin $readmemb("data.b", testVector); count = 0; { reset, data } = testVector[0]; end
always @(posedge clk) begin count = count + 1; #1 { reset, data } = testVector[count]; endendmodule
Test Vectors
Verilog - 46
Some Hints for Debugging
Clock is carefully designed to tick at time (k*period)+1 11, 21, 31, 41, . . .
All signals are stable at (k*period) 10, 20, 30, 40, . . .
==> Look at signals just before clock ticks You can single-step you simulation this way Registers all have consistent values All next_state values are ready All outputs are ready The inputs that will be sampled at clock tick are ready
==> If you stop your simulation, let it run to the next quiet time E.g. stop at 342, run to 350.
Verilog - 47
Debugging Hints
Use the Memory view to examine memory contents
Use debugger *judiciously* to stop simulation Set breakpoint in a particular state Set breakpoint when there is a memory write/read
Examine address/data Add signal breakpoint
Stop at a specific value Stop when signal changes
Run simulation to quiet point after it stops Otherwise lots of blocks will still be waiting to execute ==> inconsistent state
Verilog - 48
Biggest Debugging Hint
Don’t use the debugger Use your head instead
The debugger is a useful tool, but should be a last resort
The best programmers I know use debuggers in very limited ways
Well-placed $display statements are useful $display(“R:%d G:%d B:%d”, red, green, blue); (not quite printf – %b, %d, %h – see Aldec online Verilog ref)
top related