0% found this document useful (0 votes)
75 views

ET5080E Digital Design Using Verilog HDL: Fall 21

This document discusses digital design using Verilog HDL. It covers topics like counters, shifters, rotators, parameters, proper sequential (SM) coding, and random miscellaneous information. The document provides examples of coding counters, rotators, shifters, and state machines in Verilog. It also briefly introduces parameters and emphasizes guidelines for good sequential logic coding.

Uploaded by

ifire
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
75 views

ET5080E Digital Design Using Verilog HDL: Fall 21

This document discusses digital design using Verilog HDL. It covers topics like counters, shifters, rotators, parameters, proper sequential (SM) coding, and random miscellaneous information. The document provides examples of coding counters, rotators, shifters, and state machines in Verilog. It also briefly introduces parameters and emphasizes guidelines for good sequential logic coding.

Uploaded by

ifire
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 35

ET5080E

Digital Design Using Verilog


HDL
Fall ‘21
Counters are Common
Shifters/Rotators
Parameters
Proper SM Coding
Random Misc Stuff
Administrative Matters
 Readings
• Cummings paramdesign paper for hdlcon (posted on class website)

2
What Have We Learned?
1) Sequential elements (flops & latches) should be inferred
using non-blocking “<=“ assignments

2) Combinational logic should be inferred using blocking “=“


statements.

3) Blocking and non-Blocking statements should not be mixed


in the same always block.

4) Plus 5 other guidelines of good coding outlined in the


Cummings SNUG paper.

3
Engineers are paid to think,
Pharmacists are paid to follow rules
 Counters are commonly needed blocks.
rst_n
Increment logic & mux are
combinational  blocking
0 R
+1 cnt[7:0] Flop is seqential.  non-blocking
comb 1

en clk

8-bit counter with reset & enable

4
Pill Counter
module pill_cnt(clk,rst_n,en,cnt); Nothing wrong with this code
input clk,rst_n; Just a little verbose. Use DF?
output [7:0] cnt; module pill_cnt(clk,rst_n,en,cnt);
reg [7:0] nxt_cnt,cnt; input clk,rst_n;
output [7:0] cnt;
always @(posedge clk, negedge rst_n)
if (!rst_n) reg [7:0] cnt;
cnt <= 8’h00; wire [7:0] nxt_cnt;
else
cnt <= nxt_cnt; always @(posedge clk, negedge rst_n)
if (!rst_n)
always @(en or cnt) cnt <= 8’h00;
if (en) else
nxt_cnt = cnt + 1; // combinational cnt <= nxt_cnt;
else
nxt_cnt = cnt; // so use blocking assign nxt_cnt (en) ? cnt+1 : cnt;

endmodule endmodule
5
I.Q. Counter (the rebel engineer)
module iq_cnt(clk,rst_n,en,cnt); What 2 rules are broken
here?
input clk,rst_n;
output [7:0] cnt; 1) Code infers
reg [7:0] cnt; combinational using a
non-blocking
always @(posedge clk or negedge rst_n) assignment
if (!rst_n)
cnt <= 8’h00; 2) We are using an if
else if (en) statement without a
cnt <= cnt + 1; // combinational pure else clause
endmodule

Is this OK?

6
Ring Counter
module ring_counter (count, enable, clock, reset);
output reg [7: 0] count;
input enable, reset, clock;

always @ (posedge clock or posedge reset)


if (reset == 1'b1) count <= 8'b0000_0001;
else if (enable == 1’b1) begin
case (count)
8’b0000_0001: count <= 8’b0000_0010;
8’b0000_0010: count <= 8’b0000_0100;

8’b1000_0000: count <= 8’b0000_0001;
default: count <= 8’bxxxx_xxxx;
endcase
end
endmodule

7
Ring Counter (a better way)
module ring_counter (count, enable, clock, reset_n);
output reg [7: 0] count;
input enable, reset, clock;

always @ (posedge clock or negedge reset_n)


if (!reset_n) count <= 8'b0000_0001;
else if (enable == 1'b1) count <= {count[6:0], count[7]};
endmodule

 Use vector concatenation in this example to be more explicit


about desired behavior/implementation
• More concise
• Does not rely on synthesis tool to be smart and reduce your logic for
you.
8
Rotator
module rotator (Data_out, Data_in, load, clk, rst_n);
output reg [7: 0] Data_out;
input [7: 0] Data_in;
input load, clk, rst_n;

always @ (posedge clk or negedge rst_n)


if (!rst_n) Data_out <= 8'b0;
else if (load) Data_out <= Data_in;
else if (en) Data_out <= {Data_out[6: 0], Data_out[7]};
else Data_out <= Data_out
endmodule

• Think what this code implies…How will it synthesize?


• What would such a block be used for?

9
Shifter
always @ (posedge clk) begin
if (rst) Data_Out <= 0;
else case (select[1:0])
2’b00: Data_Out <= Data_Out; // Hold
2’b01: Data_Out <= {Data_Out[3], Data_Out[3:1]}; // ‚ by 2
2’b10: Data_Out <= {Data_Out[2:0], 1’b0}; // X by 2
2’b11: Data_Out <= Data_In; // Parallel Load
endcase
end
endmodule

• Think what this code implies…How will it synthesize?


• Is the reset synchronous or asynchronous? • There is no default to the case, is
this bad?
• Why was the MSB replicated on the ‚ by 2
10
Aside (a quick intro to parameters)
 parameter  like a local `define
• Defined locally to the module
• Can be overridden (passed a value in an instantiation)
• There is another method called defparam (don’t ever use
it) that can override them

 localparam  even more local than parameter


• Can’t be passed a value
• defparam does not modify
• Only available in Verilog 2001
11
Aside (a quick intro to parameters)
module adder(a,b,cin,sum,cout);

parameter WIDTH = 8; // default is 8


module alu(src1,src2,dst,cin,cout);
input [WIDTH-1:0] a,b; input [15:0] src1,src2;
input cin; …
output [WIDTH-1:0] sum; //////////////////////////////////
output cout; // Instantiate 16-bit adder //
////////////////////////////////
assign {cout,sum} = a + b + cin
adder #(16) add1(.a(src1),.b(src2),
endmodule .cin(cin),.cout(cout),
.sum(dst));
Instantiation of module can
override a parameter. …
endmodule

12
Aside (a quick intro to parameters)
 Examples:
parameter Clk2q = 1.5, parameter IDLE = 2’b00;
Tsu = 1, parameter CONV = 2’b01;
Thd = 0; parameter ACCM = 2’b10;

module register2001 #(parameter SIZE=8)


(output reg [SIZE-1:0] q, input [SIZE-1:0] d,
• Read Cummings
input clk, rst_n);
paramdesign paper
always @(posedge clk, negedge rst_n) for hdlcon posted on
if (!rst_n) q <= 0; class website
else q <= d;
Verilog 2001 allows
definition in module header
endmodule
13
State Machines
State Machines:
• Next State and output
logic are combinational
blocks, which have
outputs dependent on the
current state.

• The current state is, of


course, stored by a FF.

• What is the best way to code State Machines?:


 Best to separate combinational (blocking) from sequential (non-blocking)
 Output logic and state transition logic can be coded in same always block
since they have the same inputs
 Output logic and state transition logic are ideally suited for a case statement
14
State Diagrams
b=0 / Y=1
Inputs, a and b are 0,
a=0 / Y=1
unless specified otherwise
a=0 a=1 / Y=1
Outputs Y and Z are 0,
unless specified otherwise.
S0 a = 1/ S1
• Is this Mealy or Moore?
Z=1

rst = 1 b = 1/ Z = 1, Y=1

Lets code this


S2

15
always @ (state,a,b)
SM Coding case (state)
S0 : if (a) begin
module fsm(clk,rst,a,b,Y,Z); nxt_state = S1;
Z = 1; end
input clk,rst,a,b;
else
output Y,Z;
What problems do nxt_state = S0;
parameter S0 = 2’b00, we have here? S1 : begin
S1 = 2’b01, Y=1;
S2 = 2’b10; if (b) begin
nxt_state = S2;
reg [1:0] state,nxt_state;
Z=1; end
always @(posedge clk, posedge rst) else
if (rst) nxt_state = S1;
state <= S0; end
else S2 : nxt_state = S0;
state <= nxt_state; endcase
endmodule
16
SM Coding (2nd try of combinational)
always @ (state,a,b) S1 : begin
nxt_state = S0; // default to reset Y=1;
Z = 0; // default outputs if (b) begin
Y = 0; // to avoid latches nxt_state = S2;
Z=1; end
case (state) else nxt_state = S1;
S0 : if (a) begin end
nxt_state = S1; default : nxt_state = S0;
Z = 1; endcase
end endmodule

Defaulting of assignments and having a default


to the case is highly recommended!

17
SM Coding Guidlines
1) Keep state assignment in separate always block using non-
blocking “<=“ assignment
2) Code state transition logic and output logic together in a
always block using blocking assignments
3) Assign default values to all outputs, and the nxt_state
registers. This helps avoid unintended latches
4) Remember to have a default to the case statement.
• Default should be (if possible) a state that transitions to the same state
as reset would take the SM to.
• Avoids latches
• Makes design more robust to spurious electrical/cosmic events.

18
SM Interacting with SM
• A very common case is a state that needs to be held for a certain time.
The state machine in this case may interact with a timer (counter).

BUS
Cycle

IDLE ChrgPmp clr_tm


Enable

tm_eq_3ms/
wrt_done R tm_eq_3ms
+1 0
tm_eq_3ms/inc_tm comb 1

Multiple levels of interaction between SM’s inc_tm clk


19
EEPROM Write SM Example [1]
module eeprom_sm(clk,por_n,wrt_eep, //// implement 3ms timer below ////
wrt_data,eep_r_w_n,eep_cs_n, always @(posedge clk or
eep_bus,chrg_pmp_en,wrt_done); posedge clr_tm)
if (clr_tm) tm <= 14’h0000;
parameter IDLE = 2’b00, else if (inc_tm) tm <= tm+1;
BUS = 2’b01,
CHRG = 2’b10; //// @4MHZ cnt of 2EE0 => 3ms ////
assign tm_eq_3ms = (tm==14’h2EE0) ?
input clk,por_n,wrt_eep; 1’b1 : 1’b0;
input [11:0] wrt_data; // data to write
output eep_r_w_n,eep_cs_n; //// implement state register below ////
output chrg_pmp_en; // hold for 3ms always @(posedge clk or
inout [11:0] eep_bus; negedge por_n)
if (!rst_n) state <= IDLE;
reg [13:0] tm; // 3ms => 14-bit timer else state <= nxtState;
reg clr_tm,inc_tm,bus_wrt;
reg [1:0] state,nxtState;

20
EEPROM Write SM Example [2]
default : begin // is CHRG
//// state transition logic & ////
inc_tm = 1;
//// output logic ////
chrg_pmp_en=1;
always @(state,wrt_eep,tm_eq_3ms)
if (tm_eq_3ms)
begin
begin
nxtState = IDLE; // default all
wrt_done = 1;
bus_wrt = 0; // to avoid
nxtState = IDLE;
clr_tm = 0; // unintended
end
inc_tm = 0; // latches
else nxtState = CHRG;
chrg_pmp_en = 0;
end
case (state) endcase
IDLE : if (wrt_eep) end
nxtState = BUS;
BUS : begin assign eep_r_w_n = ~bus_wrt;
clr_tm = 1; assign eep_cs_n = ~bus_wrt;
bus_wrt = 1; assign eep_bus = (bus_wrt) ?
nxtState = CHRG; wrt_data : 12’bzzz;
end endmodule
21
USART (RS232) Example
LSB MSB

Start
Bit
(fixed period low) Payload goes out must have at least 1
(like 57600 baud) little endian period of high at end
(stop bit)
Assume we have a 4MHz clock running our digital system

We want to make a RS232 transmitter with a baud rate of 57,600

How many clock cycles do we hold each bit?

4MHz
Cycles   69 69 = 7’b1000101
57600 baud
22
USART Example
module usart_tx(clk,rst_n,strt_tx,tx_data,tx_done,TX);

input clk, rst_n, strt_tx; // start_tx comes from Master SM


input [7:0] tx_data; // data to transmit
output TX; // TX is the serial line
output tx_done; // tx_done asserted back to Master SM
.
.
.
endmodule;

1) Go over HW3 problem statement

23
Random Misc Topics

24
Mux With case
module Mux_4_32_(output [31:0] mux_out, input [31:0] data_3,
data_2, data_1, data_0, input [1:0] select, input enable);
reg [31: 0] mux_int;
// choose between the four inputs
always @ ( data_3 or data_2 or data_1 or data_0 or select)
case (select) (* synthesis parallel_case *)
2’b00: mux_int = data_0; Synthesis directive:
2’b01: mux_int = data_1; Lets the synthesis tool know
2’b10: mux_int = data_2; to use parallel (mux) scheme
2’b11: mux_int = data_3; when synthesizing instead of
endcase priority encoding. Called an
// add the enable functionality attribute in the IEEE spec
assign mux_out = enable ? mux_int : 32'bz;
endmodule

 Case statement implies priority unless use parallel_case pragma


25
Encoder With case
module encoder (output reg [2:0] Code, input [7:0] Data);
always @ (Data)
// encode the data
case (Data)
8'b00000001 : Code = 3’d0;
8'b00000010 : Code = 3’d1;
8'b00000100 : Code = 3’d2;
8'b00001000 : Code = 3’d3;
8'b00010000 : Code = 3’d4;
8'b00100000 : Code = 3’d5;
8'b01000000 : Code = 3’d6;
8'b10000000 : Code = 3’d7;
default : Code = 3‘bxxx; // invalid, so don’t care
endcase
endmodule

26
Priority Encoder With casex
module priority_encoder (output reg [2:0] Code, output valid_data,
input [7:0] Data);

assign valid_data = |Data; // "reduction or" operator


always @ (Data)
// encode the data
casex (Data)
8'b1xxxxxxx : Code = 7;
8'b01xxxxxx : Code = 6;
8'b001xxxxx : Code = 5;
8'b0001xxxx : Code = 4;
8'b00001xxx : Code = 3;
8'b000001xx : Code = 2;
8'b0000001x : Code = 1;
8'b00000001 : Code = 0;
default : Code = 3'bxxx; // should be at least one 1, don’t care
endcase
endmodule

27
Seven Segment Display
module Seven_Seg_Display (Display, BCD, Blanking);
output reg [6: 0] Display; // abc_defg
input [3: 0] BCD;
input Blanking;
parameter BLANK = 7'b111_1111; // active low
parameter ZERO = 7'b000_0001; // h01
parameter ONE = 7'b100_1111; // h4f
parameter TWO = 7'b001_0010; // h12
parameter THREE = 7'b000_0110; // h06
parameter FOUR = 7'b100_1100; // h4c a
parameter FIVE = 7'b010_0100; // h24 f b
parameter SIX = 7'b010_0000; // h20 g
parameter SEVEN = 7'b000_1111; // h0f c
e
parameter EIGHT = 7'b000_0000; // h00
parameter NINE = 7'b000_0100; // h04 d

Defined constants – can make code more understandable!


28
Seven Segment Display [2]
always @ (BCD or Blanking)
if (Blanking) Display = BLANK;
else
case (BCD)
4’d0: Display = ZERO;
4’d1: Display = ONE; Using the
4’d2: Display = TWO; defined
4’d3: Display = THREE; constants!
4’d4: Display = FOUR;
4’d5: Display = FIVE;
4’d6: Display = SIX;
4’d7: Display = SEVEN;
4’d8: Display = EIGHT;
4’d9: Display = NINE;
default: Display = BLANK;
endcase
endmodule

29
Inter vs Intra Statement Delays
 Inter-assignment delays block both evaluation and assignment
• #4 c = d;
• #8 e = f;

 Intra-assignment delays block assignment but not evaluation


• c = #4 d;
• e = #8 f;
 Blocking statement is still blocking though, so evaluation of
next statements RHS still does not occur until after the
assignment of the previous expression LHS.
• What?? How is it any different then? Your confusing me!
30
Inter vs Intra Statement Delays
(Blocking Statements)
module inter(); module intra();
integer a,b; integer a,b;
initial begin initial begin
Compare these two
a=3; a=3;
modules
#6 b = a + a; b = #6 a + a;
#4 a = b + a; a = #4 b + a;
end end
endmodule endmodule

Yaa, Like I said, they Time Event


Time Event
are the same!
0 a=3 0 a=3

6 b=6 Or are they? 6 b=6

10 a=9 10 a=9

31
Intra Statement Delays (Blocking
Statements)
module inter2(); module inter2();
integer a,b; integer a,b;
initial begin Time Event initial begin Time Eval Assign
a=3; a=3; Event Event
#6 b = a + a; 0 a=3 b = #6 a + a; 0 nxt_b= 6 a=3
#4 a = b + a; a = #4 b + a;
end 3 a=1 end 3 -- a=1

initial begin 6 b=2 initial begin 6 nxt_a=7 b=6


#3 a=1; #3 a=1;
#5 b=3; 8 b=3 #5 b=3; 8 -- b=3
end end
10 a=4 10 -- a=7
endmodule endmodule

32
Non-Blocking: Inter-Assignment Delay
 Delays both the evaluation and the update

always @(posedge clk) begin


b <= a + a; Time Event
# 5 c <= b + a;
0 clk pos edge
# 2 d <= c + a;
end 0 b=6

5 c=9
initial begin
a = 3; b = 2; c = 1; 7 c=12
end

33
Non-Blocking: Inter-Assignment Delay
 Delays both the evaluation and the update

always @(posedge clk) begin


b <= a + a; Time Event
c <= #5 b + a;
0 clk pos edge
d <= #2 c + a;
end 0 b=6

2 d=4
initial begin
a = 3; b = 2; c = 1; 5 c=5
end

This is more like modeling the Clk2Q delay of a Flop


(it captures on rising edge, but has a delay till output)

34
Intra-Assignment Review
module bnb;
reg a, b, c, d, e, f;
Note: In testbenches I
initial begin // blocking assignments
mainly find blocking inter-
a = #10 1; // a will be assigned 1 at time 10 assignment delays to be the
b = #2 0; // b will be assigned 0 at time 12 most useful. Delays really
c = #4 1; // c will be assigned 1 at time 16 not used outside of
end testbenches that much
during the design process.
initial begin // non-blocking assignments
d <= #10 1; // d will be assigned 1 at time 10
e <= #2 0; // e will be assigned 0 at time 2
f <= #4 1; // f will be assigned 1 at time 4
end
endmodule

35

You might also like