一位全加器原理
法1 串行一位加法器法
一位全加器
module adder_1bit(
input din_one, //第一个加数
input din_two, //第二个加数
input cin, //进位输入
output sum, //和输出
output cout //进位输出
);
//利用连续赋值语句实现全加操作
assign sum = din_one ^ din_two ^ cin;
assign cout = (din_one & din_two) | (din_two & cin) | (din_one & cin);
endmodule
2bit
module adder_2bit(
input [1 : 0] din_one, //第一个加数
input [1 : 0] din_two, //第二个加数
input cin, //进位输入
output [1 : 0] sum, //和输出
output cout //进位输出
);
wire cin_0bit; //低位加法的进位输出
//实例化adder_1bit实现低位加法
adder_1bit U1_low_bit(
.din_one(din_one[0]),
.din_two(din_two[0]),
.cin(cin),
.sum(sum[0]),
.cout(cin_0bit)
);
//实例化adder_1bit实现高位加法
adder_1bit U2_high_bit(
.din_one(din_one[1]),
.din_two(din_two[1]),
.cin(cin_0bit),
.sum(sum[1]),
.cout(cout)
);
//利用模块实例化语句实现2位全加操作
endmodule
4bit
module adder_4bit(
input [3 : 0] din_one, //第一个加数
input [3 : 0] din_two, //第二个加数
input cin, //进位输入
output [3 : 0] sum, //和输出
output cout //进位输出
);
wire cin_0bit; //低位加法的进位输出
//实例化adder_1bit实现低位加法
adder_2bit U1_low_bit(
.din_one(din_one[1 : 0]),
.din_two(din_two[1 : 0]),
.cin(cin),
.sum(sum[1 : 0]),
.cout(cin_0bit)
);
//实例化adder_1bit实现高位加法
adder_2bit U2_high_bit(
.din_one(din_one[3 : 2]),
.din_two(din_two[3 : 2]),
.cin(cin_0bit),
.sum(sum[3 : 2]),
.cout(cout)
);
//利用模块实例化语句实现2位全加操作
endmodule
法2 并行加法器
思路 :直接用加法运算符“+”实现。直接表示
/*******************8位加法器 ***********************/
module adder_nonpipe(cout, sum, ina, inb, cin, enable);
output cout;
output [7:0] sum;
input [7:0] ina, inb;
input cin, enable;
reg cout;
reg [7:0] sum;
reg [7:0] tempa, tempb;
reg tempc;
always @(posedge enable)
begin
tempa <= ina;
tempb <= inb;
tempc <= cin;
end
always @(posedge enable)
begin
{cout,sum} <= tempa + tempb + tempc;
end
endmodule
法3 参数化
module N_bit_add(
clk ,
rst_n ,
//其他信号,举例dout
A ,
B ,
Cin ,
dout ,
sout
);
//参数定义
parameter DATA_W = 8;
//输入信号定义
input clk ;
input rst_n ;
input Cin ;
input[DATA_W-1:0] A ;
input[DATA_W-1:0] B ;
//输出信号定义
output[DATA_W-1:0] dout ;
output sout ;
//进位位,S[7]为输出最后进位
reg [DATA_W-1:0] S ;
genvar i;
generate for(i=0;i<DATA_W;i=i+1)
begin:one_bit_add
if(i==0)begin
assign dout[i]=A[i]^B[i]^Cin;
assign S[i]=(A[i]&B[i])|(A[i]&Cin)|(Cin&B[i]);
end
else begin
assign dout[i]=A[i]^B[i]^S[i-1];
assign S[i]=(A[i]&B[i])|(A[i]&Cin;)|(Cin&B[i]);
end
end
endgenerate
assign sout=S[7];
endmodule
法4流水线
1 /*******************8位2级流水加法器*************************/
2 module adder_pipeline(cout, sum, ina, inb, cin, enable);
3
4 output cout;
5 output [7:0] sum;
6 input [7:0] ina, inb;
7 input cin, enable;
8
9 reg cout;
10 reg [7:0] sum;
11
12 reg [3:0] tempa, tempb, firsts;
13 reg firstc;
14 always @(posedge enable)
15 begin
16 {firstc,firsts} = ina[3:0] + inb[3:0] + cin;
17 tempa = ina[7:4]; //高4位输入寄存,使其与sum低4位在下级流水线同步输入。
tempb = inb[7:4]; //否则sum的高4位,与低四位分两个时钟周期输出
18 end
19
20 always @(posedge enable)
21 begin
22 {cout,sum[7:4]} = tempa + tempb + firstc;
23 sum[3:0] = firsts; //不能合并为{cout, sum} = {tempa + tempb + firstc, firsts}; 位宽不匹配
24 end
25
26 endmodule
四级流水线
module adder_pipeline(rst_n,
clk,
a,
b,
cin,
sum
);
parameter DATA_SIZE = 8;
input rst_n;
input clk;
input [DATA_SIZE - 1 : 0] a;
input [DATA_SIZE - 1 : 0] b;
input cin;
output [DATA_SIZE : 0] sum;
reg [DATA_SIZE - 1 : 0] a_r;
reg [DATA_SIZE - 1 : 0] b_r;
reg cin_r;
reg [DATA_SIZE : 0] sum;
reg [1:0] stage0_sum;
reg stage0_cout;
reg [DATA_SIZE - 1 : 0] stage0_a_r;
reg [DATA_SIZE - 1 : 0] stage0_b_r;
//reg [4:0] stage1_sum;
reg [3:0] stage1_sum;
reg stage1_cout;
reg [DATA_SIZE - 1 : 0] stage1_a_r;
reg [DATA_SIZE - 1 : 0] stage1_b_r;
//reg [6:0] stage2_sum;
reg [5:0] stage2_sum;
reg stage2_cout;
reg [DATA_SIZE - 1 : 0] stage2_a_r;
reg [DATA_SIZE - 1 : 0] stage2_b_r;
//reg [8:0] stage3_sum;
reg [7:0] stage3_sum;
reg stage3_cout;
always@(posedge clk)
if(!rst_n)
begin
a_r <= 8'd0;
b_r <= 8'd0;
cin_r <= 1'b0;
end
else
begin
a_r <= a;
b_r <= b;
cin_r <= cin;
end
always@(posedge clk)
if(!rst_n)
begin
{stage0_cout,stage0_sum} <= 3'd0;
stage0_a_r <= 8'd0;
stage0_b_r <= 8'd0;
end
else
begin
//{stage0_cout,stage0_sum} <= a_r[1:0] + b_r[1:0] + cin_r;
{stage0_cout,stage0_sum} <= {1'b0,a_r[1:0]} + {1'b0,b_r[1:0]} + cin_r;
stage0_a_r <= a_r;
stage0_b_r <= b_r;
end
always@(posedge clk)
if(!rst_n)
begin
{stage1_cout,stage1_sum} <= 5'd0;
stage1_a_r <= 8'd0;
stage1_b_r <= 8'd0;
end
else
begin
//{stage1_cout,stage1_sum} <= { {a_r[3:2] + b_r[3:2] + stage0_cout},{stage0_sum} };
//{stage1_cout,stage1_sum} <= { {{1'b0,a_r[3:2]} + {1'b0,b_r[3:2]} + stage0_cout},{stage0_sum} };
//{stage1_cout,stage1_sum} <= { {1'b0,a_r[3:2]} + {1'b0,b_r[3:2]} + stage0_cout,stage0_sum };
//{stage1_cout,stage1_sum} = { {a_r[3],a_r[3:2]} + {b_r[3],b_r[3:2]} + stage0_cout,stage0_sum };
{stage1_cout,stage1_sum} <= { {1'b0,stage0_a_r[3:2]} + {1'b0,stage0_b_r[3:2]} + stage0_cout,stage0_sum };
stage1_a_r <= stage0_a_r;
stage1_b_r <= stage0_b_r;
end
always@(posedge clk)
if(!rst_n)
begin
{stage2_cout,stage2_sum} <= 7'd0;
stage2_a_r <= 8'd0;
stage2_b_r <= 8'd0;
end
else
begin
{stage2_cout,stage2_sum} <= { {1'b0,stage1_a_r[5:4]} + {1'b0,stage1_b_r[5:4]} + stage1_cout,stage1_sum };
stage2_a_r <= stage1_a_r;
stage2_b_r <= stage1_b_r;
end
always@(posedge clk)
if(!rst_n)
begin
{stage3_cout,stage3_sum} <= 9'd0;
end
else
begin
{stage3_cout,stage3_sum} <= { {stage2_a_r[7],stage2_a_r[7:6]} + {stage2_b_r[7],stage2_b_r[7:6]} + stage2_cout,stage2_sum };
end
always@(posedge clk)
if(!rst_n)
begin
sum <= 9'd0;
end
else
begin
sum <= {stage3_cout,stage3_sum};
end
endmodule
testbench
`timescale 1 ns/1 ns
module tb();
//时钟周期,单位为ns,可在此修改时钟周期。
parameter CYCLE = 20;
//复位时间,此时表示复位3个时钟周期的时间。
parameter RST_TIME = 3 ;
parameter DATA_W = 4;
//时钟和复位
reg clk ;
reg rst_n;
//uut的输入信号
reg[DATA_W-1:0] A ;
reg[DATA_W-1:0] B ;
reg Cin;
//uut的输出信号
wire sout;
wire[DATA_W-1:0] dout;
//待测试的模块例化
N_bit_add #(.DATA_W(4))uut(
.clk (clk ),
.rst_n (rst_n ),
.A (A ),
.B (B ),
.Cin (Cin),
.dout (dout ),
.sout (sout )
);
//生成本地时钟50M
initial begin
clk = 0;
forever
#(CYCLE/2)
clk=~clk;
end
//产生复位信号
initial begin
rst_n = 1;
#2;
rst_n = 0;
#(CYCLE*RST_TIME);
rst_n = 1;
end
integer i;
//输入信号a赋值方式
initial begin
i=0;
#1;
//赋初值
Cin=0;
A= 0;
#(10*CYCLE);
//开始赋值
for (i=0;i<16;i=i+1)begin
A=i;
#(CYCLE/2);
end
end
integer j;
initial begin
j=0;
#1;
//赋初值
B = 0;
#(10*CYCLE);
//开始赋值
for (j=0;j<16;j=j+1)begin
B=j;
#(CYCLE/2);
end
end
endmodule
ref
https://www.cnblogs.com/youngforever/archive/2013/06/08/3127204.html