Verilog除法器设计(包含单步设计和流水线设计)

更新时间:2023-06-23 10:06:20 阅读: 评论:0

Verilog除法器设计(包含单步设计和流⽔线设计)
Verilog 除法器设计(包含单步设计和流⽔线设计)
1 除法器原理(定点)
和⼗进制除法类似,计算 27 除以 5 的过程如下所⽰:
除法运算过程如下:
(1) 取被除数的⾼⼏位数据,位宽和除数相同(实例中是 3bit 数据)。
(2) 将被除数⾼位数据与除数作⽐较,如果前者不⼩于后者,则可得到对应位的商为 1,两者做差得到第⼀步的余数;否则得到对应的商为0,将前者直接作为余数。
(3) 将上⼀步中的余数与被除数剩余最⾼位 1bit 数据拼接成新的数据,然后再和除数做⽐较。可以得到新的商和余数。
(4) 重复过程 (3),直到被除数最低位数据也参与计算。
需要说明的是,商的位宽应该与被除数保持⼀致,因为除数有可能为1。所以上述⼿动计算除法的实例中,第⼀步做⽐较时,应该取数字27 最⾼位 1 (3’b001) 与 3’b101 做⽐较。 根据此计算过程,设计位宽可配置的流⽔线式除法器,流⽔延迟周期个数与被除数位宽⼀致。
2 除法器设计
2.1 单步运算设计
单步除法计算时,单步被除数位宽(信号 dividend)需⽐原始除数(信号 divisor)位宽多 1bit 才不⾄于溢出。
为了便于流⽔,输出端需要有寄存器来存储原始的除数(信号 divisor 和 divisor_kp)和被除数信息(信号 dividend_ci 和
dividend_kp)。
单步的运算结果就是得到新的 1bit 商数据(信号 merchant)和余数(信号 remainder)。
为了得到最后的除法结果,新的 1bit 商数据(信号 merchant)还需要与上⼀周期的商结果(merchant_ci)进⾏移位累加。
单步运算单元设计如下(⽂件名 divider_cell.v):
// parameter M means the actual width of divisor
module    divider_cell
#(parameter N=5,
parameter M=3)
(
邓石如篆书input                    clk,
input                    rstn,
input                    en,
input [M:0]              dividend,
input [M-1:0]            divisor,
input [N-M:0]            merchant_ci , //上⼀级输出的商
input [N-M-1:0]          dividend_ci , //原始除数
output reg [N-M-1:0]      dividend_kp,  //原始被除数信息
output reg [M-1:0]        divisor_kp,  //原始除数信息
output reg                rdy ,
output reg [N-M:0]        merchant ,  //运算单元输出商
output reg [M-1:0]        remainder  //运算单元输出余数
);
always @(podge clk or negedge rstn) begin
if (!rstn) begin
rdy            <= 'b0 ;
merchant      <= 'b0 ;
remainder      <= 'b0 ;
divisor_kp    <= 'b0 ;
dividend_kp    <= 'b0 ;
end
el if (en) begin
rdy            <= 1'b1 ;
divisor_kp    <= divisor ;  //原始除数保持不变
dividend_kp    <= dividend_ci ;  //原始被除数传递
if (dividend >= {1'b0, divisor}) begin
merchant    <= (merchant_ci<<1) + 1'b1 ; //商为1
厂房出租合同remainder  <= dividend - {1'b0, divisor} ; //求余
end
el begin
merchant    <= merchant_ci<<1 ;  //商为0
remainder  <= dividend ;        //余数不变
end
end // if (en)
疙瘩汤做法el begin
rdy            <= 'b0 ;
merchant      <= 'b0 ;
remainder      <= 'b0 ;
divisor_kp    <= 'b0 ;
dividend_kp    <= 'b0 ;
end
end
endmodule
2.2 流⽔级例化
将单步计算的余数(信号 remainder)和原始被除数(信号 dividend)对应位的 1bit 数据重新拼接,作为新的单步被除数输⼊到下⼀级单步除法计算单元。
其中,被除数、除数、及商的数据信息也要在下⼀级运算单元中传递。
流⽔级模块例化完成除法的设计如下(⽂件名 divider_man.v):
//parameter N means the actual width of dividend
//using 29/5=5 (4)
module    divider_man
#(parameter N=5,
parameter M=3,
parameter N_ACT = M+N-1)
(
input                    clk,
input                    rstn,
input                    data_rdy ,  //数据使能
input [N-1:0]            dividend,  //被除数
input [M-1:0]            divisor,    //除数
output                    res_rdy ,
output [N_ACT-M:0]        merchant ,  //商位宽:N
output [M-1:0]            remainder ); //最终余数
wire [N_ACT-M-1:0]  dividend_t [N_ACT-M:0] ;
wire [M-1:0]        divisor_t [N_ACT-M:0] ;
wire [M-1:0]        remainder_t [N_ACT-M:0];
wire [N_ACT-M:0]    rdy_t ;
wire [N_ACT-M:0]    merchant_t [N_ACT-M:0] ;
//初始化⾸个运算单元
divider_cell      #(.N(N_ACT), .M(M))
u_divider_step0
( .clk              (clk),
.rstn            (rstn),
.en              (data_rdy),
//⽤被除数最⾼位 1bit 数据做第⼀次单步运算的被除数,⾼位补0
.dividend        ({{(M){1'b0}}, dividend[N-1]}),
.divisor          (divisor),
.merchant_ci      ({(N_ACT-M+1){1'b0}}),  //商初始为0
.dividend_ci      (dividend[N_ACT-M-1:0]), //原始被除数
//output
.
dividend_kp      (dividend_t[N_ACT-M]),  //原始被除数信息传递
.divisor_kp      (divisor_t[N_ACT-M]),    //原始除数信息传递
.rdy              (rdy_t[N_ACT-M]),
.merchant        (merchant_t[N_ACT-M]),  //第⼀次商结果
.remainder        (remainder_t[N_ACT-M])  //第⼀次余数
);
genvar              i ;
generate
for(i=1; i<=N_ACT-M; i=i+1) begin: sqrt_stepx
divider_cell      #(.N(N_ACT), .M(M))踌躇不前的意思
u_divider_step
(.clk              (clk),
.rstn            (rstn),
.en              (rdy_t[N_ACT-M-i+1]),
.dividend        ({remainder_t[N_ACT-M-i+1], dividend_t[N_ACT-M-i+1][N_ACT-M-i]}),  //余数与原始被除数单bit数据拼接              .divisor          (divisor_t[N_ACT-M-i+1]),
.merchant_ci      (merchant_t[N_ACT-M-i+1]),
.dividend_ci      (dividend_t[N_ACT-M-i+1]),
//output
.divisor_kp      (divisor_t[N_ACT-M-i]),
.dividend_kp      (dividend_t[N_ACT-M-i]),
.rdy              (rdy_t[N_ACT-M-i]),
.merchant        (merchant_t[N_ACT-M-i]),
.remainder        (remainder_t[N_ACT-M-i])
);
end // block: sqrt_stepx
endgenerate
assign res_rdy      = rdy_t[0];
assign merchant      = merchant_t[0];  //最后⼀次商结果作为最终的商
assign remainder    = remainder_t[0]; //最后⼀次余数作为最终的余数
endmodule
testbench
取被除数位宽为 5,除数位宽为 3,testbench 中加⼊⾃校验,描述如下:`timescale 1ns/1ns
module test ;
parameter    N = 5 ;
parameter    M = 3 ;
reg          clk;
reg          rstn ;
reg          data_rdy ;
reg [N-1:0]  dividend ;
reg [M-1:0]  divisor ;
wire        res_rdy ;
wire [N-1:0] merchant ;
wire [M-1:0] remainder ;
搬家吉利话//clock
always begin
clk = 0 ; #5 ;
clk = 1 ; #5 ;
end
//driver
initial begin
rstn      = 1'b0 ;
#8 ;
rstn      = 1'b1 ;
#55 ;
@(negedge clk ) ;
data_rdy  = 1'b1 ;
dividend  = 25;      divisor      = 5;
#10 ;  dividend  = 16;      divisor      = 3;
#10 ;  dividend  = 10;      divisor      = 4;
#10 ;  dividend  = 15;      divisor      = 1;
企业导师评语
repeat(32)    #10  dividend  = dividend + 1 ;
divisor      = 7;
repeat(32)    #10  dividend  = dividend + 1 ;
divisor      = 5;
repeat(32)    #10  dividend  = dividend + 1 ;
divisor      = 4;
repeat(32)    #10  dividend  = dividend + 1 ;
divisor      = 6;
repeat(32)    #10  dividend  = dividend + 1 ;
end
//对输⼊延迟,便于数据结果同周期对⽐,完成⾃校验
reg  [N-1:0]  dividend_ref [N-1:0];
reg  [M-1:0]  divisor_ref [N-1:0];
always @(podge clk) begin
dividend_ref[0] <= dividend ;
divisor_ref[0]  <= divisor ;
end
genvar        i ;
generate
for(i=1; i<=N-1; i=i+1) begin
always @(podge clk) begin
dividend_ref[i] <= dividend_ref[i-1];
divisor_ref[i]  <= divisor_ref[i-1];
divisor_ref[i]  <= divisor_ref[i-1];
end
end
endgenerate
//⾃校验
reg  error_flag ;
always @(podge clk) begin
# 1 ;
if (merchant * divisor_ref[N-1] + remainder != dividend_ref[N-1] && res_rdy) begin    //testbench 中可直接⽤乘号⽽不考虑运算周期            error_flag <= 1'b1 ;
end
el begin
error_flag <= 1'b0 ;
end
end
//module instantiation
divider_man  #(.N(N), .M(M))
u_divider
(
.clk              (clk),
.rstn            (rstn),
.data_rdy        (data_rdy),
.dividend        (dividend),
.divisor          (divisor),
.res_rdy          (res_rdy),
.merchant        (merchant),
.remainder        (remainder));
//simulation finish
initial begin
forever begin绿茶冲泡时间
#100;
英文摘要怎么写if ($time >= 10000)  $finish ;
end
end
endmodule // test
仿真结果

本文发布于:2023-06-23 10:06:20,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1051111.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:被除数   数据   原始   设计   除法   除数
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图