Verilog -- 无符号整数除法器(二)

Verilog -- 无符号整数除法器(二)

在 Verilog -- 任意整数除法器(一)中已经给出了一种除法器的组合逻辑实现,但是实际使用中可能还是需要讲组合逻辑插拍才能得到更好的性能。下面给出一种基于状态机的时序逻辑除法器实现。

这边先上一下算法流程图,跟之前的一样:

graph LR id0(32位整数a除以b)-->id1(a的高位扩展32位) id0(32位整数a除以b)-->id2(b的低位扩展32位) id1 --> id3(a左移一位) id2 --> id4{a>=b?} id3 --> id4 id4 -- 是 --> id5(a = a-b+1) id5 -->id6{移位次数<32} id4 --否-->id6 id6 --是--> id3 id6 --否--> id7(输出a)

下面是verilog代码:


`timescale 1ns/1ps


module div_fsm 
#(
parameter DATAWIDTH=8
)
(
  input                       clk      ,
  input                       rstn    ,
  input                       en   ,
  output  wire                ready    ,
  input  [DATAWIDTH-1:0]      dividend ,
  input  [DATAWIDTH-1:0]      divisor  ,
  output wire [DATAWIDTH-1:0] quotient ,
  output wire [DATAWIDTH-1:0] remainder,
  output wire                 vld_out
);

reg [DATAWIDTH*2-1:0] dividend_e ;
reg [DATAWIDTH*2-1:0] divisor_e  ;
reg [DATAWIDTH-1:0]   quotient_e ;
reg [DATAWIDTH-1:0]   remainder_e;


reg [1:0] current_state,next_state;

reg [DATAWIDTH-1:0] count;

parameter IDLE =2'b00   ,
          SUB  =2'b01   ,
		  SHIFT=2'b10   ,
		  DONE =2'b11   ;



always@(posedge clk or negedge rstn)
  if(!rstn) current_state <= IDLE;
  else current_state <= next_state;

always @(*) begin
  next_state <= 2'bx;
  case(current_state)
    IDLE: if(en)     next_state <=  SUB;
	      else       next_state <=  IDLE;
    SUB:  next_state <= SHIFT;
    SHIFT:if(count<DATAWIDTH) next_state <= SUB;
          else next_state <= DONE;
    DONE: next_state      <= IDLE;
  endcase
end

 
always@(posedge clk or negedge rstn) begin
 if(!rstn)begin
   dividend_e  <= 0;
   divisor_e   <= 0;
   quotient_e  <= 0;
   remainder_e <= 0;
   count       <= 0;
 end 
 else begin 
  case(current_state)
  IDLE:begin
         dividend_e <= {{DATAWIDTH{1'b0}},dividend};
	     divisor_e  <= {divisor,{DATAWIDTH{1'b0}}};
       end
  SUB:begin
        if(dividend_e>=divisor_e)begin
           quotient_e <= {quotient_e[DATAWIDTH-2:0],1'b1};
		   dividend_e <= dividend_e-divisor_e;
         end
	    else begin
	       quotient_e <= {quotient_e[DATAWIDTH-2:0],1'b0};
		   dividend_e <= dividend_e;
        end
      end
  SHIFT:begin
	   if(count<DATAWIDTH)begin
	     dividend_e <= dividend_e<<1;
	     count      <= count+1;		 
       end
	   else begin
		 remainder_e <= dividend_e[DATAWIDTH*2-1:DATAWIDTH];
       end
     end
  DONE:begin
		count       <= 0;
  end	 
  endcase
 end
end
  
assign quotient  = quotient_e;
assign remainder = remainder_e;

assign ready=(current_state==IDLE)? 1'b1:1'b0;
assign vld_out=(current_state==DONE)? 1'b1:1'b0;
	       
endmodule

testbench:

`timescale 1ns/1ps

module div_fsm_tb();

parameter DATAWIDTH = 16;

reg  clk;
reg  rstn;       
reg  en;    
wire ready;     
reg  [DATAWIDTH-1:0]    dividend; 
reg  [DATAWIDTH-1:0]    divisor;
wire [DATAWIDTH-1:0]    quotient;
wire [DATAWIDTH-1:0]    remainder;
wire                    vld_out;

wire [DATAWIDTH-1:0]    quotient_ref; // true result
wire [DATAWIDTH-1:0]    remainder_ref; 
assign quotient_ref = dividend/divisor;
assign remainder_ref = dividend%divisor;

always #1 clk = ~clk;

integer i;
initial begin
  clk = 1;
  rstn = 1;
  en = 0;
  #2 rstn = 0; #2 rstn = 1;
  repeat(2) @(posedge clk);

  for(i=0;i<10;i=i+1) begin
    en <= 1;
    dividend <= $urandom()%1000;
    divisor  <= $urandom()%100;
    wait (ready == 1);
    wait (vld_out == 1);
  end


end


initial begin
    $fsdbDumpvars();
    $fsdbDumpMDA();
    $dumpvars();
    #1000 $finish;
 end

div_fsm #(
    .DATAWIDTH                      ( DATAWIDTH  ))
U_DIV_FSM_0(
    .clk                            ( clk        ),
    .rstn                           ( rstn       ),
    .en                             ( en         ),
    .ready                          ( ready      ),
    .dividend                       ( dividend   ),
    .divisor                        ( divisor    ),
    .quotient                       ( quotient   ),
    .remainder                      ( remainder  ),
    .vld_out                        ( vld_out    )
);


endmodule



仿真波形

对于16位的数据,计算周期为36。

posted @ 2020-05-10 20:50  love小酒窝  阅读(3290)  评论(0编辑  收藏  举报