Невозможно реализовать простой ALU
Вопрос
У меня есть базовый 8-битный ALU, описанный в Verilog.Я пытаюсь реализовать дизайн, но получаю сообщения об ошибках:
ОШИБКА: NgdBuild: 809 - коэффициент чистой выходной площадки<1>' имеет незаконную нагрузку:вывод I3 в блоке Mmux_opcode[2]_GND_1_o_wide_mux_8_OUT81 с типом LUT6
Дизайн выполняет следующие операции: сложение, вычитание, умножение, деление И, ИЛИ, XOR и XNOR.Интересной вещью в этом является тот факт, что Xilinx XST не может синтезировать делитель, если только дивиденд не делится в 2 раза (в основном смещаясь вправо).Поэтому, чтобы позаботиться об этом, я использовал ОСНОВНОЙ IP-компонент, сгенерированный Xilinx Core Generator.Он принимает один такт (без включения часов или синхронной очистки) и выводит правильное частное и остаток примерно через 20 тактов.Само ядро можно найти в разделе математические функции в программе Core Generator.В любом случае, вот мой код:
`timescale 1ns / 1ps
module ALU8(A,B,opcode,clk,OUT);
// I/O
// We have two 16-bit inputs
input [7:0] A,B;
// The opcode determines our next operation
input [2:0] opcode;
// The processor clock
input clk;
// A 32-bit output
output [15:0] OUT;
// The inputs are wires
wire [7:0] A,B;
wire [2:0] opcode;
// The output is a register
reg [15:0] OUT;
// The quotient and remainder for tyhe divider
wire [7:0] quotient,remainder;
// Declare an internal dividing unit
Divider8 divider(.rfd(), .clk(clk), .dividend(A), .quotient(quotient), .divisor(B), .fractional(remainder));
// Define operation codes, there's only 9 so far
parameter ADD = 3'b000;
parameter SUB = 3'b001;
parameter MUL = 3'b010;
parameter DIV = 3'b011;
parameter AND = 3'b100;
parameter OR = 3'b101;
parameter XOR = 3'b110;
parameter XNOR = 3'b111;
// On the rising-edge of the clock
always @(posedge clk)
begin
// The output is determined by the operation
// Think of it as a MUX
// A MUX8 will be added in later
case(opcode)
ADD: OUT <= A + B;
SUB: OUT <= A - B;
MUL: OUT <= A * B;
DIV: OUT <= {quotient,remainder};
AND: OUT <= A & B;
OR: OUT <= A | B;
XOR: OUT <= A ^ B;
XNOR: OUT <= A ~^ B;
default: OUT <= 16'b0000000000000000;
endcase
end
endmodule
Очевидно, что мой код ужасен, а мои комментарии, вероятно, ошибочны, но я всего лишь новичок в Verilog.Тем не менее, я планирую значительно улучшить этот код и добавить больше операций для практики.Сам модуль успешно выполняет синтез и корректное моделирование, но я не могу реализовать его ни на одной ПЛИС.Кто-нибудь знает, есть ли проблема с кодом, или с Xilinx ISE (который, как обычно, полон ошибок), или, может быть, с настройками проекта?
Редактировать:Я внес несколько изменений в код, чтобы отразить рекомендации, содержащиеся в ответах.
Решение
Выбрана ли у вас в вашем проекте coregen опция "Создать оболочку netlist с помощью IO pads"?Судя по ошибке, похоже, что ядро Divider8 имеет OBUF или аналогичный выходной буфер, управляющий коэффициентным выводом.OBUF может передавать только сигнал, выходящий из ПЛИС.
Еще одно замечание, хотя это не связано с ошибкой ngdbuild:обычно неблокирующие назначения используются в последовательных блоках ("always @(posedge clk)"), например"ВОН <= A + B".Краткое объяснение этого заключается в том, что обновление сигнала OUT откладывается до тех пор, пока не будут обработаны все остальные события за текущее время, что позволяет избежать условий гонки в симуляторе.
Другие советы
Это не ответ, но я думаю, что эти советы могут улучшить ваш код.
Поскольку у меня нет вашего Divider8
модуль, я не могу скомпилировать ваш код, пока не закомментирую divider
пример.Похоже, что сообщение об ошибке связано с этим экземпляром.
Для многих инструментов синтеза initial
блоки не поддаются синтезированию.Поскольку я не использую xilinx, я не могу комментировать его поддержку.Возможно, вы могли бы просто удалить initial
блок.
Лучше использовать неблокирующие назначения (<=
) для синтеза последовательной логики.Например:
case(opcode)
ADD: OUT <= A + B;
SUB: OUT <= A - B;
Вы могли бы перекодировать свою константу следующим образом:
default: OUT = {16{1'b0}};