1.目标:使用verilog实现一个32位的除法器,实现27/5 = 5……2
2.方法:
首先将被除数前面补上16个0,在除数后面补上16个0
A被除数27: 0000_0000_0000_0000 0000_0000_0001_1011
B除数5: 0000_0000_0000_0101 0000_0000_0000_0000
循环用A减去B,如果前者小于后者,就将A向左移动一位,否则就是下面的情况:
A被除数27: 0000_0000_0000_0110 1100_0000_0000_0000
B除数5: 0000_0000_0000_0101 0000_0000_0000_0000
这个时候进行计算A = A-B+1(A>=B时候)
得到
A: 0000_0000_0000_0001 1100_0000_0000_0001(最低位的1代表商的最高位为1)
可见,只要循环16次,那么得到的A低十六位就是 商,高十六位就是 余数。
3. division.v
`timescale 1ns / 1ps
//
// Company: Shanghaitech
// Engineer: Junluoyu
//
// Create Date: 2021/11/02 23:47:38
// Design Name:
// Module Name: division
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module division(
input [15:0] A,
input [7:0] B,
output [15:0] result,
output [15:0] odd
);
/*---------------------------------------------------------------------------------------------*/
reg [15:0] a_reg;
reg [7:0] b_reg;
reg [31:0] temp_a;
reg [31:0] temp_b;
integer i;
/*---------------------------------------------------------------------------------------------*/
always @(*) begin
a_reg = A;
b_reg = B;
end
always @(*) begin
temp_a = {16'h0,a_reg};
temp_b = {b_reg,16'h0};
for(i=0;i<16;i=i+1)
begin
temp_a = temp_a <<1 ;
if(temp_a >= temp_b)
begin
temp_a = temp_a - temp_b +1;
end
else
begin
temp_a = temp_a;
end
end
end
assign odd = temp_a[31:16];
assign result = temp_a[15:0];
endmodule
4.testbench
`timescale 1ns / 1ps
//
// Company: Shanghaitech
// Engineer: Junluoyu
//
// Create Date: 2021/11/03 00:06:34
// Design Name:
// Module Name: tb_2
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tb_2();
/*---------------------------------------------------------------------------------------------*/
reg [15:0] A;
reg [7:0] B;
wire [15:0] result;
wire [15:0] odd;
/*---------------------------------------------------------------------------------------------*/
division division_inst(
.A (A ),
.B (B ),
.result (result),
.odd (odd )
);
/*----------------------------------------------------------------------------------------------*/
// initial clk_in = 1'b0;
// always #5 clk_in = ~clk_in; // 10ns,50MHz
/*----------------------------------------------------------------------------------------------*/
initial begin
#100;
A = 16'd27;
B = 8'd5;
#1000;
$stop;
end
endmodule
5.仿真波形
可见计算正确
6.扩展:怎么计算乘法呢,是不是相同的过程呢?