2013-10-17 64 views
-2
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對於無符號和無符號的數字應該產生不同的結果。但我不知道如何去做。可有一個人幫我*/輸入必須註冊,然後必須採取2的補碼數量只有

 generate 
     if(TWOSCOMP==1) 
    [email protected](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) 
    [email protected](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 
    [email protected](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 // [email protected] (posedge i_clk or posedge i_rst or posedge i_start) 

    //always block to transverse through the states 
    [email protected](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 // [email protected] (posedge i_clk or posedge i_rst) 

    [email protected](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 // [email protected] (state,i_start,product_i,count_i) 

    generate 
     if(TWOSCOMP==1) 
    [email protected](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) 
    [email protected](state,i_start,product_i,count_i) 
     begin 
     o_product<=product_i; 
     end 
    endgenerate 

    [email protected](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 
+0

你能澄清你通過寄存器輸入的意思,你想把它們通過觸發器? – Morgan

+1

好問題顯示重新創建問題的最小代碼,您用於處理TWOCOMP添加複雜問題的生成。這增加了我們閱讀和理解問題的時間。幫助我們來幫助你。 – Morgan

+0

是的,我想讓他們通過觸發器 – uma

回答

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