Невозможно реализовать простой АЛУ - PullRequest
1 голос
/ 16 марта 2011

У меня есть базовый 8-битный ALU, описанный в Verilog.Я пытаюсь реализовать дизайн, но получаю сообщения об ошибках:

ОШИБКА: NgdBuild: 809 - неверная загрузка выходной панели net 'quotient <1>': вывод I3 в блоке Mmux_opcode [2] _GND_1_o_wide_mux_8_OUT81с типом LUT6

Конструкция выполняет следующие операции: сложение, вычитание, умножение, деление, И, ИЛИ, XOR и XNOR.Интересно то, что Xilinx XST не может синтезировать делитель, если дивиденд не делится на коэффициент 2 (в основном смещение вправо).Поэтому, чтобы позаботиться об этом, я использовал IP-компонент CORE, сгенерированный 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. Однако я планирую значительно улучшить этот код и добавить больше операций для практики. Модульсам по себе успешно синтезирует и симулирует правильно, но я не могу реализовать его на любой FPGA. Кто-нибудь знает, есть ли проблема с кодом, или Xilinx ISE (который, как обычно, полон ошибок), или, может быть, настройки проекта?

РЕДАКТИРОВАТЬ: я внес несколько изменений в код, чтобы отразить рекомендации, предоставленные ответы.

Ответы [ 2 ]

1 голос
/ 17 марта 2011

Есть ли в вашем проекте coregen опция «Создать оболочку списка соединений с IO-площадками»?Судя по ошибке, ядро ​​Divider8 имеет OBUF или аналогичный выходной буфер, управляющий частным выходом.OBUF может управлять только сигналом, который покидает FPGA.

Еще одно замечание, хотя это не связано с ошибкой ngdbuild: обычно неблокирующие назначения используются в последовательных блоках («always @ (posedge clk)»), например, "OUT <= A + B".Краткое объяснение этого состоит в том, что он откладывает обновление сигнала OUT до тех пор, пока не будут обработаны все другие события для текущего времени, что позволяет избежать условий гонки в симуляторе. </p>

1 голос
/ 16 марта 2011

Это не ответ, но я думаю, что эти советы могут улучшить ваш код.

Поскольку у меня нет вашего Divider8 модуля, я не могу скомпилировать ваш код, если я не закомментирую экземпляр divider. Похоже, что сообщение об ошибке связано с этим экземпляром.

Для многих инструментов синтеза initial блоки не синтезируются. Поскольку я не пользуюсь xilinx, я не могу комментировать его поддержку. Возможно, вы могли бы просто удалить блок initial.

Лучше использовать неблокирующие назначения (<=) для синтеза последовательной логики. Например:

case(opcode)
    ADD: OUT <= A + B;
    SUB: OUT <= A - B;

Вы можете перекодировать вашу константу как:

    default: OUT = {16{1'b0}};
...