input valid_i, input ready_i, output busy, // the divider is busy in computing output valid_o, output ready_o, input clk, input rst_n ); localparam WIDTH = $clog2(K); reg [K-1:0] Rp; // rp is initialized to high k bits of dicidend reg [K-1:0] Rq; // rq is initialized to low k bits of dicidend reg [WIDTH:0] Rc; // shift counter, initialized to K reg valid; // combinational logic
always @(posedge clk ornegedge rst_n) begin if(!rst_n)begin Rc <= {(WIDTH+1){1'b0}}; end elseif (~busy & valid_i)begin Rc <= K; end elsebegin Rc <= Rc - 1'b1; end end
always @(posedge clk ornegedge rst_n) begin if(!rst_n)begin Rp <= {K{1'b0}}; end elseif (~busy & valid_i)begin Rp <= dividend[2*K-1:K]; end elsebegin Rp <= Rp_next; end end
always @(posedge clk ornegedge rst_n) begin if(!rst_n)begin Rq <= {K{1'b0}}; end elseif (~busy & valid_i)begin Rq <= dividend[K-1:0]; end elsebegin Rq <= Rq_next; end end
always @(posedge clk ornegedge rst_n) begin if(!rst_n)begin valid <= 1'b0; end elseif ( valid_i & (Rc == {{WIDTH{1'b0}}, 1'b1}))begin valid <= 1'b1; end end
//===================================================================== // // Designer : wenkai_sjtu@163.com // // Description: // an signed left shift divider, using nonerestoring algrithm // no overflow and zero divisor check // Revision History: // ====================================================================
input valid_i, input ready_i, output busy, // the divider is busy in computing output valid_o, output ready_o, input clk, input rst_n );
// use state machine localparam IDEL = 2'b00, SHIFT=2'b01, CORRECT = 2'b10, OUTPUT = 2'b11;
localparam WIDTH = $clog2(K) + 1; // expand 1 bit to avoid overflow
reg [K-1:0] Rp; // rp is initialized to high k bits of dicidend reg [K-1:0] Rq; // rq is initialized to low k bits of dicidend reg [WIDTH-1:0] Rc; // shift counter, initialized to K reg [1:0] state; // the state of divider reg [1:0] state_next;
wire sign_dividend = dividend[2*K-2]; // sign bit of dividend wire sign_divisor = divisor[K-1]; // sign bit of divisor wire sign_remainder = Rp[K-1];// sign bit of remainder
wire [K-1:0] divisor_neg = ~divisor; // 1's complement of divisor wire shift_sub = ~(sign_remainder ^ sign_divisor); // sign of remainder equal to sign of divisor, sub ,otherwise add wire need_correct; wire correct_sub; reg sub; // substract flag of adder
// when shift finish, the result needs correct if sign of remainder is different to sign of dividend assign need_correct = (Rc == {WIDTH{1'b0}}) & (sign_remainder ^ sign_dividend);
assign correct_sub = need_correct & ( (sign_remainder & sign_divisor) // remainder < 0, divisor < 0 but dividend > 0 | (~sign_remainder & ~sign_divisor)); // remainder > 0, divisor > 0 but dividend < 0 // in this 2 case we need to substract another divisor to correct the result otherwise we need to add
always @(*) begin // default value Rp_next = dividend[2*K-2:K-1]; Rq_next = {dividend[K-2:0],1'b0}; Rc_next = K-2; sub = shift_sub; addend1 = Rp_shift; addend2 = shift_sub ? divisor_neg : divisor; case (state) IDEL : begin if(valid_i)begin state_next = SHIFT; end elsebegin state_next = IDEL; Rp_next = Rp; Rq_next = Rq; Rc_next = Rc; end end SHIFT:begin Rp_next = adder_result; Rq_next = Rq_shift; sub = shift_sub; addend1 = Rp_shift; addend2 = shift_sub ? divisor_neg : divisor; if(Rc != {WIDTH{1'b0}})begin state_next = SHIFT; Rc_next = Rc-1'b1; end elsebegin state_next = CORRECT; Rc_next = Rc; // keep rc=0 end end CORRECT:begin state_next = OUTPUT; Rp_next = need_correct ? adder_result : Rp; Rq_next = need_correct ? (correct_sub ? Rq_con + 1'b1 : Rq_con - 1'b1) : Rq_con; Rc_next = Rc; addend1 = Rp; addend2 = correct_sub ? divisor_neg : divisor; sub = correct_sub; end OUTPUT:begin if(ready_i & ~valid_i)begin// wait next data state_next = IDEL; end elseif (ready_i & valid_i)begin// begin next computation state_next = SHIFT; end elsebegin// wait result to be stored state_next = OUTPUT; Rp_next = Rp; Rq_next = Rq; Rc_next = Rc; end end endcase end
always @(posedge clk ornegedge rst_n) begin if(!rst_n)begin state <= IDEL; Rp <= {K{1'b0}}; Rq <= {K{1'b0}}; Rc <= {WIDTH{1'b0}}; end elsebegin state <= state_next; Rp <= Rp_next; Rq <= Rq_next; Rc <= Rc_next; end end