我一直在使用' /'运算符在verilog中执行divison。我能够正确地获得模拟结果,但问题是由于' /'我的代码无法合成。运营商。它显示错误" /的第二个操作数应该是2"的幂。我应该如何在Verilog HDL中执行divison?
答案 0 :(得分:0)
除法错误消息指出,除法运算符不可合成,它应该只用于模拟。
您需要做什么取决于分工的条件。 您可以使用重复减法算法,这是最简单的解决方案。
缺点是你在N个时钟周期得到你的除法结果,其中N在除法的整数部分,但是你可以在除法完成时设置一个标志位。
以下是该算法的描述,来自维基百科:
while N ≥ D do
N := N − D
end
return N
编辑:为了完整性,任何人都可以达到这个问题。这是算法的可合成实现。 (这不是最好的实现,也没有经过全面测试)
module mod_div(
input clk,
input rst,
input start,
input [7:0] num,
input [7:0] den,
output [7:0] res,
output [7:0] rem,
output reg done
);
/* Registers to store the input arguments */
reg [7:0] num_r;
reg [7:0] den_r;
/* counts the number of times denominator fits in numerator */
reg [7:0] result_integer;
/* True if the algorithm is running */
reg working;
always @(posedge clk) begin
if(rst == 1'b1)begin
/* setting the working registers to 0 */
num_r <= 8'b0;
den_r <= 8'b0;
working <= 1'b0;
result_integer <= 'b0;
done <= 'b0;
end else if(start == 1'b1) begin
/* Captures the parameters and starts the operation */
num_r <= num;
den_r <= den;
working <= 1'b1;
done <= 1'b0;
end
/* The actual algorithm */
if (working == 1'b1 && start == 1'b0)begin
if(num_r >= den_r) begin
/* The division will give a proper fraction */
num_r <= num_r - den_r;
result_integer <= result_integer + 8'b1;
end else begin
working <= 'b0;
done <= 1'b1;
end
end
end
/* The reminder of the division */
assign rem = num_r;
/*The integer part is the number of times the divisor was substracted from the
* numerator*/
assign res = result_integer;
endmodule
这里也是这个模块的测试平台:
module division_tb();
reg clk;
reg rst;
reg [7:0] numerator;
reg [7:0] denominator;
reg start;
wire [7:0] integer_result;
wire [7:0] reminder_result;
wire done_flag;
mod_div DUT (
.clk(clk),
.rst(rst),
.start(start),
.num(numerator),
.den(denominator),
.res(integer_result),
.rem(reminder_result),
.done(done_flag)
);
always begin
#10 clk = ~clk;
end
initial begin
clk = 1'b0;
rst = 1'b1;
#15 rst = 1'b0;
numerator = 17;
denominator = 5;
#1 start = 1;
#20 start = 0;
#200 $finish;
end
/* FOR GTK WAVE */
initial
begin
$dumpfile("shift.vcd");
$dumpvars(0, division_tb);
end
endmodule
在图像中正在执行17/5的分割,以开始操作
start
导线需要在1
中至少1个时钟周期,当除法完成时,标志done
设置为1
,此时结果为输出寄存器。对于此示例integer_part
:3
,提醒为2