2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 读书笔记:数字逻辑基础与verilog设计之数字系统设计流程03----------二进制除法器电路设计

读书笔记:数字逻辑基础与verilog设计之数字系统设计流程03----------二进制除法器电路设计

时间:2022-10-21 16:11:30

相关推荐

读书笔记:数字逻辑基础与verilog设计之数字系统设计流程03----------二进制除法器电路设计

除法器(除法算法)是一类算法。给定两个整数 N(分子)和 D(分母),计算它们的商和(或)余数。其中某些算法可以通过人工手动计算,而另一些则需要依赖数字电路的设计或软件。[1]除法算法主要分为两类:慢除法快除法。慢除法在每次迭代的过程中给出结果(商)的一位数字。慢除法包括复原法(restoring)、非复原法(non-restoring)和SRT除法等。快除法从商的一个近似估计开始,并且在每次迭代过程中产生有效位数为最终商的两倍多的中间值。Newton-Raphson和GoldSchmidt属于这一类。-----维基百科

本文所讲的除法器主要针对正整数的除法运算,使用的是慢除法的设计思想。

上篇博客中提到乘法器是被乘数左移相加,而除法器刚好相反,是被除数左移相减。

一、实现思想

除法器实现思想:假设被除数data_a[3:0]=‘b0101,除数data_b[1:0]='b11,

要想实现data_a[3:0]÷data_b[1:0] = result[3:0]......remainder[3:0],需要以下步骤:

1、定义两个寄存器变量result[3:0]和remainder[3:0];

2、每个时钟周期将data_a[3:0]向左移移位,移出的那一位送到remainder的最低位,即remainder <= {remainder[2:0],移出的那一位};

3、比较移位后的remainder[3:0]与data_b[1:0]的大小,若remainder[3:0]>=data_b[1:0],则remainder[3:0]-data_b[1:0],同时result最低左移入1;若remainder[3:0]<=data_b[1:0],则remainder[3:0保持不变,同时result最低位左移入0;

4、判断data_a[3:0]移位完成,若未完成,重复步骤2-3,反之输出完成标志信号。

二、对应的算法状态机

按照上述除法器的实现思想,可以画出除法器的实现流程,如下所示:

图1 算法状态机

图1中算法状态机描述了除法器的实现思想,接下来就可以根据算法状态机来画实现该电路的数据路径。

三、数据路径

图2 数据路径

数据路径如图2所示,左移寄存器data_a在每个时钟周期将移出的数据data_bit0送给remainder移位寄存器的最低位,移位后的数据跟data_b相减是在en_c信号控制下进行的,同时result移位寄存器最低位移入0还是1也是由en_c决定的。这些信号何时有效在接下来的控制信号的流程图中都可以明确的给出。

四、控制信号

图3 控制信号

根据图1和图2确定了使能信号在哪个状态应该使能,其中flag信号是移位完成标志信号。其余信号分别是寄存器和加法器的使能信号和加载信号,对比图2可以理清这些信号的功能。

五、verilog描述

接下来使用verilog描述上述数据路径,代码如下:

顶层代码:

module divider(input clk,input rst,input start,input load_a,input load_b,input [3:0]data_a,input [1:0]data_b,output [3:0]result,output [3:0]remainder,output reg done);wire flag;reg en_a;reg en_b;reg en_c;reg load_c;wire valid;//wire [3:0]remainder;parameter s0 = 'b001;parameter s1 = 'b010;parameter s2 = 'b100;reg [2:0]current_state = 'd0;reg [2:0]next_state = 'd0;reg en_o = 'd0;///结果移位使能信号///次态向现态转移always @(posedge clk)if(!rst)current_state <= s0;elsecurrent_state <= next_state;///次态生成always@(*)case(current_state)s0:beginif(start)next_state <= s1;elsenext_state <= s0;ends1:beginif(flag)next_state <= s2;elsenext_state <= s1;ends2:beginif(!start)next_state <= s0;elsenext_state <= s2;enddefault:next_state <= s0;endcase///输出结果赋值always@(*)case(current_state)s0:beginload_c = 'd1;en_a = 'd0;en_b = 'd0;en_c = 'd0;done = 'd0;en_o = 'd0;ends1:beginen_o = 'd1;load_c = 'd0;en_a = 'd1;en_b = 'd1;done = 'd0;if(valid&&(data_b!=0))beginen_c = 'd1;endelsebeginen_c = 'd0;endends2:beginload_c = 'd0;en_a = 'd0;en_b = 'd0;en_c = 'd0;done = 'd1;en_o = 'd0;enddefault:beginload_c = 'd1;en_a = 'd0;en_b = 'd0;en_c = 'd0;done = 'd0;en_o = 'd0;endendcasewire data_bit0;wire enb_control;// Instantiate the moduleleft_shifter left_shifter (.clk(clk), .en_a(en_a), .load_a(load_a), .data_a(data_a), .flag(flag),///移位完成标志位.enb_control(enb_control),.data_bit0(data_bit0));// Instantiate the moduleleft_shifter_se left_shifter_se (.clk(clk), .en_b(en_b), .en_c(en_c), .load_b(load_b), .data_bit0(data_bit0), .data_b(data_b), .valid(valid),.remainder(remainder),.enb_control(enb_control));// Instantiate the moduleresult_1 result_1 (.clk(clk), .load_c(load_c),.en_c(en_c), .en_o(en_o),.result(result));endmodule

data_a左移寄存器代码:

module left_shifter(input clk,input en_a,input load_a,input [3:0]data_a,output flag,output data_bit0,output enb_control);reg [3:0]data = 'd0;always @(posedge clk)if(load_a)begindata <= data_a;endelse if(en_a)begindata <= {data[2:0],1'b0};endelsebegindata <= data;endassign data_bit0 = data[3];reg [2:0]count = 'd0;always @(posedge clk)if(load_a)count <= 'd0;else if(en_a)count <= count + 'd1;elsecount <= count;assign flag = (count=='d4)?'d1:'d0;assign enb_control = (count=='d4)?'d0:'d1;endmodule

remainder左移寄存器及加法器代码:

module left_shifter_se(input clk,input en_b,//控制以为寄存器使能input en_c,//控制余数和被除数相减的减法器使能input load_b,input data_bit0,input [1:0]data_b,//被除数output reg valid = 'd0,output reg [3:0]remainder,input enb_control);reg [3:0]remainder_1 = 'd0;always @(posedge clk)if(load_b)remainder <= 'd0;else if(en_b&enb_control)remainder <= {remainder_1[2:0],data_bit0};elseremainder <= remainder_1;always @(*)if(load_b)remainder_1 = 'd0;else if(en_c)remainder_1 = remainder + (~data_b+1);elseremainder_1 = remainder;always @(*)if(remainder >= data_b)valid = 'd1;elsevalid = 'd0;endmodule

result左移寄存器代码:

module result_1(input clk,input en_c,input load_c,input en_o,output reg[3:0]result = 'd0);always @(posedge clk)if(load_c)result <= 'd0;else if(en_o)beginif(en_c)result <= {result[2:0],1'b1};elseresult <= {result[2:0],1'b0};endelseresult <= result;endmodule

仿真文件代码:

module test;// Inputsreg clk;reg rst;reg start;reg load_a;reg load_b;reg [3:0] data_a;reg [1:0] data_b;// Outputswire [3:0] result;wire [3:0]remainder;wire done;// Instantiate the Unit Under Test (UUT)divider uut (.clk(clk), .rst(rst), .start(start), .load_a(load_a), .load_b(load_b), .data_a(data_a), .data_b(data_b), .result(result), .remainder(remainder),.done(done));initial begin// Initialize Inputsclk = 0;rst = 0;start = 0;load_a = 0;load_b = 0;data_a = 0;data_b = 0;// Wait 100 ns for global reset to finish#100;// Add stimulus hereendalways #5 clk = ~clk;reg[4:0] cnt = 'd0;always @(posedge clk)if(cnt == 'd30)cnt <= 'd30;elsecnt <= cnt + 'd1;///复位信号always @(posedge clk)if(cnt <= 'd2)rst <= 'd0;elserst <= 'd1;//加载信号和数据always @(posedge clk)if((cnt> 'd2)&&(cnt < 'd5))beginload_a <= 'd1;load_b <= 'd1;data_a <= 'd5;data_b <= 'd3;endelsebeginload_a <= 'd0;load_b <= 'd0;data_a <= 'd0;data_b <= data_b;end///start信号always @(posedge clk)if((cnt> 'd8)&&(cnt < 'd25))start <= 'd1;elsestart <= 'd0;endmodule

Isim行为仿真结果:

图4 仿真波形

由仿真结果可知,在done信号拉高时,输出正确的除法结果。本实例中:data_a = 5,data_b=3;5 ÷ 3 = 1...2。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。