Restructered pre-import
This commit is contained in:
251
Old Pages/Electronics/FPGAExercise3.md
Executable file
251
Old Pages/Electronics/FPGAExercise3.md
Executable file
@@ -0,0 +1,251 @@
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Digital Design and FPPGA Workshop
|
||||
HacDC
|
||||
William Gibb (teachmeFPGA@gmail.com)
|
||||
Week 3 - Introduction to Combinatorial Verilog
|
||||
Full adder and ALU exercise
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
For our exercises this week, we'll be working with a few different modeling
|
||||
styles, focused around a 4-bit full adder. We'll be working with a model
|
||||
where the 1 bit full adder circuit is explicitly defined, and break that down
|
||||
into half adders, behavioral and structural models.
|
||||
|
||||
The full adder circuit can be constructed from 1-bit half adder circuits.
|
||||
The truth table for the half adder is as follows.
|
||||
A B | S Cout
|
||||
=========
|
||||
0 0 | 0 0
|
||||
0 1 | 1 0
|
||||
1 0 | 1 0
|
||||
1 1 | 0 1
|
||||
=========
|
||||
S = A xor B
|
||||
Cout = A and B
|
||||
|
||||
Two of these cells, plus an additional OR gate, can be used to implement a
|
||||
full adder. The S output of the first half adder cell is connected to the
|
||||
input of the second cell, as is the Cin. The S output of the second cell is
|
||||
the sum S. The Cout is computed by ORing the Cout of both cells.
|
||||
|
||||
Likewise, the truth table for the Full Adder is as follows, for reference.
|
||||
Cin A B | S Cout
|
||||
===============
|
||||
0 0 0 | 0 0
|
||||
0 0 1 | 1 0
|
||||
0 1 0 | 1 0
|
||||
0 1 1 | 0 1
|
||||
1 0 0 | 1 0
|
||||
1 0 1 | 0 1
|
||||
1 1 0 | 0 1
|
||||
1 1 1 | 1 1
|
||||
================
|
||||
|
||||
To do
|
||||
0) Copy the full adder codes below to files in your working directory.
|
||||
Be sure to copy a makefile to the directory.
|
||||
0.a) mkdir a new directory for this example. name it something useful, such as "adder_exercise"
|
||||
0.b) create a new file for each verilog module, in the form modulename.v where module name is the name of the module. We'll need full_adder.v, full_adder_4bit.v, add test_adder.v.
|
||||
0.c) copy and paste the code for each module into the file. be sure that anything in the file that isn't verilog code is commented out.
|
||||
0.d) if your in the vm, type copymake.sh into the command line to copy a makefile into your working directory
|
||||
|
||||
1) Change the values of the makefile to test the full adder.
|
||||
1.a) Change the line SRC and TESTBENCH to include only the .v files created earlier. if you need to add a new source to a project, add it to your makefile as well.
|
||||
|
||||
2) Verify the full adder works by simulation.
|
||||
|
||||
3) Write a description of the half adder, at gate level
|
||||
|
||||
4) Write a full adder description, using the half adders you wrote in step
|
||||
3. Give this full adder module a different module name than the provided
|
||||
model.
|
||||
|
||||
5) Write a 4 bit full adder module using the new 1 bit full adder. Be sure to
|
||||
give it a module name different than the name of the provided module.
|
||||
|
||||
6) Take a break if you feel needed...or keep on coding
|
||||
|
||||
7) Write a 4 bit full adder module using the new 1 bit full adder from step 6.
|
||||
Be sure to give it a module name different than the name of the provided
|
||||
module.
|
||||
|
||||
8) One last adder - Write a 4 bit behavioral adder module. Use 4 bit inputs
|
||||
and outputs in this module. Again, give it a new name.
|
||||
|
||||
9) Add the new models to the makefile.
|
||||
-half adder
|
||||
-full adder from half adders
|
||||
-4 bit full adder from step 5
|
||||
-full adder from step 6
|
||||
-4 bit full adder from step 7
|
||||
-4 bit full adder from step 8
|
||||
|
||||
9) Modify the testbench to instantiate the new modules. You'll need to
|
||||
instantiate the 4 bit full adder from step 5, step 7 and step 8. This is why
|
||||
they all need to have unique module names. You'll need to add three 4 bit
|
||||
wires for connecting the sum output of these new adders, as well as
|
||||
three 1 bit wires for connecting the cout output of these new adders.
|
||||
|
||||
10) Simulate and verify all of the models behave the same way.
|
||||
|
||||
Once this is done, and you have simulated the adders and shown that they all
|
||||
behave the same way, you'll have built the following types of modules
|
||||
- Structural Model (step 5)
|
||||
- Behavioral & Hierarchical Model (step 7)
|
||||
- Behavioral Model (step 8)
|
||||
|
||||
After that is done, people are encouraged to take the ALU presented in the
|
||||
slides and are encouraged to expand the functionality of the ALU to 8 total
|
||||
functions. The functions that should be added to the ALU are as follows:
|
||||
- r = ~A (R equals the complement of A)
|
||||
- r = A ^ B (R equals A xor B)
|
||||
- r = A << B (R equals A left shifted B bits)
|
||||
|
||||
After this functionality has been added to the ALU model, the test bench used
|
||||
for the 4 bit full adder can be modified to simulate the ALU.
|
||||
Steps to do this
|
||||
0) Copy the test bench and makefile to your working directory
|
||||
1) Add/remove wires and regs as needed
|
||||
2) Replace the DUT with the ALU
|
||||
3) Expand the inputs in order to test all of the ALU functions.
|
||||
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Full Adder Code
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
module full_adder(a, b, cin, sum, cout);
|
||||
input a, b, cin;
|
||||
output sum, cout;
|
||||
|
||||
reg sum, cout;
|
||||
|
||||
always @(a or b or cin)
|
||||
begin
|
||||
sum = a ^ b ^ cin;
|
||||
cout= (a & b) | (a & cin) | (b & cin);
|
||||
end
|
||||
endmodule
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
module full_adder_4bit (a, b, cin, sum, cout);
|
||||
input[3:0] a, b;
|
||||
input cin;
|
||||
output [3:0] sum;
|
||||
output cout;
|
||||
|
||||
wire c1, c2, c3;
|
||||
|
||||
// instantiate 1-bit adders
|
||||
full_adder FA0(a[0],b[0], cin, sum[0], c1);
|
||||
full_adder FA1(a[1],b[1], c1, sum[1], c2);
|
||||
full_adder FA2(a[2],b[2], c2, sum[2], c3);
|
||||
full_adder FA3(a[3],b[3], c3, sum[3], cout);
|
||||
|
||||
endmodule
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
module test_adder;
|
||||
reg[3:0] a, b;
|
||||
reg cin;
|
||||
wire [3:0] sum;
|
||||
wire cout;
|
||||
|
||||
full_adder_4bit dut(a, b, cin,
|
||||
sum, cout);
|
||||
|
||||
initial
|
||||
begin
|
||||
a = 4'b0000;
|
||||
b = 4'b0000;
|
||||
cin= 1'b0;
|
||||
#50;
|
||||
a = 4'b0101;
|
||||
b = 4'b1010;
|
||||
// sum = 1111, cout= 0
|
||||
#50;
|
||||
a = 4'b1111;
|
||||
b = 4'b0001;
|
||||
// sum = 0000, cout= 1
|
||||
#50;a = 4'b0000;
|
||||
b = 4'b1111;
|
||||
cin= 1'b1;
|
||||
// sum = 0000, cout= 1
|
||||
#50;
|
||||
a = 4'b0110;
|
||||
b = 4'b0001;
|
||||
// sum = 1000, cout= 0
|
||||
end // initial begin
|
||||
|
||||
initial
|
||||
begin
|
||||
$dumpfile ("waves.lxt");
|
||||
$dumpvars(0,test_adder);
|
||||
end
|
||||
|
||||
endmodule// test_adder
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
ALU Code
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
module mul16(i0,i1,prod);
|
||||
input [15:0] i0,i1;
|
||||
output [31:0] prod;
|
||||
// this is a magnitude multiplier
|
||||
// signed arithmetic later
|
||||
assign prod = i0 * i1;
|
||||
endmodule
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
module add32(i0,i1,sum);
|
||||
input [31:0] i0,i1;
|
||||
output [31:0] sum;
|
||||
assign sum = i0 + i1;
|
||||
endmodule
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
module sub32(i0,i1,diff);
|
||||
input [31:0] i0,i1;
|
||||
output [31:0] diff;
|
||||
assign diff = i0 - i1;
|
||||
endmodule
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
module mux32two(i0,i1,sel,out);
|
||||
input [31:0] i0,i1;
|
||||
input sel;
|
||||
output [31:0] out;
|
||||
|
||||
assign out = sel? i1 : i0;
|
||||
endmodule
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
module mux32three(i0,i1,i2,sel,out);
|
||||
input [31:0] i0,i1,i2;
|
||||
input [1:0] sel;
|
||||
output [31:0] out;
|
||||
|
||||
reg[31:0] out;
|
||||
|
||||
always @ (i0 or i1 or i2 or sel)
|
||||
begin
|
||||
case (sel)
|
||||
2???b00: out = i0;
|
||||
2???b01: out = i1;
|
||||
2???b10: out = i2;
|
||||
default: out = 32???bx;
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
module alu(a, b, f, r);
|
||||
input [31:0] a, b;
|
||||
input [2:0] f;
|
||||
output [31:0] r;
|
||||
|
||||
// wire declarations
|
||||
wire [31:0] addmux_out, submux_out;
|
||||
wire [31:0] add_out, sub_out, mul_out;
|
||||
|
||||
// module declarations
|
||||
mux32two adder_mux(b, 32'd1, f[0], addmux_out);
|
||||
mux32two sub_mux(b, 32'd1, f[0], submux_out);
|
||||
add32 our_adder(a, addmux_out, add_out);
|
||||
sub32 our_subtracter(a, submux_out, sub_out);
|
||||
mul16 our_multiplier(a[15:0], b[15:0], mul_out);
|
||||
mux32three output_mux(add_out, sub_out, mul_out, f[2:1], r);
|
||||
|
||||
endmodule
|
||||
|
||||
[Category:FPGAWorkshop](Category:FPGAWorkshop "wikilink")
|
||||
Reference in New Issue
Block a user