输入必须注册,然后必须采用2的补码数

时间:2013-10-17 12:00:59

标签: verilog

module multiplier(//global inputs
          i_clk,i_rst,
          //outputs
          o_product,o_done,
          //input
          i_multiplicant,i_multiplier,i_start
          );

   //parameter declarations
   parameter MULTIPLICANT_WIDTH =5;       //width for multiplicant
   parameter MULTIPLIER_WIDTH =5;        //width for multiplier
   parameter TWOSCOMP=0;                  //'1'=signed multiplication and '0'=unsigned multiplication
   parameter PRODUCT_WIDTH =(MULTIPLICANT_WIDTH+MULTIPLIER_WIDTH);   //width of the product  
   parameter NPOWER = 6;                           //multiplier width<=2**NPOWER
   parameter NULL_VECTOR_S = 32'h00000000;       //used to fill the upper part of product register with zero at the begining of multiplication
   parameter S0= 2'd0;
   parameter S1= 2'd1;
   parameter S2= 2'd2;  


   //global inputs
   input i_clk;
   input i_rst;

   //outputs
   output reg [PRODUCT_WIDTH-1:0] o_product;
   output             o_done;

   //input           
   input [MULTIPLICANT_WIDTH-1:0] i_multiplicant;
   input [MULTIPLIER_WIDTH-1:0]   i_multiplier;
   input              i_start;      //indicates start of multiplication

   // reg and wire declarations
   reg                o_done; 
   reg                sign_i;      //sign product
   reg [PRODUCT_WIDTH-1:0]    product_i; 
   reg [PRODUCT_WIDTH-1:0]    product_ii;  
   reg [NPOWER-1:0]           count_i;    
   reg [MULTIPLICANT_WIDTH-1:0]   multiplicant_i;
   reg [MULTIPLIER_WIDTH-1:0]     multiplier_i;
   reg                add_i;
   reg                shr_i;
   reg [1:0]              state=2'b00;
   reg [1:0]              nextstate=2'b00;

   //correcting the bits for signed multiplication  

/ *这是我试图使输入注册的地方..我没有得到任何错误,但FSM给出了问题。根据我的意思,无符号数的结果应该比签名产品提前2个周期。 FSM应该从不同的时间开始,对于无符号和无符号数字,应该以不同的方式生成o_done。但我不知道怎么做。有人可以帮助我* /

     generate
      if(TWOSCOMP==1) 
    always@(posedge i_clk or posedge i_rst)
      begin  
         if(i_rst)begin 
              multiplicant_i<=0;
              multiplier_i<=0;
             end  else begin
             $display("Testing signed numbers");
                 sign_i<= i_multiplicant[MULTIPLICANT_WIDTH-1] ^ i_multiplier[MULTIPLIER_WIDTH-1]; 
             multiplicant_i=rectify_multcnd(i_multiplicant,TWOSCOMP); 
         multiplier_i=rectify_mulplr(i_multiplier,TWOSCOMP);
     end 
     end 
   endgenerate 
  generate
      if(TWOSCOMP==0)
    always@(posedge i_clk or posedge i_rst)
      begin    
          if(i_rst==1) begin 
              multiplicant_i<=0;
              multiplier_i<=0;
              end else begin  
       $display("Testing unsigned numbers"); 
         multiplicant_i<=i_multiplicant;
         multiplier_i<=i_multiplier;
     end 
      end 
   endgenerate   


   //functionn to correct multiplicant bits   
   function [MULTIPLICANT_WIDTH-1:0]rectify_multcnd;    
      input [MULTIPLICANT_WIDTH-1:0]multiplicant;
      reg [MULTIPLICANT_WIDTH-1:0]  rec_v;
      input                 twoc;
      begin
     if((multiplicant[MULTIPLICANT_WIDTH-1] & twoc)==1)
       rec_v=~(multiplicant);
     else
       rec_v=multiplicant;
     rectify_multcnd=(rec_v+(multiplicant[MULTIPLICANT_WIDTH-1] & twoc));
      end
   endfunction
   //function to correct multipier bits            
   function [MULTIPLIER_WIDTH-1:0]rectify_mulplr;   
      input [MULTIPLIER_WIDTH-1:0]multiplier;
      reg [MULTIPLIER_WIDTH-1:0]  rec_v;
      input               twoc;
      begin
     if((multiplier[MULTIPLIER_WIDTH-1] & twoc)==1)
       rec_v=~(multiplier);
     else
       rec_v=multiplier;
     rectify_mulplr=(rec_v+(multiplier[MULTIPLIER_WIDTH-1] & twoc));
      end
   endfunction     

   //start of multiplication  
   always@(posedge i_clk or posedge i_rst) 
     begin
    if(i_rst==1)
      product_i<=18'd0;
    else begin 
       if(i_start==1) begin 
          product_i <= {NULL_VECTOR_S[MULTIPLICANT_WIDTH-1:0], multiplier_i}; 
       end  else if (add_i==1)
         product_i<= {{1'b0, product_i[PRODUCT_WIDTH-1:MULTIPLIER_WIDTH]} + {1'b0,multiplicant_i}, product_i[MULTIPLIER_WIDTH-1:1]};
       else if (shr_i==1)
         product_i<= {1'b0 , product_i[PRODUCT_WIDTH-1:1]};
    end 
     end // always@ (posedge i_clk or posedge i_rst or posedge i_start)

   //always block to transverse through the states   
   always@(posedge i_clk or posedge i_rst)
     begin
    if(i_rst==1)begin
       state<=S0;
       count_i<=0;
    end else begin
       state<=nextstate;
       if(state==S1) begin
          count_i<=count_i-1;   
       end 
       else if (state==S0)  begin 
          count_i<=(MULTIPLIER_WIDTH-1);
       end
    end 
     end // always@ (posedge i_clk or posedge i_rst)

   always@(state,i_start,product_i,count_i)
     begin                                
        case (state) 
          S0 :begin 
             add_i <= 0;
             shr_i <= 0;
             o_done <= 0;                                           
             if  (i_start==1) 
               nextstate <= S1; 
             else 
               nextstate <= S1;
      end 
          S1:begin
             o_done  <= 0;                                           
             add_i <= product_i[0]; 
             shr_i <= ~product_i[0];
             if (count_i==NULL_VECTOR_S [(MULTIPLIER_WIDTH-1):0])
               nextstate <= S2 ; 
             else 
               nextstate <= S1;      
          end              
          S2 :begin  
             o_done  <= 1;                                           
             add_i <= 0;
             shr_i <= 0;
             nextstate <= S0;
      end 
      default:begin
             o_done  <= 0;                                           
             add_i <= 0;
             shr_i <= 0;                                           
             nextstate <= S0;
          end
    endcase // case (state)     
     end // always@ (state,i_start,product_i,count_i) 

   generate
      if(TWOSCOMP==1)
    always@(state,i_start,product_i,count_i)
      begin 
         if(sign_i ==1)
           product_ii<=((~(product_i)) + 1); 
         else
           product_ii<=product_i;
      end  
   endgenerate 

   generate
      if(TWOSCOMP==0)
    always@(state,i_start,product_i,count_i)
      begin 
         o_product<=product_i;
      end
   endgenerate 

   always@(posedge i_clk or posedge i_rst)
     begin
    if(i_rst==1)
      o_product<=0;
    else if(TWOSCOMP==1)begin 
       o_product<=product_ii;
    end  
     end     
endmodule // multiplier

1 个答案:

答案 0 :(得分:0)

要缓冲或注册输入,请取2的补码数:

module fubar(
  input                     clk,
  input                     rst_n,
  input                     twocomp, //Could be param
  input       signed [31:0] a,
  output reg         [31:0] abs_a
);
  //Buffer input
  reg signed [31:0] a_buf;
  always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
      a_buf <= 'b0;
    end
    else begin
      a_buf <= a;
    end
  end

  //If Two Comp mode enabled and input was negative
  // invert (absolute value)
  always @* begin
    if ((twocomp == 1'b1) && (a_buf[31] == 1'b1)) begin
      abs_a = -a_buf;
    end
    else begin
      abs_a = a;
    end
  end

endmodule