input

advertisement
ENEE 408C Lab
Capstone Project: Digital System
Design
Spring 2006
Class Web Site:
http://www.ece.umd.edu/class/enee408c
TA’s Information
Alessandro Geist
ageist@umd.edu
Office Hours: TBD
Parameters: An N-bit Register
module register (Q,D, clk, reset_n);
parameter
size=2;
input [size-1:0] D;
input clk;
input reset_n;
output[size-1:0] Q;
reg
[size-1:0] Q;
always @ (posedge clk or negedge reset_n) begin
if (!reset_n)
// active low reset
Q<=0;
else
Q<=D;
end
endmodule
Parameters
register r1(Q,D, clk, reset_n);
register #(16) r2(Q2,D2, clk, reset_n);
If multiple parameters:
Some_module #(10,8) mod(a,b,c);
Define Statements
`define IN_SIZE 8 // num bits of input
module some_module(A,B);
input [`INPUT_SIZE-1:0] A,B;
.
.
.
endmodule
Concatenation
/////////////////////////// BCD to 7-Segment Display ///////////////////////////////////
module sevensegment(a,b,c,d,e,f,g,W,X,Y,Z);
output
a,b,c,d,e,f,g;
input
W,X,Y,Z;
reg
a,b,c,d,e,f,g;
always @ (W or X or Y or Z) begin
case ({W,X,Y,Z})
4'b0000: {a,b,c,d,e,f,g} = 7'b1111110;
4'b0001: {a,b,c,d,e,f,g} = 7'b0110000;
4'b0010: {a,b,c,d,e,f,g} = 7'b1101101;
4'b0011: {a,b,c,d,e,f,g} = 7'b1111001;
4'b0100: {a,b,c,d,e,f,g} = 7'b0110011;
4'b0101: {a,b,c,d,e,f,g} = 7'b1011011;
4'b0110: {a,b,c,d,e,f,g} = 7'b1011111;
4'b0111: {a,b,c,d,e,f,g} = 7'b1110000;
4'b1000: {a,b,c,d,e,f,g} = 7'b1111111;
4'b1001: {a,b,c,d,e,f,g} = 7'b1111011;
default: {a,b,c,d,e,f,g} = 7'b0000000;
endcase
end// end always block
endmodule
// 0
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// BLANK
Loops
A loop is synthesizable if it is static: The number of iterations is fixed and
independent of the data
Example:
reg [2:0]
i;
reg [3:0]
out;
wire [3:0]
a,b;
always @ (a or b)
begin
for (i=0; i<=3; i=i+1)
out[i] = a[i] & b[i];
end
endmodule
Example Unrolled:
out[0] = a[0] & b[0];
out[1] = a[1] & b[1];
out[2] = a[2] & b[2];
out[3] = a[3] & b[3];
Generate Statements
Generate Loop
Generate loops can be used to create multiple instances of
instances within a for loop.
The for loop in a generate statement is similar to the regular for loop
except for the following conditions:
– The loop index variable must be a genvar variable, a special integer
variable used in for loops.
– The assignments in the loop control must assign to the same genvar.
– The contents of the loop must be within a named begin–end block.
The genvar variable is a special integer variable used in generate
loops, which can be assigned only 0 or positive numbers. A genvar
can only be assigned a value as part of a generate loop statement. A
genvar variable can be defined outside of the generate block or
within a generate block. If declared outside, the genvar variable can
be used by any number of generate blocks.
Conditional Generates
Conditional generates can be created in two ways:
– if –else statements
– case statements
Both of these statements can be used within the generate block.
Here is an example of using a generate statement to control the type of
adder used:
// if-else
generate
if (adder_width < 8)
ripple_carry # (adder_width) u1 (a, b, sum);
else
carry_look_ahead # (adder_width) u1 (a, b, sum);
endgenerate
Note: The expression inside the if statement must evaluate to a static value.
Conditional Generates
The following example uses the case statement to
determine which adder is used, based on the parameter
WIDTH:
// case
parameter WIDTH=1;
generate
case (WIDTH)
1: adder1 x1 (c0, sum, a, b, ci);
2: adder2 x1 (c0, sum, a, b, ci);
default: adder # WIDTH (c0, sum, a, b, ci);
endcase
endgenerate
Generate Statement Example
Generating multiple module instances of otherModule and connecting them:
module some_module(mod_out, A);
parameter SIZE = 8;
input [SIZE-1:0] A;
output [SIZE-1:0] mod_out;
wire [SIZE:0] intermediate;
generate
genvar I;
for (i=0; i<SIZE; i=i+1)
begin: instance_name
otherModule name(mod_out[i], intermediate[i+1], A[i], intermediate[i]);
end
endgenerate
endmodule
Finite State Machines
A finite state machine (FSM) is a circuit
designed to sequence through specific
patterns of states in a sequential manner.
Each state is represented by a binary
value.
An FSM contains a sequential state
register, and combinational next-state and
output logic.
Mealy and Moore Machines
A Mealy state machine has outputs that
are a function of the current state AND
the primary inputs.
A Moore state machine has outputs that
are a function of the current state only.
A combined Mealy/Moore state machine
has … both.
Numerous FSM ‘dialects’ exist in
design tools.
State Table
Input
A
Input
Hold
Curren
t State
Next
State
Output Output
Y_Me Y_Mo
0
1
0
X
X
X
000
000
001
000
001
000
1
0
0
0
0
1
1
X
X
0
X
X
1
0
001
010
011
011
010
011
011
000
1
0
0
1
1
0
1
1
1
X
0
X
011
100
100
000
1
0
1
1
State Diagram
0X/1
0
XX/0
1
000
1X/0
001
100
1
0X/0
00/1
1X/1
10/1
1
X1/0
011
010
XX/0
0
HDL Coding Style
Typically the synchronous portion is simply
the state <= next_state assignment.
The next_state portion is done in a purely
combinational block (or multiple blocks).
– This is best done using a case statement
rather than an if/else tree.
– Defaults are easily set and excepted by
unique cases.
Resets
Using an asynchronous reset
– Ensures that the state machine is always
initialized to a known valid state.
– No need to decode any unused current state
values and thus minimizes next state logic.
Using a synchronous reset or no reset
– Cannot predict initial state.
– Must decode all states in the next state logic.
– Can be a win if the next state logic is small
compared to the additional size of the reset HW.
State Encoding
Sequential (“binary”)
– Simple assignment
Gray
– Assigns states by the minimum logic difference in the
state transition graph.
– I.e., assign adjacent codes to adjacent states
– Reduces the amount of logic needed to decode each
state.
Johnson
– Only one bit changes.
One-hot
– One bit in the state register for each state.
– A large number of flip-flops, but no decoding for states.
– Can result in smaller and faster FSMs, especially for
ASICs with large amounts of sequential logic relative to
combinational logic resources.
State Encoding (Example)
Number
Sequential
Gray
Johnson
One-Hot
0
0000
0000
00000000
0000000000000001
1
0001
0001
00000001
0000000000000010
2
0010
0011
00000011
0000000000000100
3
0011
0010
00000111
0000000000001000
4
0100
0110
00001111
0000000000010000
5
0101
0111
00011111
0000000000100000
6
0110
0101
00111111
0000000001000000
7
0111
0100
01111111
0000000010000000
8
1000
1100
11111111
0000000100000000
9
1001
1101
11111110
0000001000000000
10
1010
1111
11111100
0000010000000000
11
1011
1110
11111000
0000100000000000
12
1100
1010
11110000
0001000000000000
13
1101
1011
11100000
0010000000000000
14
1110
1001
11000000
0100000000000000
15
1111
1000
10000000
1000000000000000
Coding a One-hot
always @ (state)
begin
next_state = 0;
case (1’b1)
reg [15:0] state,
state[S0]: next_state[S1] =
next_state;
1;
state[S1]: …;
always @ (posedge clk)
state[S2]: …;
begin
...
state <= #1 next_state;
default: next_state =
end
16’bx
endcase
end
parameter S0=0, S1=1,
S2=2, S3=3, …;
Why to Use a One-hot
Advantages
– Easy to decode – one bit active for each
state.
–  Compact decoding logic.
– Fast.
Disadvantages
– Size
But, compare the size of any state
machine to the datapath that it is
controlling. In many circumstances, the
datapath dwarfs the state machine and
the speed advantage is worth the
tradeoff.
`define STATE_BITS 2
`define S0 2'b00
`define S1 2'b01
`define S2 2'b11
module moore (z, state,
reset_n, clk, x);
output z; // data output
output [`STATE_BITS-1: 0]
state;
input reset_n;
input clk;
input x; // single data input
reg z;
reg [`STATE_BITS-1:0] state;
always @(state) begin
case (state)
`S0: z = 1'b0;
`S1: z = 1'b0;
`S2: z = 1'b1;
default: z = 1'bX;
// for all cases to be covered
endcase
end
always @(negedge reset_n or posedge clk) begin
if (~reset_n)
state <= `S0;
// initial state
else begin
case (state)
`S0: begin
if (x)
state <= `S1;
else
state <= `S2;
end
`S1: begin
if (!x)
state <= `S2;
end
`S2:
state <= `S0;
default: state <= 2'b00;
endcase
end // end else
end // end always
endmodule
`timescale 1ns/1ns
`define PERIOD
`define STATE_BITS 2
`define S0 2’b00
`define S1 2'b01
`define S2 2'b11
module test_state();
wire z;
wire [`STATE_BITS-1:0] state;
reg reset_n;
reg clk;
reg x;
integer error_count;
// instantiate module
moore m1(z, state,
reset_n, clk, x);
initial begin
clk = 0;
error_count = 0;
reset_n =0;
# `PERIOD reset_n = 1;
end
always #(`PERIOD/2) clk = ~clk;
task error_check;
input [`STATE_BITS-1:0] expectedState, actualState;
input expectedZ, actualZ;
begin
if (!((actualState == expectedState) && (actualZ == expectedZ)))
begin
error_count = error_count +1;
$display(“ERROR: state = %0b, output = %0b at time %0t.”,
actualState, actualZ, $time);
end
end
endtask
initial begin
$display(“start simulation”);
x = 0;
// initial data value, check reset
#`PERIOD; error_check(`S0, state, 1’b0, z);
x = 0;
// next go to state `S2
#`PERIOD; error_check(`S2, state, 1’b0, z);
x = 1;
// next go to state `S0
#`PERIOD; error_check(`S0, state, 1’b0, z);
x = 1;
// next, go to state `S1
#`PERIOD; error_check(`S1, state, 1’b0, z);
end
endmodule
Functions and Tasks
Functions and Tasks are similar to
functions and subroutines in C
Why?
– More readable
– More portable
– More compact
Functions
Used to implement combinational behavior
Cannot call tasks
Cannot call functions recursively
Cannot contain timing control (delay, event,
wait)  zero elapsed simulated time
Must have at least one input
Cannot have output or inout ports
Must return a value
(syntax: function_name = returned_value)
Are invoked as operands in expressions
Can be invoked from procedural and
continuous assignment statements
Functions: Example
// Function Declaration
function [7:0] twoscomplement;
input
[7:0] operand;
operand = (~operand) + 1;
endfunction
// Calling the function
assign A_comp = twoscomplement(A);
Tasks
Can call tasks and functions
Can contain timing control  can consume time
Can only be called from procedural statements
Any combination of input, output, and inout ports is
allowed
Can return values through the output and inout
ports
Are invoked as separate procedural statements
Cannot be invoked from continuous assignment
statements
Recursion can be used
All calls of a task use the same memory for variables
Tasks: Example
module task_example (a,b,c);
input [7:0] a,b;
output [7:0] c;
reg [7:0] c;
task adder;
input [7:0] a,b;
output [7:0] adder;
reg c;
integer i;
begin
c = 0;
for (i = 0; i <= 7; i = i+1) begin
adder[i] = a[i] ^ b[i] ^ c;
c = (a[i] & b[i]) | (a[i] & c) | (b[i] & c);
end
end
endtask
always
adder (a,b,c); // Call Task
endmodule
Download