2016-10-28 7 views
0

Я использую оператор '/' для выполнения divison в verilog. Я могу получить результаты моделирования правильно, но дело в том, что мой код не смог получить синтез из-за оператора «/». Он отображал ошибку «второй операнд/должен быть мощностью 2». Как мне выполнить деление в Verilog HDL?Алгоритм для Divison

+0

Существует несколько алгоритмов для делений, основанных на методе сдвига и добавления. Вы можете найти их в цифровых схемах или книгах по компьютерному дизайну. –

ответ

0

Оператор деления не синтезируется, как указано сообщением об ошибке, он должен использоваться только для моделирования.

Что вам нужно сделать, это зависит от условий деления. Вы можете использовать алгоритм повторного вычитания, который является самым простым решением.

Недостатком является то, что вы получаете результат своего деления в N тактовых циклах, где N в целочисленной части деления, но вы можете установить бит флага для завершения деления.

Вот описание алгоритма из Википедии:

while N ≥ D do 
    N := N − D 
end 
return N 

Edit: Для полноты картины к любому достигающего этот вопрос. Вот синтезируемая реализация алгоритма. (Это не лучшая реализация, ни она была полностью проверена)

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_part: 3 и напоминание 2

+0

Я уже реализовал то же самое в verilog. Появилась ошибка: «Set_interation_limit XX» –

 Смежные вопросы

  • Нет связанных вопросов^_^