## 2014年6月7日 星期六

### Division (除法器)

Division (除法器)

http://blog.csdn.net/chevroletss/article/details/6308399

Reference：

“Digital design and principles and practices”, John F. Wakerly
“Advanced Digital Design with Verilog HDL”, Michael D.Ciletti

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: SEU.IC
// Engineer: Ray
// Description:
//   1, this verilog code is designed for unsigned integer division;
//   2, subtract_and_shift  -->  division;
//   3, word1_in/word2_in = quotient + remainder;
//   4, word1_in is the dividend and word2_in is the divisor;
//   5, if word2_in == 'd0, then set the error_out;
//   6, ready_out is utilized to indicate the completion of division
//   7, the width of word2_in is not larger than the width of word1_in;
//   8, the subtraction is realized by 2s complement addition
//////////////////////////////////////////////////////////////////////////////////
module division_4(
quotient_out,
remainder_out,
error_out,
word1_in,
word2_in,
start_in,
clock,
reset);
parameter l_divn = 8;
parameter l_divr = 8;
parameter s_idle = 0,
s_1    = 1,
s_2    = 2,
s_3    = 3,
s_err  = 4;
parameter  l_state = 3;
output [l_divn-1 : 0] quotient_out;
output [l_divn-1 : 0] remainder_out;
input  [l_divn-1 : 0] word1_in;
input  [l_divr-1 : 0] word2_in;
input                 start_in, clock, reset;
reg    [l_state-1 : 0] state, next_state;
reg    [l_divn-1  : 0] dividend;
reg    [l_divr-1  : 0] divisor;
reg    [l_divn-1  : 0] quotient_out;
wire                   GTE   = (dividend >= divisor);
wire                   ready_out = ((state == s_idle)&&!reset)||(state == s_3);
wire                   error_out = (state == s_err);
assign remainder_out = dividend;
always @(posedge clock, posedge reset)
if(reset)
state <= s_idle;
else
state <= next_state;
always@(state, word1_in, word2_in, start_in, GTE)
begin
subtract   = 0;
case (state)
s_idle:     case(start_in)
0:   next_state = s_idle;
1:   if(word2_in == 0) next_state = s_err;
else if(word1_in)
begin
next_state = s_1;
end
else
next_state = s_3;
endcase
s_1:        if(GTE)
begin
next_state = s_2;
subtract   = 1;
end
else
next_state = s_3;
s_2:        if(GTE)
begin
next_state = s_2;
subtract   = 1;
end
else
next_state = s_3;
s_3:        case(start_in)
0: next_state = s_3;
1: if(word2_in == 0) next_state = s_err;
else if(word1_in == 0) next_state = s_3;
else
begin
next_state = s_1;
end
endcase
s_err:      next_state = s_idle;
default:    next_state = s_idle;
endcase
end
always @(posedge clock, posedge reset)
begin
if(reset)
begin
divisor  <= 'd0;
dividend <= 'd0;
quotient_out <= 'd0;
end
begin
divisor  <= word2_in;
dividend <= word1_in;
quotient_out <= 'd0;
end
else if(subtract)
begin
dividend <= dividend[l_divn-1 : 0] + 1'b1 + {{(l_divn - l_divr){1'b1}}, ~divisor[l_divr-1 :0]};// 2s complement addition
quotient_out <= quotient_out + 1;
end
end

endmodule

test_bench

module tb_div_4;
// Inputs
reg [7:0] word1_in;
reg [7:0] word2_in;
reg start_in;
reg clock;
reg reset;
// Outputs
wire [7:0] quotient_out;
wire [7:0] remainder_out;
wire error_out;
// Instantiate the Unit Under Test (UUT)
division_4 uut (
.quotient_out(quotient_out),
.remainder_out(remainder_out),
.error_out(error_out),
.word1_in(word1_in),
.word2_in(word2_in),
.start_in(start_in),
.clock(clock),
.reset(reset)
);
always #10 clock = ~clock;
initial begin
// Initialize Inputs
word1_in = 0;
word2_in = 0;
start_in = 0;
clock = 0;
reset = 1;
// Wait 100 ns for global reset to finish
#100;
reset = 0;
word1_in = 'd20;
word2_in = 'd10;
#50;
start_in = 1;
#50;
start_in = 0;
word1_in = 'd241;
word2_in = 'd78;
#100;
start_in = 1;
#50;
start_in = 0;
word1_in = 'd201;
word2_in = 'd55;
#200;
start_in = 1;
#50;
start_in = 0;
word1_in = 'd100;
word2_in = 'd0;
#200;
start_in = 1;
#50;
start_in = 0;

end

endmodule

Simualtion Wave：