Verilog Tutorial Covered in Lecture

advertisement
1
Verilog – System Design Example
Example: Design a 4-bit by 4-bit Multiplier using Repetitive Add Algorithm.
For example, if you wanted to multiply
1010 A
0110 B
------00111100
Result
The above can be accomplished by repeatedly adding 1010 six times (i.e., the B value).
The datapath and the controller for this will appear as:
A (4 bits)
Clk
A (4 bit Latch)
B(4 bits)
4 bit down Counter
Load A
Load Counter
Dec. Count
0
NOR 4
8-Bit Adder
CountEq0
Ready
Reset
Result (8-bit FET Register)
Done
Load Result
Clear Result
:
Controller State Diagram:
______
Ready
Load A
Load Counter
Clear Result
________
Ready
CountEq0
Load Result
CountEq0
Done
_______
= CountEq0
C
O
N
T
R
O
L
L
E
R
2
Create a new Altera project called MultiplierRepetitiveAdd by using the new project wizard. The
different steps of the wizard are as shown below.
3
Depending upon the complexity of the project, you can choose an appropriate device family.
4
Select Verilog HDL when prompted for EDA Tool settings as shown below.
5
Choose File->New and select the Verilog HDL option,
Type the following code in the editor window.
module OneBitAdder(a,b,cin,sum,cout);
input a,b,cin;
output sum,cout;
assign sum = a ^ b ^ cin;
assign cout = (a & b) | (a & cin) | (b & cin);
endmodule
Save the file in the MultiplierRepetitiveAdd folder with the name of OneBitAdder.v.
6
Similarly add another file to the project with the following code and save it as EightBitAdder.v.
module EightBitAdder(A, B, cin, Sum, cout);
input[7:0] A,B;
input cin;
output[7:0] Sum;
output cout;
wire[7:0] ctemp;
OneBitAdder add0(A[0],B[0],cin,Sum[0],ctemp[0]);
OneBitAdder add1(A[1],B[1],ctemp[0],Sum[1],ctemp[1]);
OneBitAdder add2(A[2],B[2],ctemp[1],Sum[2],ctemp[2]);
OneBitAdder add3(A[3],B[3],ctemp[2],Sum[3],ctemp[3]);
OneBitAdder add4(A[4],B[4],ctemp[3],Sum[4],ctemp[4]);
OneBitAdder add5(A[5],B[5],ctemp[4],Sum[5],ctemp[5]);
OneBitAdder add6(A[6],B[6],ctemp[5],Sum[6],ctemp[6]);
OneBitAdder add7(A[7],B[7],ctemp[6],Sum[7],ctemp[7]);
endmodule
As you can see from the above code that the 8-bit adder uses 8 one-bit adder modules to form a
ripple carry adder.
Similarly create and save the following modules.
module Reg4Latch(D,clk,Q); // save as Reg4Latch.v
input[3:0] D;
input clk;
output[3:0] Q;
//reg[3:0] temp; // rather than declaring reg[3:0] temp, you can declar reg Q[3:0]
reg[3:0]Q;
// and assign D to Q
always @(clk,D) // latch
begin
if (clk == 1'b1)
Q = D;
//temp = D;
end
//assign Q = temp;
endmodule
module Reg8FF(D,clk,clear,Q); // save as Reg8FF.v
input[7:0] D;
input clk,clear;
output[7:0] Q;
reg[7:0] temp;
always @(negedge clk) // Falling edge triggered
begin
if (clear == 1'b1)
temp = 8'b00000000;
else
temp = D;
7
end
assign Q = temp;
endmodule
module NORG4(X,out); // save as NORG4.v
input[3:0] X;
output out;
assign out = ~(X[0]| X[1] | X[2] | X[3]);
endmodule
module DownCounter4(Data,clk,load,dec,Out); // save as DownCounter4.v
input[3:0] Data;
input load, dec, clk;
output[3:0] Out;
reg[3:0] temp;
always @(negedge clk)
begin
if (load == 1'b1)
temp = Data;
else
begin
if (dec == 1'b1)
temp = temp - 1'b1;
end
end
assign Out = temp;
endmodule
module Controller(ready,reset,counteq0,clk,loadA,loadCounter,decCount,clearResult,
loadResult,done,state); // save as Controller.v
input ready,reset,counteq0,clk;
output loadA,loadCounter,clearResult,decCount,loadResult,done;
output[1:0] state;
reg loadA,loadCounter,clearResult,loadResult,decCount,done; // same outputs can be declared
as reg
reg[1:0] stateT;
parameter s0=0, s1 = 1, s2 = 2;
always @(negedge clk)
begin
if (reset == 1'b1)
stateT = s0;
else
case(stateT)
s0 : if (ready == 1'b0)
stateT = s0;
8
else
stateT = s1;
s1 : if (counteq0 == 1'b0)
stateT = s1;
else
stateT = s2;
s2 : stateT = s0;
endcase
end
assign state = stateT;
always @(stateT,clk,counteq0) // important parameters for sensitivity list
begin
case(stateT)
s0 : begin
loadA = 1'b1;
loadCounter = 1'b1;
clearResult = 1'b1;
loadResult = 1'b0;
decCount = 1'b0;
done = 1'b0;
end
s1 : begin
loadA = 1'b0;
loadCounter = 1'b0;
clearResult = 1'b0;
loadResult = ~counteq0 & clk; // without anding with clk, loadResult will
decCount = 1'b1;
// will be high in multiple states
done = 1'b0;
end
s2 : begin
loadA = 1'b0;
loadCounter = 1'b0;
clearResult = 1'b0;
loadResult = 1'b0;
decCount = 1'b0;
done = 1'b1;
end
endcase
end
endmodule
module DataPath(A, B, clk,ready,Prod,decCounter,loadCounter,loadA,
clearResult,loadResult, counteq0,count); // save as DataPath.v
input[3:0] A,B;
input clk,ready,decCounter,loadCounter,loadA,clearResult,loadResult;
output[7:0] Prod;
output counteq0;
output[3:0] count;
9
reg temp[7:0];
wire[3:0] CounterOut;
wire[7:0] AdderOut;
wire[3:0] Aout;
wire cout;
wire[7:0] ResultOut;
//-----------datapth components--------------Reg4Latch AReg(A,loadA,Aout);
EightBitAdder add8({4'b0000,A},ResultOut,1'b0,AdderOut,cout);
Reg8FF res8(AdderOut,loadResult,clearResult,ResultOut);
DownCounter4 counter4(B,clk,loadCounter,decCounter,CounterOut);// parameters for Reg8FF:
Data,clk,load,dec,Out
NORG4 n4(CounterOut,counteq0);
//-------------------------------------------assign Prod = ResultOut;
assign count=CounterOut; // for debugging purpose
endmodule
module MultiplierRepetitiveAdd(A,B,ready,reset,clk,Result,done,state,count,loadResult);
// save as MultiplierRepetitiveAdd.v
input[3:0] A,B; // state, count, loadResult outputs are for debugging purpose
input ready,reset,clk;
output[7:0] Result;
output[3:0] count;
output loadResult;
output done;
wire[7:0] tempRes;
output[1:0] state;
wire[1:0] stateTemp;
wire[3:0] countTemp;
wire decCounter,loadCounter,loadA,clearResult,loadResultT,doneTemp,counteq0;
DataPath dpath(A, B,
clk,ready,tempRes,decCounter,loadCounter,loadA,clearResult,loadResultT,
counteq0,countTemp);
Controller
control(ready,reset,counteq0,clk,loadA,loadCounter,decCounter,clearResult,loadResultT,doneT
emp,stateTemp);
assign Result = tempRes;
assign done = doneTemp;
assign state = stateTemp;
assign count = countTemp;
// for debugging purpose
assign loadResult=loadResultT; // for debugging purpose
endmodule
Add another Verilog file for testbench to the project by choosing File->new. Type the following
code in it.
10
// testbench
`timescale 1ns/100ps
module tbMultiplierRepetitiveAdd(); // save as tbMultiplierRepetitiveAdd.v
reg[3:0] At,Bt;
reg readyt,resett,clkt;
wire[7:0] Result;
wire done;
wire[1:0] state; // inputs to module are declared as reg, outputs as wire in TB
wire[3:0] count;
wire loadResult;
MultiplierRepetitiveAdd mrp(At,Bt,readyt,resett,clkt,Result,done,state,count,loadResult);
initial
begin
clkt = 1'b0;
resett = 1'b1;
#15 resett = 1'b0;
end
initial
begin
readyt = 1'b0;
#30 readyt = 1'b1;
#20 readyt = 1'b0;
end
initial
begin
At = 4'b1010;
Bt = 4'b0110;
end
always
begin
#5 clkt = ~clkt;
end
initial
#200 $finish;
endmodule
From the Assignments->Settings menu, click on the TestBenches… button as shown below.
11
Then click on the New button:
Then type the name of the testbench file i.e., tbMultiplierRepetitiveAdd.v as shown below.
After selecting the testbench file, click on the Add button as shown above.
12
Click on the OK button, then OK button in the next dialog.
Then click on Apply and OK.
13
Now the testbench will be compiled along with rest of the Verilog code for the project.
From the Processing menu, choose “Start Compilation”.
14
If there are no errors reported, you can simulate your project by choosing Tools->Run
Simulation Tool ->RTL Simulation as shown below.
This will launch the ModelSim and run the project to end of simulation time. When it prompts
you to “Are you sure you want to finish?”, choose “NO”.
Then right click in the waveform area and choose “Zoom full” as shown below.
15
This will show the complete simulation for your design as shown below.
Download