用 Verilog 设计一个3-8译码器、一个多位全加器和一个16位算术逻辑单元 (ALU)
1. 3-8译码器
译码器的编辑与生成
3-8译码器的 verilog 代码如下:
module decoder74LS138 (
output reg [7:0] out,
input [2:0] in
);
always@(*)
case (in)
0: out = 8'b00000001;
1: out = 8'b00000010;
2: out = 8'b00000100;
3: out = 8'b00001000;
4: out = 8'b00010000;
5: out = 8'b00100000;
6: out = 8'b01000000;
7: out = 8'b10000000;
endcase
endmodule
生成的 RTL 电路如下:
译码器的仿真测试
3-8译码器仿真测试的 verilog 代码如下:
`timescale 1ns/1ns
module tb_decoder74LS138();
reg [2:0] in;
wire [7:0] out;
initial begin
in = 0;
end
always #10 in <= {$random} % 8;
initial begin
$timeformat(-9, 0, "ns", 6);
$monitor("@time %t:in=%b out=%b", $time, in, out);
end
decoder74LS138 decoder74LS138_ins
(
.in(in),
.out(out)
);
endmodule
仿真测试波形图如下:
Transcript 结果如下:
# @time 0ns:in=000 out=00000001
# @time 10ns:in=100 out=00010000
# @time 20ns:in=001 out=00000010
# @time 40ns:in=011 out=00001000
# @time 50ns:in=101 out=00100000
# @time 80ns:in=010 out=00000100
# @time 90ns:in=001 out=00000010
# @time 100ns:in=101 out=00100000
# @time 110ns:in=110 out=01000000
# @time 120ns:in=101 out=00100000
# @time 140ns:in=100 out=00010000
# @time 150ns:in=001 out=00000010
# @time 160ns:in=110 out=01000000
# @time 170ns:in=101 out=00100000
# @time 180ns:in=010 out=00000100
# @time 190ns:in=101 out=00100000
# @time 200ns:in=111 out=10000000
# @time 210ns:in=010 out=00000100
# @time 220ns:in=111 out=10000000
# @time 230ns:in=010 out=00000100
# @time 240ns:in=110 out=01000000
# @time 250ns:in=000 out=00000001
# @time 260ns:in=101 out=00100000
# @time 270ns:in=100 out=00010000
# @time 280ns:in=101 out=00100000
# @time 310ns:in=011 out=00001000
# @time 320ns:in=010 out=00000100
# @time 330ns:in=000 out=00000001
# @time 350ns:in=010 out=00000100
# @time 360ns:in=101 out=00100000
# @time 370ns:in=110 out=01000000
# @time 380ns:in=011 out=00001000
# @time 390ns:in=101 out=00100000
# @time 400ns:in=011 out=00001000
# @time 420ns:in=101 out=00100000
# @time 430ns:in=010 out=00000100
# @time 440ns:in=110 out=01000000
# @time 450ns:in=101 out=00100000
# @time 460ns:in=111 out=10000000
# @time 470ns:in=011 out=00001000
# @time 480ns:in=010 out=00000100
# @time 500ns:in=100 out=00010000
# @time 510ns:in=010 out=00000100
# @time 530ns:in=001 out=00000010
# @time 540ns:in=000 out=00000001
# @time 560ns:in=001 out=00000010
# @time 570ns:in=011 out=00001000
# @time 580ns:in=110 out=01000000
# @time 610ns:in=100 out=00010000
# @time 620ns:in=010 out=00000100
# @time 630ns:in=011 out=00001000
# @time 640ns:in=001 out=00000010
# @time 650ns:in=101 out=00100000
# @time 660ns:in=111 out=10000000
# @time 670ns:in=011 out=00001000
# @time 680ns:in=010 out=00000100
# @time 690ns:in=110 out=01000000
# @time 700ns:in=101 out=00100000
# @time 710ns:in=001 out=00000010
# @time 730ns:in=010 out=00000100
# @time 740ns:in=100 out=00010000
# @time 750ns:in=111 out=10000000
# @time 770ns:in=000 out=00000001
# @time 780ns:in=111 out=10000000
# @time 800ns:in=100 out=00010000
# @time 810ns:in=011 out=00001000
# @time 820ns:in=001 out=00000010
# @time 840ns:in=000 out=00000001
# @time 850ns:in=111 out=10000000
# @time 860ns:in=001 out=00000010
# @time 870ns:in=110 out=01000000
# @time 880ns:in=100 out=00010000
# @time 890ns:in=010 out=00000100
# @time 900ns:in=000 out=00000001
# @time 910ns:in=111 out=10000000
# @time 920ns:in=101 out=00100000
# @time 930ns:in=010 out=00000100
# @time 940ns:in=110 out=01000000
# @time 950ns:in=101 out=00100000
# @time 960ns:in=001 out=00000010
# @time 970ns:in=111 out=10000000
# @time 980ns:in=011 out=00001000
# @time 990ns:in=101 out=00100000
2. 全加器
用门级描述方式生成的全加器
1位全加器
verilog 代码
module full_adder_structural(a, b, cin, sum, cout);
input a, b, cin;
output sum, cout;
wire t1, t2, t3, t4;
and u1(t1, a, b);
and u2(t2, a, cin);
and u3(t3, b, cin);
or u4(cout, t1, t2, t3);
xor u5(t4, a, b);
xor u6(sum, t4, cin);
endmodule
RTL 图
4个1位全加器级联构成的4位串行全加器
verilog 代码
module serial_carry_adder_4bit_structural (
input [3:0] a, b,
input cin,
output [3:0] sum,
output cout
);
wire [4:0] c;
assign c[0] = cin;
full_adder_structural fa_0(a[0], b[0], c[0], sum[0], c[1]);
full_adder_structural fa_1(a[1], b[1], c[1], sum[1], c[2]);
full_adder_structural fa_2(a[2], b[2], c[2], sum[2], c[3]);
full_adder_structural fa_3(a[3], b[3], c[3], sum[3], c[4]);
assign cout = c[4];
endmodule
RTL 图
用行为级描述方式生成的全加器
1位全加器
verilog 代码
module full_adder (
input a, b, cin,
output sum, cout
);
assign sum = a ^ b ^ cin;
assign cout = (a & b) | (a & cin) | (b & cin);
endmodule
RTL 图
4个1位全加器级联构成的4位串行全加器
verilog 代码
module serial_carry_adder_4bit (
input [3:0] a, b,
input cin,
output [3:0] sum,
output cout
);
wire [4:0] c;
assign c[0] = cin;
full_adder fa_0(a[0], b[0], c[0], sum[0], c[1]);
full_adder fa_1(a[1], b[1], c[1], sum[1], c[2]);
full_adder fa_2(a[2], b[2], c[2], sum[2], c[3]);
full_adder fa_3(a[3], b[3], c[3], sum[3], c[4]);
assign cout = c[4];
endmodule
RTL 图
8个1位全加器级联构成的8位串行全加器
verilog 代码
与4位串行全加器类似。
module serial_carry_adder_8bit (
input [7:0] a, b,
input cin,
output [7:0] sum,
output cout
);
wire [8:0] c;
assign c[0] = cin;
full_adder fa_0(a[0], b[0], c[0], sum[0], c[1]);
full_adder fa_1(a[1], b[1], c[1], sum[1], c[2]);
full_adder fa_2(a[2], b[2], c[2], sum[2], c[3]);
full_adder fa_3(a[3], b[3], c[3], sum[3], c[4]);
full_adder fa_4(a[4], b[4], c[4], sum[4], c[5]);
full_adder fa_5(a[5], b[5], c[5], sum[5], c[6]);
full_adder fa_6(a[6], b[6], c[6], sum[6], c[7]);
full_adder fa_7(a[7], b[7], c[7], sum[7], c[8]);
assign cout = c[8];
endmodule
RTL 图(1位全加器内部已省略)
3. 算术逻辑单元 (ALU)(16位)
verilog 代码
代码中的 n 表示位数,这里 n = 16.
//16bit arithmetic and logic unit(ALU)
module ALU_16bit#(
parameter n = 16
)(
input [n-1:0] opA, //INPUT operand A
input [n-1:0] opB, //INPUT operand B
input [3:0] S , //INPUT Signal that selects working mode
input wire M , //INPUT Signal that controls logical operation
input wire Cin, //INPUT signal that carry
output reg[n-1:0]DO,//OUTPUT DATA
output wire C , //OUTPUT Carry
output wire V , //Overflow
output wire N , //DO's sign bit
output wire Z //if DO is 0
);
reg [n-1:0] p;
reg [n-1:0] g;
reg [n:0] carry;
//main body
always@(opA,opB,S,M,Cin)
//need blocking assignment
begin
carry[0] = Cin;
g = {n{S[3]}}&opA&opB | {n{S[2]}}&opA&(~opB) | {n{(~M)}};
//Expand bits
//let every bit is S[3]/S[2]/(~M)
//by {n{}}
p = ~({n{S[3]}}&opA&opB | {n{S[2]}}&opA&(~opB) | {n{S[1]}}&(~opA)&opB | {n{S[0]}}&(~opA)&(~opB));
//Expand bits
//let every bit is S[3]/S[2]/S[1]/S[0]
//by {n{}}
carry[n:1] = g|(p&carry[n-1:0]);
DO = p^carry[n-1:0];
end
//CVNZ analysis
assign C = carry[n];//carry is the MSD of carry[n,0]
assign V = (opA[n-1]&opB[n-1]&~DO[n-1]) | (~opA[n-1]&~opB[n-1]&DO[n-1]);//1:overflow;0:not
assign N = DO[n-1];//sign bit is the MSD
assign Z = (!(DO))?1:0;//if all bits are 0,then Z=1,else Z=0;
endmodule
RTL 图