设计思路:
通过verilog实现除法有两大类,分别是:
基于减法操作。
基于乘法操作的算法。
8bit/8bit的除法实现
附录:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2019/07/29 16:11:22
// Design Name:
// Module Name: test_div
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
// testbench //
module test_div();
reg I_clk;
reg I_rst_p;
reg I_data_valid; //输入有效信号
reg [7:0] I_data_a; //被除数
reg [7:0] I_data_b; //除数
wire O_data_valid;
wire [7:0] O_data_shang;
wire [7:0] O_data_yushu;
c u_c(
.I_clk(I_clk),
.I_rst_p(I_rst_p),
.I_data_valid(I_data_valid),
.I_data_a(I_data_a),
.I_data_b(I_data_b),
.O_data_valid(O_data_valid),
.O_data_shang(O_data_shang),
.O_data_yushu(O_data_yushu)
);
always #3.125 I_clk <= ~I_clk;
initial begin
I_clk = 0;
I_rst_p = 1;
I_data_valid = 0;
I_data_a = 0;
I_data_b = 0;
#10;
I_rst_p = 0;
#30;
@(posedge I_clk )
begin
I_data_valid = 1;
I_data_a = {$random}%256;
I_data_b = {$random}%20;
end
repeat(18) @(posedge I_clk) I_data_valid = 0;
@(posedge I_clk )
begin
I_data_valid = 1;
I_data_a = {$random}%256;
I_data_b = {$random}%20;
end
repeat(18) @(posedge I_clk) I_data_valid = 0;
@(posedge I_clk )
begin
I_data_valid = 1;
I_data_a = {$random}%256;
I_data_b = {$random}%20;
end
repeat(10) @(posedge I_clk) I_data_valid = 0;
@(posedge I_clk )
begin
I_data_valid = 1;
I_data_a = {$random}%256;
I_data_b = {$random}%20;
end
repeat(18) @(posedge I_clk) I_data_valid = 0;;
end
endmodule
module c(
input I_clk,
input I_rst_p,
input I_data_valid,
input [7:0] I_data_a,
input [7:0] I_data_b,
output reg O_data_valid,
output reg [7:0] O_data_shang,
output reg [7:0] O_data_yushu
);
reg [7:0] tempa;
reg [7:0] tempb;
reg [15:0] temp_a;
reg [15:0] temp_b;
reg div_start;
reg div_start_d1;
wire div_start_neg;
reg [4:0] div_cnt;
always@(posedge I_clk or posedge I_rst_p)
begin
if(I_rst_p)
begin
tempa <= 8'h0;
tempb <= 8'h0;
end
else if(I_data_valid)
begin
tempa <= I_data_a;
tempb <= I_data_b;
end
else
begin
tempa <= tempa;
tempb <= tempb;
end
end
always@(posedge I_clk or posedge I_rst_p)
begin
if(I_rst_p)
div_start <= 1'b0;
else if(I_data_valid && div_start == 1'b0)
div_start <= 1'b1; //开始计算
else if(div_cnt == 5'd16 ) //每16个时钟后开始下一次计算
div_start <= 1'b0;
else
div_start <= div_start;
end
//========================================================div_cnt 计数器
always@(posedge I_clk or posedge I_rst_p)
if(I_rst_p)
div_cnt <= 5'd0;
else if(div_start)
div_cnt <= div_cnt + 1;
else
div_cnt <= 5'd0;
//=======================================================
always@(posedge I_clk or posedge I_rst_p)
begin
if(I_rst_p)
begin
temp_a <= 16'h0;
temp_b <= 16'h0;
end
else if(div_start )
if(div_cnt == 4'd0)
begin
temp_a <= {8'h0,tempa};
temp_b <= {tempb,8'h0};
end
else if(div_cnt[0] == 1'b1)
begin
temp_a <= {temp_a[14:0],1'b0}; //相当于乘2 或者左移一位
else
begin
temp_a <= (temp_a[15:8] >= temp_b[15:8])?(temp_a - temp_b + 1):temp_a;
//判断temp_a乘2之后取高8位与输入的除数比较大小 , 8次移动完temp_a[15:8]<temp_b[15:8])
//结果就是左边高temp_a[15:8]是余数,右边temp_a[7:0]是商
end
else
begin
temp_a <= 16'h0;
temp_b <= 16'h0;
end
end
always@(posedge I_clk)
begin
div_start_d1 <= div_start; //延一拍
end
assign div_start_neg = div_start_d1 & (~div_start); //产生一个脉冲
always@(posedge I_clk or posedge I_rst_p)
begin
if(I_rst_p)
begin
O_data_valid <= 1'b0;
O_data_shang <= 1'b0;
O_data_yushu <= 1'b0;
end
else if(div_start_neg)
begin
O_data_valid <= 1'b1;
O_data_shang <= temp_a[7:0];
O_data_yushu <= temp_a[15:8];
end
else
begin
O_data_valid <= 1'b0;
O_data_shang <= 1'b0;
O_data_yushu <= 1'b0;
end
end
endmodule
仿真结果: