Я использую оператор '/' для выполнения divison в verilog. Я могу получить результаты моделирования правильно, но дело в том, что мой код не смог получить синтез из-за оператора «/». Он отображал ошибку «второй операнд/должен быть мощностью 2». Как мне выполнить деление в Verilog HDL?Алгоритм для Divison
ответ
Оператор деления не синтезируется, как указано сообщением об ошибке, он должен использоваться только для моделирования.
Что вам нужно сделать, это зависит от условий деления. Вы можете использовать алгоритм повторного вычитания, который является самым простым решением.
Недостатком является то, что вы получаете результат своего деления в 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- волна:
в изображении разделение 17/5, выполняемой в настоящее время, чтобы начать операцию start
проволоки должна быть в 1
, по крайней мере, 1 с тактовой ycle, когда деление завершено, флаг done
установлен в 1
, в этот момент результат находится в выходных регистрах. В данном примере integer_part
: 3
и напоминание 2
Я уже реализовал то же самое в verilog. Появилась ошибка: «Set_interation_limit XX» –
Существует несколько алгоритмов для делений, основанных на методе сдвига и добавления. Вы можете найти их в цифровых схемах или книгах по компьютерному дизайну. –