verilog实现简单的除法运算

设计思路:
通过verilog实现除法有两大类,分别是:
基于减法操作。
基于乘法操作的算法。

在这里插入图片描述
8bit/8bit的除法实现
附录:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2019/07/29 16:11:22
// Design Name: 
// Module Name: test_div
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//      testbench         //
module test_div();   

reg               I_clk;
reg               I_rst_p;
reg               I_data_valid;      //输入有效信号
reg       [7:0]   I_data_a;        //被除数
reg       [7:0]   I_data_b;        //除数
wire                O_data_valid;
wire      [7:0]    O_data_shang;
wire      [7:0]    O_data_yushu;
c u_c(
       .I_clk(I_clk),
       .I_rst_p(I_rst_p),
       .I_data_valid(I_data_valid),
       .I_data_a(I_data_a),
       .I_data_b(I_data_b),
       .O_data_valid(O_data_valid),
       .O_data_shang(O_data_shang),
       .O_data_yushu(O_data_yushu)
);
always #3.125  I_clk <= ~I_clk;
initial begin
   I_clk  = 0;
   I_rst_p = 1;
   I_data_valid = 0;
   I_data_a = 0;
   I_data_b = 0;
   #10;
   I_rst_p = 0;
   #30;
   @(posedge I_clk ) 
      begin 
         I_data_valid = 1;
         I_data_a = {$random}%256; 
         I_data_b = {$random}%20;
      end
   repeat(18) @(posedge I_clk)    I_data_valid = 0;
   @(posedge I_clk ) 
      begin 
         I_data_valid = 1;
         I_data_a = {$random}%256; 
         I_data_b = {$random}%20;
      end
   repeat(18) @(posedge I_clk)    I_data_valid = 0;
   @(posedge I_clk ) 
      begin 
         I_data_valid = 1;
         I_data_a = {$random}%256; 
         I_data_b = {$random}%20;
      end
   repeat(10) @(posedge I_clk)    I_data_valid = 0;      
   @(posedge I_clk ) 
      begin 
         I_data_valid = 1;
         I_data_a = {$random}%256; 
         I_data_b = {$random}%20;
      end
   repeat(18) @(posedge I_clk)    I_data_valid = 0;;   
end

endmodule
module c(
                        input               I_clk,
                        input               I_rst_p,
                        input               I_data_valid,
                        input       [7:0]   I_data_a,
                        input       [7:0]   I_data_b,
                        output reg          O_data_valid,
                        output reg [7:0]    O_data_shang,
                        output reg [7:0]    O_data_yushu

    );
reg  [7:0]   tempa;
reg  [7:0]   tempb;
reg  [15:0]  temp_a;
reg  [15:0]  temp_b;
reg          div_start;
reg          div_start_d1;
wire         div_start_neg;
reg  [4:0]   div_cnt;
always@(posedge I_clk or posedge I_rst_p)
   begin
      if(I_rst_p)
         begin
            tempa <= 8'h0;            
            tempb <= 8'h0;            
         end
      else if(I_data_valid)
         begin
            tempa <= I_data_a;            
            tempb <= I_data_b;            
         end
      else
         begin
            tempa <= tempa;            
            tempb <= tempb;            
         end
   end

always@(posedge I_clk or posedge I_rst_p)
   begin
      if(I_rst_p)
         div_start <= 1'b0;
      else if(I_data_valid && div_start == 1'b0)
         div_start <= 1'b1;           //开始计算
      else if(div_cnt == 5'd16 )  //每16个时钟后开始下一次计算
         div_start <= 1'b0;
      else
          div_start <= div_start;
   end
//========================================================div_cnt  计数器
always@(posedge I_clk or posedge I_rst_p)
   if(I_rst_p)
      div_cnt <= 5'd0;
   else if(div_start)
      div_cnt <= div_cnt + 1;
   else
      div_cnt <= 5'd0;
//=======================================================           
always@(posedge I_clk or posedge I_rst_p)
   begin
      if(I_rst_p)
         begin
            temp_a <= 16'h0;
            temp_b <= 16'h0;            
         end
      else if(div_start )
         if(div_cnt == 4'd0)
            begin
               temp_a <= {8'h0,tempa};
               temp_b <= {tempb,8'h0};
            end
         else if(div_cnt[0] == 1'b1)
            begin
               temp_a <= {temp_a[14:0],1'b0};   //相当于乘2   或者左移一位
         else
            begin
               temp_a <= (temp_a[15:8] >= temp_b[15:8])?(temp_a - temp_b + 1):temp_a;
               //判断temp_a乘2之后取高8位与输入的除数比较大小 ,  8次移动完temp_a[15:8]<temp_b[15:8])
               //结果就是左边高temp_a[15:8]是余数,右边temp_a[7:0]是商
            end
      else
         begin
            temp_a <= 16'h0;
            temp_b <= 16'h0;              
         end
   end
always@(posedge I_clk)
   begin
      div_start_d1 <= div_start;                                      //延一拍
   end
assign div_start_neg = div_start_d1 & (~div_start);   //产生一个脉冲

always@(posedge I_clk or posedge I_rst_p)
   begin
      if(I_rst_p)
         begin
            O_data_valid <= 1'b0;
            O_data_shang <= 1'b0;
            O_data_yushu <= 1'b0;         
         end
      else if(div_start_neg)
         begin
            O_data_valid <= 1'b1;
            O_data_shang <= temp_a[7:0];
            O_data_yushu <= temp_a[15:8];              
         end
      else
         begin
            O_data_valid <= 1'b0;
            O_data_shang <= 1'b0;
            O_data_yushu <= 1'b0;          
         end
   end
endmodule

仿真结果:
在这里插入图片描述
在这里插入图片描述

### 回答1: 实现64位除法可以通过使用Verilog编写相应的硬件电路来完成。以下是一种可能的实现方法: 首先,我们需要将64位除数和被除数输入到电路中。我们可以使用两个64位输入端口来实现这一点。 接下来,我们需要设计一个计算器来执行除法操作。这个计算器将采用迭代的方式,根据除法的算法来计算商和余数。 首先,我们将寄存器设置为被除数的初始值,记作Dividend。然后我们将寄存器Q设置为一个全零的64位数,用于存储商的结果。 接着,我们需要开始迭代计算。在每一轮迭代中,我们将被除数寄存器Dividend左移1位,并将商寄存器Q左移1位。然后,将被除数寄存器Dividend的最低位设置为与除数相同的位(Dividend[0] = divisor[63])。 接下来,我们需要检查Dividend的最高位是否为1。若为1,则说明被除数大于或等于除数,此时需要执行减法操作。我们将被除数与除数相减,并存储在Dividend寄存器中。 如果Dividend的最高位为0,则说明被除数小于除数,此时不需要进行减法操作。 迭代计算将重复以上的步骤,直到所有的64位都被处理完毕。最后,我们将商存储在寄存器Q中,并输出。 需要注意的是,由于Verilog是一种描述硬件电路的语言,所以我们需要将上述步骤转化为适当的Verilog代码来实现所需的64位除法电路。 ### 回答2: 在Verilog实现64位除法需要进行多个步骤。首先,我们需要将被除数和除数拆分为64个位,并将其存储在两个64位寄存器中。接下来,我们可以使用迭代除法算法进行除法运算。 迭代除法算法的基本思想是将被除数和除数左移一位,并比较被除数是否大于除数,如果是,则将商的对应位设置为1,并将被除数减去除数;如果不是,则将商的对应位设置为0。然后再将被除数和除数左移一位,重复以上步骤,直到除数左移64次,完成整个除法运算。 此外,在进行除法运算之前,我们需要确保被除数和除数的符号位相同。如果不同,则可以使用二进制补码运算将它们转换为相同的符号,然后再进行除法运算。最后,我们需要将得到的商和余数存储在相应的寄存器中。 除法运算实现需要使用多个寄存器、比较器和加法器等硬件元件,它们可以通过Verilog语言进行描述、连接和编程。在整个过程中,我们还需要考虑到除数为零的情况,需要进行异常处理。 总的来说,实现64位除法需要结合迭代除法算法、二进制补码运算以及合适的硬件元件来完成。 ### 回答3: Verilog是一种硬件描述语言(HDL),用于设计和实现数字电路。要实现64位除法,可以使用Verilog编写一个除法器模块。 首先,我们需要定义输入和输出端口。对于64位除法,输入为被除数和除数,输出为商和余数。我们可以定义一个64位的有符号或无符号整数作为输入和输出端口。 接下来,我们可以使用组合逻辑和时序逻辑来实现除法器。在组合逻辑部分,我们将进行除法运算的计算。可以使用除法运算的一种常用算法,如非连续除法算法或布斯-库算法。 除法运算的核心过程是通过比较被除数和除数的大小来计算商和余数。我们可以使用循环来实现这一计算过程,直到被除数完全被除尽或达到最大除法迭代次数。 在时序逻辑部分,我们可以使用寄存器来存储中间计算结果。每次迭代时,更新寄存器的值,并将新的被除数和商存储在相应的寄存器中,以便在下一次迭代中使用。 最后,我们需要编写仿真脚本来测试除法器模块。通过提供不同的测试输入和验证输出,我们可以确保除法器能够正确地执行除法运算。 综上所述,要实现64位除法,我们可以使用Verilog编写一个基于组合逻辑和时序逻辑的除法器模块。通过定义适当的输入和输出端口,并使用适当的算法和寄存器,我们可以实现这个功能。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值