verilog实现简单的除法运算

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

verilog实现简单的除法运算_第1张图片
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]

仿真结果:
verilog实现简单的除法运算_第2张图片
verilog实现简单的除法运算_第3张图片

你可能感兴趣的:(FPGA基础)