无法实现简单的 ALU

发布于 2024-10-22 01:42:49 字数 1985 浏览 8 评论 0原文

我有一个用 Verilog 描述的基本 8 位 ALU。我正在尝试实现该设计,但收到错误消息:

ERROR:NgdBuild:809 - output pad net 'quotient<1>'有非法负载: 模块 Mmux_opcode[2]_GND_1_o_wide_mux_8_OUT81 上的引脚 I3,类型为 LUT6

该设计执行以下运算:加法、减法、乘法、除法、AND、OR、XOR 和 XNOR。有趣的是,除非被除数除以 2(基本上是右移),否则 Xilinx XST 无法合成除法器。因此,为了解决这个问题,我使用了 Xilinx Core Generator 生成的 CORE IP 组件。它采用单个时钟(没有时钟使能或同步清除,并在大约 20 个时钟周期后输出正确的商和余数。核心本身可以在核心生成器程序中的数学函数下找到。无论如何,这是我的代码:

`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(像往常一样充满错误)或项目设置是否有问题

?代码,以反映答案提供的建议。

I have a basic 8-bit ALU described in Verilog. I am trying to implement the design, but I am getting error messages:

ERROR:NgdBuild:809 - output pad net 'quotient<1>' has an illegal load:
pin I3 on block Mmux_opcode[2]_GND_1_o_wide_mux_8_OUT81 with type LUT6

The design does the following operation, addition, subtraction, multiplication, division, AND, OR, XOR, and XNOR. The interesting thing about it is the fact that Xilinx XST cannot synthesis a divider unless the dividend is being divided by a factor of 2 (basically shifting right). So to take care of this I used a CORE IP component generated by Xilinx Core Generator. It takes in a single clock (no clock enable or synchronous clear, and outputs the correct quotient and remainder after about 20 or so clock cycles. The core itself can be found under math functions in the Core Generator program. Anyway, here's my code:

`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

Obviously my code terrible and my comments are probably erroneous, but I am just a beginner with Verilog. However, I do plan on improving this code greatly and adding more operations for me to practice. The module itself does successfully synthesis and simulate correctly, but I am unable to implement it on any FPGA. Anyone know if there is a problem with the code, or Xilinx ISE (which is full of bugs as usual), or maybe the project settings?

EDIT: I've made a few changes to the code, to reflect the advice provided by the answers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

尐籹人 2024-10-29 01:42:49

您的 coregen 项目中是否选择了“使用 IO 焊盘创建网表包装器”选项?从错误来看,Divider8 内核有一个 OBUF 或类似的输出缓冲区来驱动商输出。 OBUF 只能驱动离开 FPGA 的信号。

另请注意,尽管这与 ngdbuild 错误无关:通常在顺序块中使用非阻塞分配(“始终@(thoughtge clk)”),例如“OUT <= A + B”。对此的简短解释是,它推迟更新 OUT 信号,直到处理完当前时间的所有其他事件,这避免了模拟器中的竞争条件。

Do you have the "Create netlist wrapper with IO pads" option selected in your coregen project? From the error it sounds like the Divider8 core has an OBUF or similar output buffer driving the quotient output. OBUF can only drive a signal that is leaving the FPGA.

Another note, although this is not related to the ngdbuild error: normally non-blocking assignments are used in sequential blocks ("always @(posedge clk)"), e.g. "OUT <= A + B". The short explanation of this is that it defers updating the OUT signal until all other events for the current time have been processed, which avoids race conditions in the simulator.

寂寞花火° 2024-10-29 01:42:49

这不是答案,但我认为这些技巧可能会改进您的代码。

由于我没有您的 Divider8 模块,因此无法编译您的代码,除非我注释掉 divider 实例。错误消息似乎与该实例有关。

对于许多综合工具来说,initial 块是不可综合的。由于我不使用xilinx,所以无法评论它的支持。也许您可以删除 initial 块。

最好使用非阻塞赋值 (<=) 来综合顺序逻辑。例如:

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

您可以将常量重新编码为:

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

This is not an answer, but I think these tips might improve your code.

Since I do not have your Divider8 module, I can't compile your code, unless I comment out the divider instance. It seems like the error message is related to that instance.

For many synthesis tools initial blocks are not synthesizable. Since I do not use xilinx, I can not comment on its support. Perhaps you could just delete the initial block.

It is better to use non-blocking assignments (<=) for synthesizing sequential logic. For example:

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

You could re-code your constant as:

    default: OUT = {16{1'b0}};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文