Sunteți pe pagina 1din 52

ECE 551

Digital Design And Synthesis


Behavioral Verilog Examples

Overview

Behavioral Design Examples

Combinational Logic
Registers

Finite State Machine Design

Mealy
Moore
Control vs. Datapath
Implicit FSM Design

Courtesy: Mike Morrow and Eric Hoffman

Bitwidth Problems with Case

Case items must match both the value and bitwidth


wire [1:0] sel = 2;
casex (sel)
0
1
2
3
endcase

:
:
:
:

a
a
a
a

=
=
=
=

8d1;
8d2;
8d3;
8d4;

What are the size of select signal and the case


items in the example above?
Courtesy: Mike Morrow and Eric Hoffman

Tricks with Case Synthesis

Case statements inherently have priority.


The first case match will be taken.
casex (sel)
2b00 :
2b01 :
2b10 :
2b11 :
endcase

a
a
a
a

=
=
=
=

8d1;
8d2;
8d3;
8d4;

Using a mux chain is a waste in this case, because


were only describing a single 4-to-1 mux.
Fix using // synopsys parallel_case
Courtesy: Mike Morrow and Eric Hoffman

Tricks with Case Synthesis


casex (sel) //
2b00 :
2b01 :
2b10 :
2b11 :
endcase

synopsys parallel_case
a = 8d1;
a = 8d2;
a = 8d3;
a = 8d4;

Now we get a single 4-to-1 mux rather than a


chain of 3 2-to-1 muxes
Note that this only affects synthesis, not
simulation
This is not part of the Verilog standard; no
guarantees it will be honored
Courtesy: Mike Morrow and Eric Hoffman

Tricks with Case Synthesis


casex (sel) // synopsys full_case
2b00 : a = 8d1;
2b01 : a = 8d2;
endcase

Not specifying all cases normally causes latches


Adding // synopsys full_case avoids this
Same limitations as parallel_case!
Can achieve the same thing using a default case
default : a = 8bx;
Default case is part of the standard, therefore it
is superior to using full_case! Use default case.
Courtesy: Mike Morrow and Eric Hoffman

Mux With if...else ifelse


module Mux_4_32_if (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;
// add the tri-state enable
assign mux_out = enable ? mux_int : 32'bz;
// choose between the four inputs
always @ ( data_3, data_2, data_1, data_0, select)
if (select == 2d0)
mux_int = data_0;
else if (select == 2d1) mux_int = data_1;
else if (select == 2d2) mux_int = data_2;
else
mux_int = data_3;
endmodule
What happens if we forget select in the trigger list?
What happens if select is 2bxx? (Simulation? Synthesis?)
Courtesy: Mike Morrow and Eric Hoffman

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;
assign

mux_out = enable ? mux_int : 32'bz;

always @ ( data_3, data_2, data_1, data_0, select)


case (select)
// synopsys parallel_case
2d0:
mux_int = data_0;
2d1:
mux_int = data_1;
2d2:
mux_int = data_2;
2d3:
mux_int = data_3;
endcase
endmodule

Case implies priority unless use parallel_case pragma


What happens if select is 2bxx? (Simulation? Synthesis?)
Courtesy: Mike Morrow and Eric Hoffman

Mux Synthesis in System Verilog

The unique keyword acts like parallel_case


Only one case will ever be matched, so make
a parallel mux
The priority keyword forces case items to be
checked in order
This indicates that you should create a chain
of muxes

Works with both IF/ELSE and CASE


Great details on the value of these new
keywords in Supplemental Reading
Courtesy: Mike Morrow and Eric Hoffman

Encoder With ifelse ifelse


module encoder (output reg [2:0] Code, input [7:0] Data);
always @ (Data)
begin
// encode the data
if (Data == 8'b00000001) Code = 3d0;
else if (Data == 8'b00000010) Code = 3d1;
else if (Data == 8'b00000100) Code = 3d2;
else if (Data == 8'b00001000) Code = 3d3;
else if (Data == 8'b00010000) Code = 3d4;
else if (Data == 8'b00100000) Code = 3d5;
else if (Data == 8'b01000000) Code = 3d6;
else if (Data == 8'b10000000) Code = 3d7;
else Code = 3'bxxx; // invalid, so dont care
end
endmodule

Courtesy: Mike Morrow and Eric Hoffman

Encoder With case


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

Does the order of the cases matter?


Do we need the default case?
Courtesy: Mike Morrow and Eric Hoffman

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, dont care if none
endcase
endmodule

Does the order of the cases matter?


Do we need the Courtesy:
default
case?
Mike Morrow and Eric Hoffman

Seven Segment Display w/Parameters


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
a
parameter
FOUR
= 7'b100_1100;
// h4c
parameter
FIVE
= 7'b010_0100;
// h24 f
parameter
SIX
= 7'b010_0000;
// h20
g
parameter
SEVEN = 7'b000_1111;
// h0f e
parameter
EIGHT = 7'b000_0000;
// h00
parameter
NINE
= 7'b000_0100;
// h04
d

Defined constants can make code more understandable!


Courtesy: Mike Morrow and Eric Hoffman

Seven Segment Display


always @ (BCD or Blanking)
if (Blanking) Display = BLANK;
else
case (BCD)
4d0:
Display
4d1:
Display
4d2:
Display
4d3:
Display
4d4:
Display
4d5:
Display
4d6:
Display
4d7:
Display
4d8:
Display
4d9:
Display
default:
Display
endcase
endmodule

=
=
=
=
=
=
=
=
=
=
=

ZERO;
ONE;
TWO;
THREE;
FOUR;
FIVE;
SIX;
SEVEN;
EIGHT;
NINE;
BLANK;

Courtesy: Mike Morrow and Eric Hoffman

Parameters are
very useful.
Well talk about
more uses of
parameters
later.

Overview

Behavioral Design Examples

Combinational Logic
Registers

Finite State Machine Design

Mealy
Moore
Control vs. Datapath
Implicit FSM Design

Courtesy: Mike Morrow and Eric Hoffman

Ring Counter
module ring_counter (count, enable, clock, reset);
output reg [7:0] count;
input
enable, clock , reset;
always @ (posedge reset, posedge clock)
if (reset == 1'b1)
count <= 8'b0000_0001;
else if (enable == 1b1) begin
case (count)
8b0000_0001: count <= 8b0000_0010;
8b0000_0010: count <= 8b0000_0100;

8b1000_0000: count <= 8b0000_0001;


default: count <= 8bxxxx_xxxx;
endcase
end
endmodule

Is there a more elegant way of doing this?


What about the hardware implementation?
Courtesy: Mike Morrow and Eric Hoffman

Ring Counter
module ring_counter (count, enable, clock, reset);
output reg [7:0] count;
input
enable, reset, clock;
always @ (posedge reset or posedge clock)
if (reset == 1'b1)
count <= 8'b0000_0001;
else if (enable == 1'b1) count <= {count[6:0], count[7]};
//else count <= count; Is inferred by lack of an else

endmodule

A shift register instead of a lot of muxes and


comparators!
Does the lack of ELSE infer a latch?
Courtesy: Mike Morrow and Eric Hoffman

Register With Parallel Load


module Par_load_reg4 (Data_out, Data_in, load, clock, reset);
output reg [3:0] Data_out;
input [3:0] Data_in;
input
load, clock, reset;
always @ (posedge reset, posedge clock)
begin
if (reset == 1'b1)
Data_out <= 4'b0;
else if (load == 1'b1)
Data_out <= Data_in;
end
endmodule

Courtesy: Mike Morrow and Eric Hoffman

Rotator with Parallel Load


module rotator (Data_out, Data_in, load, clock, reset);
output reg [7: 0] Data_out;
input [7: 0] Data_in;
input
load, clock, reset;
always @ (posedge reset or posedge clock)
if (reset == 1'b1) Data_out <= 8'b0;
else if (load == 1'b1) Data_out <= Data_in;
else Data_out <= {Data_out[6: 0], Data_out[7]};
endmodule

Courtesy: Mike Morrow and Eric Hoffman

Shift Register Part 1


module Shift_Reg(Data_Out, MSB_Out, LSB_Out,
Data_In, MSB_In, LSB_In, s1, s0, clk, rst);
output reg [3: 0] Data_Out;
output
MSB_Out, LSB_Out;
input
[3: 0] Data_In;
input
MSB_In, LSB_In;
input
s1, s0, clk, rst;
assign MSB_Out = Data_Out[3];
assign LSB_Out = Data_Out[0];
// continued on next slide

Courtesy: Mike Morrow and Eric Hoffman

Shift Register Part 2


always @ (posedge clk) begin
if (rst) Data_Out <= 0;
else case ({s1, s0})
2d0: Data_Out <= Data_Out;
// Hold
2d1: Data_Out <= {MSB_In, Data_Out[3:1]}; // Shift from MSB
2d2: Data_Out <= {Data_Out[2: 0], LSB_In}; // Shift from LSB
2d3: Data_Out <= Data_In;
// Parallel Load
endcase
end
endmodule
Given Verilog code, be able to tell what it does.
Given a high-level description, be able to write Verilog code to
implement it.
Courtesy: Mike Morrow and Eric Hoffman

Register File
module Register_File (Data_Out_1, Data_Out_2, Data_in, Read_Addr_1,
Read_Addr_2, Write_Addr, Write_Enable, Clock);
output [15:0] Data_Out_1, Data_Out_2;
input
[15:0] Data_in;
input
[2:0] Read_Addr_1, Read_Addr_2, Write_Addr;
input
Write, Enable, Clock;
reg
[15:0] Reg_File [0:7]; // 16-bit by 8-word memory declaration
always @ (posedge Clock) begin
if (Write_Enable) Reg_File [Write_Addr] <= Data_in;
Data_Out_1 <= Reg_File[Read_Addr_1];
Data_Out_2 <= Reg_File[Read_Addr_2];
end
endmodule

What kind of read and write capability does this module have?
Are the reads and writesCourtesy:
synchronous
orEricasynchronous?
Mike Morrow and
Hoffman

Overview

Behavioral Design Examples

Combinational Logic
Registers

Finite State Machine Design

Mealy
Moore
Control vs. Datapath
Implicit FSM Design

Courtesy: Mike Morrow and Eric Hoffman

FSM Models & Types

Explicit

Declares a state register that stores the FSM state


May not be called state might be a counter!

Implicit

Describes state implicitly by using multiple event controls

Moore

Outputs depend on state only (synchronous)

Mealy

Outputs depend on inputs and state (asynchronous)


Outputs can also be registered (synchronous)
Courtesy: Mike Morrow and Eric Hoffman

Generic FSM Diagram


Mealy
Inputs

Next State
Logic
State Register
Current State

Next State
FF

Courtesy: Mike Morrow and Eric Hoffman

Output
Logic

Outputs

State Diagram
Outputs Y and Z are 0,
unless specified otherwise.
a=0

S0

b=0

a = 1/
Z=1

S1
Y=1

We dont care about the


value of b in S0, or the
value of a in S1, or either a
or b in S2.
Is this Mealy or Moore?

b = 1/ Z = 1

reset = 1
S2

Courtesy: Mike Morrow and Eric Hoffman

State Diagram: Mealy!


a=0
b = x/
Y = 0,
Z=0

S0

a=1
b = x/
Y = 0,
Z=1

reset = 1
ab = xx/
YZ = 00

a=x
b = 0/
Y = 1,
Z=0

S1

Outputs Y and Z are 0,


unless specified otherwise.

We dont care about the


value of b in S0, or the
value of a in S1, or either a
or b in S2.

Is this Mealy or Moore?


a=x
b = 1/
Y = 1,
S2 Z = 1

Courtesy: Mike Morrow and Eric Hoffman

Mealy Verilog [1] Part 1


module fsm_mealy1 (clk, reset, a, b, Y, Z);
input clk, reset, a, b;
output Y, Z;
reg[1:0] state, next_state;
reg Y, Z;
parameter S0 = 2b00, S1 = 2b01, S2 = 2b10; //state values

always@(posedge clk) begin


if (reset)
state <= S0;
// using non-blocking since sequential
else
state <= next_state;
end
//continued on next slide

Courtesy: Mike Morrow and Eric Hoffman

Mealy Verilog [1] Part 2


// next state logic
always@(state, a, b)
case (state)
S0: if (a)
next_state = S1;
else
next_state = S0;
S1: if (b)
next_state = S2;
else
next_state = S1;
S2:
next_state = S0;
default: next_state = 2bx;
endcase

// output logic
always@(state, a, b) begin
Z = 1b0, Y = 1b0; //avoids latch
case (state)
S0: if (a) Z = 1;
S1: begin
Y = 1;
if (b) Z = 1;
end
S2: ;
// Z = 0, Y = 0
default: begin
Y = 1bx; Z = 1bx; end
endcase
endmodule

What happens when


state = S1, b = 1b0?
Courtesy: Mike Morrow and Eric Hoffman

Mealy FSM
Inputs

Outputs

Next State and


Output Logic
State Register
Current State

FF

What are the advantages and disadvantages of this approach?

Courtesy: Mike Morrow and Eric Hoffman

Mealy Verilog [2] Part 1


module fsm_mealy2 (clk, reset, a, b, Y, Z);
input clk, reset, a, b;
output Y, Z;
reg[1:0] state, next_state;
reg Y, Z;
parameter S0 = 2b00, S1 = 2b01, S2 = 2b10; //state values
always@(posedge clk) begin
if (reset)
state <= S0;
// using non-blocking since sequential
else
state <= next_state;
end
//continued on next slide
Courtesy: Mike Morrow and Eric Hoffman

Mealy Verilog [2] Part 2


// next state & output logic
always@(state, a, b)
begin
Y = 0; Z = 0;
case (state)
S0: if (a) begin
next_state = S1;
Z = 1;
else
next_state = S0;
S1: begin
Y = 1;

if (b)
begin
next_state = S2;
Z = 1;
end
else
next_state = S1;
end
S2: next_state = S0;
default: begin
next_state = 2bx; Y = 1bx;
Z = 1bx; end
endcase
endmodule

Courtesy: Mike Morrow and Eric Hoffman

Registered Mealy FSM


Output Register
Inputs

Outputs

Next State and


Output Logic
State Register
Current State

FF

This delays the change in outputs by one cycle


How would this change the previous code?
Courtesy: Mike Morrow and Eric Hoffman

FF

Registered Mealy FSM


Output Register
Registered
Outputs

Inputs

Next State and


Output Logic
State Register
Current State

FF

Combinational
Outputs

FF

Can be helpful for debugging to also see outputs before registering


Courtesy: Mike Morrow and Eric Hoffman

Overview

Behavioral Design Examples

Combinational Logic
Registers

Finite State Machine Design

Mealy
Moore
Control vs. Datapath
Implicit FSM Design

Courtesy: Mike Morrow and Eric Hoffman

State Diagram: Moore


a=0
S0

b=0

a=1

S1
Y=1

Outputs Y and Z are 0,


unless specified otherwise.
If an input isnt listed for a
transition, we dont care
about its value for that
transition

b=1

reset = 1

S2
Z=1

Courtesy: Mike Morrow and Eric Hoffman

Moore FSM
Inputs

Next State
Logic
State Register
Current State

Next State
FF

Courtesy: Mike Morrow and Eric Hoffman

Output
Logic

Outputs

Moore Verilog Part 1


module fsm_moore (clk, reset, a, b, Y, Z);
input clk, reset, a, b;
output Y, Z;
reg[1:0] state, next_state;
reg Y, Z;
parameter S0 = 2b00, S1 = 2b01, S2 = 2b10; //state values
always@(posedge clk) begin
if (reset)
state <= S0;
// using non-blocking since sequential
else
state <= next_state; //continued on next slide
end

Courtesy: Mike Morrow and Eric Hoffman

Moore Verilog Part 2


//next state logic
always@(state or a or b)
case (state)
S0: if (a)
next_state = S1;
else
next_state = S0;
S1: if (b)
next_state = S2;
else
next_state = S1;
S2: next_state = S0;
default: next_state = 2bxx;
endcase

//output logic
always@(state) begin
Z = 0, Y = 0; // avoids latches
case (state)
S0: ;
S1: Y = 1;
S2: Z = 1;
default: begin
Y = 1bx; Z = 1bx; end
endcase
end
endmodule

Courtesy: Mike Morrow and Eric Hoffman

Overview

Behavioral Design Examples

Combinational Logic
Registers

Finite State Machine Design

Mealy
Moore
Control vs. Datapath
Implicit FSM Design

Courtesy: Mike Morrow and Eric Hoffman

Multi-Add Example FSM

Specification:

Inputs [7:0] in, [1:0] more (and clk, rst)


Output register [7:0] total initialized to 0 on reset
While more is not 0
Add in to total more times

(in can change each clock cycle)

Read a new value of more


If more is 0, go to a final state where no more adding
takes place, and sit there until reset

Courtesy: Mike Morrow and Eric Hoffman

FSM Diagram (Mealy)

Can separate the Control from the Datapath

Datapath: Accumulator w/ enable (add)


Control: FSM to generate enable above

Can create combined Control and Datapath


reset = 1
add = 0

more = 3 / add = 1
more = 2 / add = 1

SDONE
S0
more = 0
/ add = 0

add = 1

S1

more = 1
/ add = 1
Courtesy: Mike Morrow and Eric Hoffman

add = 1

S2

Separate Control / Datapath


module multiadd_ctrl(output reg add, input [1:0] more,
input clk, rst); // signals in and total not included
reg [1:0] state, next;
parameter SDONE=2b00, S0=2b01, S1=3b10, S2=3b11;

initial state <= S0; // May not synthesize, better to rely on rst
always@(posedge clk or posedge rst)
if (rst) state <= S0;
else state <= next;

Courtesy: Mike Morrow and Eric Hoffman

Separate Control / Datapath


//next state logic
always@(state, more)
case (state)
S0:
case (more)
2b00: next = SDONE;
2b01: next = S0;
2b10: next = S1;
2b11: next = S2;
default: next = 2bxx;
endcase
S1: next = S0;
S2: next = S1;
SDONE: next = SDONE;
default: next = 2bxx;
endcase

//output logic
always@(state,more) begin
case (state)
SDONE: add = 0;
S0:
add = |more;
default: add = 1;
endcase
end
endmodule

Courtesy: Mike Morrow and Eric Hoffman

Separate Control / Datapath


module multiadd(output reg [7:0] total,
input [7:0] in, input [1:0] more, input clk, rst);
wire adden;
// control
multiadd_ctrl ctrl(adden, more, clk, rst);
// datapath
always@(posedge clk) begin
if (rst) total <= 0;
else if (adden) total <= total + in;
end
endmodule

Courtesy: Mike Morrow and Eric Hoffman

Combined Control / Datapath


multiadd(output reg [7:0] total,
input [7:0] in, input [1:0] more, input clk, rst);
reg [1:0] state;
parameter SE=2b00, S0=2b01, S1=2b10, S2=2b11;
always@(posedge clk) begin
if (rst) begin
state <= S0; total <= 0;
end
else begin
// else block continued on next slide...

Courtesy: Mike Morrow and Eric Hoffman

Combined Control / Datapath


// default to performing the add
total <= total + in;
case (state)
S0: begin
case (more)
2b00: begin
state <= SDONE;
total <= total; // override default
end
2b01: state <= S0;
2b10: state <= S1;
2b11: state <= S2;
default: state <= 2bxx;
endcase
end // end state==S0 case

S1: state <= S0;


S2: state <= S1;
SDONE: begin
state <= SDONE;
total <= total; // override default
end
default: state <= 2bxx;
endcase
end
endmodule

Courtesy: Mike Morrow and Eric Hoffman

Overview

Behavioral Design Examples

Combinational Logic
Registers

Finite State Machine Design

Mealy
Moore
Control vs. Datapath
Implicit FSM Design

Courtesy: Mike Morrow and Eric Hoffman

Implicit FSM Model

More abstract representation

May not have explicit state register!

Only FSMs with one choice at each state

Does it yield simpler code?

Maybe *shorter* code


But is more confusing!

Description of reset behavior more complex


Much less likely to synthesize than explicit!

Can confuse some synthesizers


Courtesy: Mike Morrow and Eric Hoffman

Implicit FSM Model

Typically uses series of @(posedge clock)s

Example: Mod 3 counter

IMPLICIT

EXPLICIT

always begin
@(posedge clk) count <= 0;
@(posedge clk) count <= count + 1;
@(posedge clk) count <= count + 1;
end

always @(posedge clk) begin


if (count==2) count <= 0;
else count <= count + 1;
end

Implicit

Difficult to add reset


Difficult to read/understand

Courtesy: Mike Morrow and Eric Hoffman

Review Questions

Why might we want to separate datapath and


control?

In what situations would we want to combine them?

How do the implementations of a Moore FSM and a


Mealy FSM differ?
How would you implement the multiadd fsm as a
single always block?

Would a single always block be easier or harder to design

than the presented implementations?


Would a single always block be easier or harder to
understand if you were reading someone elses design?
Courtesy: Mike Morrow and Eric Hoffman

Review Questions

Design a circuit that

Inputs a single 8-bit data value, clock, and reset


Outputs a single 10-bit data value
At reset the output becomes zero
Every four cycles after a reset, the output value is

changed to be the sum of the input values over the four


previous cycles
The output should not change more frequently than
every four cycles (unless there is a reset)

Courtesy: Mike Morrow and Eric Hoffman

S-ar putea să vă placă și