除法器思路都是一样的,都是根据下述这个图实现
如果全用组合逻辑实现,那么时序肯定很差,另外一方面如果用时序逻辑实现就要考虑到实际使用时候出发的除数和被除数是流水进来的,所以结果上肯定是要一个周期输出一个数据。
所以我的思路就很简单,就是加寄存器,一拍走一个,如果是N位的我这里用到了N+1个寄存器,当然还可缩减一个。
我分别对除数被除数还有有效信号做了寄存器,然后一拍一拍往下传,用时序逻辑实现除法器移位后的判断,用组合逻辑实现移位操作。
代码如下
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/05/12 20:07:37
// Design Name:
// Module Name: divider_code
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
//除法器以8bit为例 流水线实现,防止新数据来之后改变之前的结果
module divider_code(
input clk ,
input rstn,
input [7:0] divisor ,
input [7:0] dividend,
input div_valid ,
output [7:0] div_dout ,
output [7:0] remainder
);
reg [15:0] divisor_r [8:0];
reg [15:0] dividend_r [8:0];
reg valid [8:0];
wire [15:0] divisor_shift[8:0];
integer i;
genvar n;
for(n=0;n<9;n=n+1)
begin:shift_assign
assign divisor_shift[n] = valid[n]? divisor_r[n] << 1 : 8'b0;
end
always@(posedge clk or negedge rstn) begin
if(~rstn)begin
for(i=0;i<9;i=i+1)begin
divisor_r[i] <= 8'b0;
dividend_r[i] <= 8'b0;
valid[i] <= 1'b0;
end
end
else if(div_valid)begin
divisor_r[0] <= {8'b0,divisor};
dividend_r[0]<= {dividend,8'b0};
valid[0] <= div_valid;
end
else
valid[0] <= 1'b0;
end
genvar j;
generate
for(j=1;j<9;j=j+1)
begin:generate_divde
always@(posedge clk)
if(valid[j-1])begin
if(divisor_shift[j-1] >= dividend_r[j-1])begin
divisor_r[j] <= divisor_shift[j-1] - dividend_r[j-1] +1'b1;
valid[j] <= valid[j-1];
dividend_r[j] <= dividend_r[j-1];
end
else begin
divisor_r[j] <= divisor_shift[j-1] ;
valid[j] <= valid[j-1];
dividend_r[j] <= dividend_r[j-1];
end
end
else
valid[j] <= valid[j-1];
end
endgenerate
assign div_dout = divisor_r[8][7:0];
assign remainder = divisor_r[8][15:8];
endmodule
可以看到连续发送的除法数据在8个cycle后连续输出