2016-10-28 43 views
0

我一直使用'/'运算符在verilog中执行divison。我能够得到正确的模拟结果,但问题是我的代码由于'/'运算符而无法合成。它显示错误“第二操作数/应该是2的幂”。我应该如何在Verilog HDL中执行divison?分区算法

+0

有几个算法的分割,基于shift和add方法。你可以在数字电路或计算机设计书中找到它们。 –

回答

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 

这是仿真的使用GTK-结果波: Division Simulation

在正在执行的17/5分割图像时,开始操作 的start导线需要在1至少1时钟ç ycle,当除法完成时,标志done被设置为1,那时结果在输出寄存器中。对于这个例子integer_part3和提醒是2

+0

我已经在verilog中实现了相同的功能。它显示一个错误:“Set_interation_limit XX” –