乘法器verilog实现

时间:2021-04-17 10:22:40

  今天重新补习了一下二进制原码,反码和补码之间的关系以及正数变负数,负数变正数之间的关系。瞬间感觉好晕,赶紧仔细研究:

  原码就是符号位加上真值的绝对值。正数原码是其本身,负数符号位为1.

  正数的反码和补码都是其本身,负数反码为符号位不变,其余各位依次取反;补码为符号位不变,其余各位依次取反后加1。

  这都好理解,那一个正数怎么变为负数呢?

注意计算机内存储负数是其补码形式! 正数取反后加1就得到负数(其实是负数的补码),例如:7二进制为0111;取反后为1000;然后+1为1001=(-7)补码。

同理负数取反+1后得到正数的补码=正数本身。

好了理清了上述关系 下面实现一个booth算法乘法器:

booth算法其实就是一种位操作,直接上例子

bit[1]

   bit[2]

  位操作

             0

0

   无操作

             0                1            +被乘数

             1

0

  -被乘数

             1                1            无操作

例如4*2 被乘数为4(0100),乘数为2(0010),都为4bit,因此result应有9bit空间。

第一步:被乘数正数:0100 负数为:1100,result={4’d0,0010,0}

第二步:判断result[1:0] ,为00 则无操作,result向右移一位,补高位与原来高位一致为result={4’d0,0001,0}

第三步:判断result[1:0],为10则减被乘数,result[9:6]+4’b1100={1100,0001,0},result向右移一位,高位补1,result={1110,0000,1}

第四步:判断result[1:0],为01则加被乘数,result[9:6]+4’b0100={0010,0000,1},result向右移一位,高位补0,result={0001,0000,0}

第五步:判断result[1:0],为00则无操作,result向右移一位,高位补0,result={0000,0001,0}

第六步:最后结果取result[9:1]={0000,1000}=8;

中间判断次数为寄存器宽度,即4bit执行4次,然后去高8为最后结果。

下面为位宽8bit的booth乘法器verilog代码:

//-----------------------------------------------------------------------------
// Title         : <title>
// Project       : <project>
//-----------------------------------------------------------------------------
// File          : multiplier.v
// Author        : caoshan
// Created       : <credate>
// Last modified : <moddate>
//-----------------------------------------------------------------------------
// Description :
// <description>
//-----------------------------------------------------------------------------
// Copyright (c) <copydate> by <company> This model is the confidential and
// proprietary property of <company> and the possession or use of this
// file requires a written license from <company>.
//------------------------------------------------------------------------------
// Modification history :
// <modhist>
//-----------------------------------------------------------------------------
module multiplier(/*autoarg*/
   // Outputs
   done_flag, mul_result,
   // Inputs
   clk, rst_n, start_en, mul_cand_data, mul_data
   );
  // parameter  WIDTH = 8;
   
   //system interface
   input             clk;
   input             rst_n;
   
   input             start_en;
   input [7:0] mul_cand_data;
   input [7:0] mul_data;

   output            done_flag;
   output [15:0] mul_result;
   
   

   /*autoinput*/
   /*autooutput*/
   /*autoreg*/
   // Beginning of automatic regs (for this module's undeclared outputs)
   reg                  done_flag;
   //reg [2*WIDTH-1:0]    mul_result;
   // End of automatics
   /*autowire*/
   //===========================================================
   // state machine
   //=======================================================
   parameter      IDLE = 3'd0;
   parameter      LOCK_DATA = 3'd1;
   parameter      IMPROVE_MC = 3'd2;
   parameter      IMPROVE_M = 3'd3;
   parameter      JUDGE  = 3'd4;
   parameter      MUL_MOV = 3'd5;
   parameter      MUL_END = 3'd6;

   reg [2:0]            curr_state;
   reg [2:0]            next_state;
   reg [7:0]      mul_cand_data_ff1;
   reg [7:0]      mul_cand_data_ff2;
   reg [7:0]     mul_data_ff;
   reg [16:0]      mul_result_ff;
   reg [7:0]      cnt;

 
   
   always @ (posedge clk or negedge rst_n)begin
      if(rst_n == 0)
        curr_state <= IDLE;
      else
        curr_state <= next_state;
   end

   always @ (*)begin
      next_state = IDLE;
      case(curr_state)
        IDLE:begin
           if(start_en)
             next_state = LOCK_DATA;
           else
             next_state = IDLE;
        end
    LOCK_DATA:begin
       next_state = IMPROVE_MC;
    end
    
        IMPROVE_MC:begin
           next_state = IMPROVE_M;
        end
    IMPROVE_M:begin
       next_state = JUDGE;
    end
        JUDGE:begin
             next_state = MUL_MOV;
        end
        MUL_MOV:begin
           if(cnt >= 7)
             next_state = MUL_END;
           else
             next_state = JUDGE;
        end
        MUL_END:begin
           next_state = IDLE;
        end
        default: next_state = IDLE;
      endcase // case (curr_state)
   end // always @ (*)
   //-------------------------------------
   //state machine change
   always@(posedge clk or negedge rst_n)begin
      if(rst_n==0)begin
         mul_cand_data_ff1 <= 0;
         mul_cand_data_ff2 <= 0;
     mul_data_ff <= 0;
      end
      
      else if(curr_state == IMPROVE_MC)begin
         mul_cand_data_ff1 <= mul_cand_data;
         mul_cand_data_ff2 <= ~mul_cand_data + 1'b1;
     mul_data_ff <= mul_data;
     
      end
   end

   always @ (posedge clk or negedge rst_n)begin
      if(rst_n == 0)
        mul_result_ff <= 0;
      else if(curr_state == IMPROVE_M)
        mul_result_ff <= {8'd0,mul_data_ff,1'b0};
      else if(curr_state == JUDGE)begin
         if(mul_result_ff[1:0]==2'b01)
           mul_result_ff <= {(mul_result_ff[16:9] + mul_cand_data_ff1[7:0]),mul_result_ff[8:0]};
         else if(mul_result_ff[1:0]== 2'b10)
           mul_result_ff <= {(mul_result_ff[16:9] + mul_cand_data_ff2[7:0]),mul_result_ff[8:0]};
      end
      else if(curr_state == MUL_MOV)
        mul_result_ff <= {mul_result_ff[16],mul_result_ff[16:1]};
   end // always @ (posedge clk or negedge rst_n)

   always @ (posedge clk or negedge rst_n)begin
      if(rst_n == 0)
        cnt <= 0;
      else if((curr_state == MUL_MOV)&&(cnt < 7))
        cnt <= cnt + 1'b1;
      else if((cnt >=7 )&&(curr_state == MUL_END))
        cnt <= 0;
   end

   always@(posedge clk or negedge rst_n)begin
      if(rst_n == 0)
        done_flag <= 0;
      else if(curr_state == MUL_END)
        done_flag <= 1;
      else
        done_flag <= 0;
   end
   reg[16:0] mul_result_ff2;
   always @ (posedge clk or negedge rst_n)begin
      if(rst_n == 0)
        mul_result_ff2 <= 0;
      else if(curr_state == MUL_END)
        mul_result_ff2 <= mul_result_ff;
   end
   
   
   assign mul_result = mul_result_ff2[16:1];
          
   endmodule //

testbench:

//-----------------------------------------------------------------------------
// Title         : <title>
// Project       : <project>
//-----------------------------------------------------------------------------
// File          : test_bench.v
// Author        : cs
// Created       : <credate>
// Last modified : <moddate>
//-----------------------------------------------------------------------------
// Description :
// <description>
//-----------------------------------------------------------------------------
// Copyright (c) <copydate> by <company> This model is the confidential and
// proprietary property of <company> and the possession or use of this
// file requires a written license from <company>.
//------------------------------------------------------------------------------
// Modification history :
// <modhist>
//-----------------------------------------------------------------------------
module testbench();
   reg             clk;
   reg             rst_n;
   
   reg             start_en;
   reg [7:0] mul_cand_data;
   reg [7:0] mul_data;

   wire            done_flag;
   wire [15:0] mul_result;

   //------------------------------------------------------------------------------
   multiplier u_multiplier(/*autoinst*/
               // Outputs
               .done_flag        (done_flag),
               .mul_result        (mul_result[15:0]),
               // Inputs
               .clk            (clk),
               .rst_n        (rst_n),
               .start_en        (start_en),
               .mul_cand_data    (mul_cand_data[7:0]),
               .mul_data        (mul_data[7:0]));
   always #20 clk = ~clk;

   initial
     begin
    clk = 0;
    rst_n = 0;
     # 100
       rst_n = 1;
     end
   reg [3:0] i;
   
   always@(posedge clk or negedge rst_n)begin
      if(rst_n==0)begin
     start_en <= 0;
     mul_cand_data <= 0;
     mul_data <= 0;
     i <= 0;
      end
      else
     case(i)
       0:begin
          if(done_flag)begin
         start_en = 0;
         i <= i + 1'b1;
         end
          else begin
         start_en <= 1'b1;
         mul_cand_data <= 8'd5;
         mul_data <= 8'd8;
          end
       end // case: 0
       1:begin
          if(done_flag)begin
         start_en = 0;
         i <= i + 1'b1;
         end
          else begin
         start_en <= 1'b1;
         mul_cand_data <= 8'b11111100;
         mul_data <= 8'd4;
          end          
       end // case: 1
       2:begin
          if(done_flag)begin
         start_en = 0;
         i <= i + 1'b1;
         end
          else begin
         start_en <= 1'b1;
         mul_cand_data <= 8'd127;
         mul_data <= 8'b10000001;
          end
       end // case: 2
       3:begin
          if(done_flag)begin
         start_en = 0;
         i <= i + 1'b1;
         end
          else begin
         start_en <= 1'b1;
         mul_cand_data <= 8'b10000001;
         mul_data <= 8'b10000001;
          end
       end // case: 3
       4:begin
          i<=4'd4;
          mul_cand_data <= 0;
          mul_data      <= 0;
       end
     endcase // case (i)
   end // always@ (posedge clk or negedge rst_n)
     initial
     begin
    $fsdbDumpfile ("./testbench.fsdb");
    $fsdbDumpvars; //
     end 
endmodule

仿真结果

乘法器verilog实现

                                                                                                                                                                                                                                                                                                                      2015年4月9日

                                                                                                                                                                                                                                                                                                                           cslegend