8 位 ALU 第 46 行:无法简化运算符 DIV
8bit ALU line 46: Can not simplify operator DIV
大家好,我只是想问一下如何调试第 46 行中的“无法简化运算符 DIV”。在 Verilog 模块 (Xilinx) 中。预先感谢您的提示和帮助:))
这是我的 8 位 ALU 的代码
module alu_8fctn (a, b, opcode, rslt, rslt_mul);
input [3:0] a, b;
input [2:0] opcode;
output [3:0] rslt;
output [7:0] rslt_mul;
wire [3:0] a, b; //inputs are wire
wire [2:0] opcode;
reg [3:0] rslt; //outputs are reg
reg [7:0] rslt_mul;
//define operation codes
parameter add_op = 3'b000,
sub_op = 3'b001,
mul_op = 3'b010,
div_op = 3'b011,
and_op = 3'b100,
or_op = 3'b101,
xor_op = 3'b110,
xnor_op = 3'b111;
//perform the operations
always @(a or b or opcode)
begin
case (opcode)
add_op : rslt = a + b;
sub_op : rslt = a - b;
mul_op : rslt_mul = a * b;
div_op : rslt = a / b;
and_op : rslt = a & b;
or_op : rslt = a | b;
xor_op : rslt = a ^ b;
xnor_op: rslt = a ^~ b;
default: rslt = 8'b0000_0000;
endcase
end
endmodule
您的 Xilinx 在 a / b
方面似乎有问题。合成器可能很难用可变除数进行优化;特别是如果它们可以为零。
Xilinx 应该有一些用于划分的预定义模块(如果没有,您可以随时制作自己的模块)
wire [3:0] rslt_div;
<XilinxPrividedDividerModuleName> div ( rslt_div, a, b);
always @*
...
div_op : rslt = a / b;
...
其他问题:
rslt
和 rslt_mul
是推断锁存器,因为它们并非在所有条件下都被赋值。在 mul_op
中,rslt_mul
仅在 mul_op
中赋值,这是唯一未赋值的条件 rslt
。
简单的解决方案是在 case 语句之前给 rslt
和 rslt_mul
一个 initial/default 值。
always @*
begin
rslt = 4'h0;
rslt_mul = 8'h00;
case (opcode)
// ... you other code
endcase
end
另请注意,always @(a or b or opcode)
是 Verilog-1995 编写敏感度列表的方式。自 Verilog-2001 以来,首选方式是 always @*
(或同义词 always @(*)
)。 SystemVerilog 在 always_comb
中更进了一步,如果推断出锁存器,一个好的工具应该标记错误。
您可能还想考虑 ANSI 样式模块 headers(自 Verilog-2001 起也可用),它比 Verilog-1995 模块 header 样式更简洁且更不容易出现错别字。
module alu_8fctn (
input [3:0] a, b,
input [2:0] opcode,
output reg [3:0] rslt,
output reg [7:0] rslt_mul );
//define operation codes
parameter add_op = 3'b000,
...
大家好,我只是想问一下如何调试第 46 行中的“无法简化运算符 DIV”。在 Verilog 模块 (Xilinx) 中。预先感谢您的提示和帮助:))
这是我的 8 位 ALU 的代码
module alu_8fctn (a, b, opcode, rslt, rslt_mul);
input [3:0] a, b;
input [2:0] opcode;
output [3:0] rslt;
output [7:0] rslt_mul;
wire [3:0] a, b; //inputs are wire
wire [2:0] opcode;
reg [3:0] rslt; //outputs are reg
reg [7:0] rslt_mul;
//define operation codes
parameter add_op = 3'b000,
sub_op = 3'b001,
mul_op = 3'b010,
div_op = 3'b011,
and_op = 3'b100,
or_op = 3'b101,
xor_op = 3'b110,
xnor_op = 3'b111;
//perform the operations
always @(a or b or opcode)
begin
case (opcode)
add_op : rslt = a + b;
sub_op : rslt = a - b;
mul_op : rslt_mul = a * b;
div_op : rslt = a / b;
and_op : rslt = a & b;
or_op : rslt = a | b;
xor_op : rslt = a ^ b;
xnor_op: rslt = a ^~ b;
default: rslt = 8'b0000_0000;
endcase
end
endmodule
您的 Xilinx 在 a / b
方面似乎有问题。合成器可能很难用可变除数进行优化;特别是如果它们可以为零。
Xilinx 应该有一些用于划分的预定义模块(如果没有,您可以随时制作自己的模块)
wire [3:0] rslt_div;
<XilinxPrividedDividerModuleName> div ( rslt_div, a, b);
always @*
...
div_op : rslt = a / b;
...
其他问题:
rslt
和 rslt_mul
是推断锁存器,因为它们并非在所有条件下都被赋值。在 mul_op
中,rslt_mul
仅在 mul_op
中赋值,这是唯一未赋值的条件 rslt
。
简单的解决方案是在 case 语句之前给 rslt
和 rslt_mul
一个 initial/default 值。
always @*
begin
rslt = 4'h0;
rslt_mul = 8'h00;
case (opcode)
// ... you other code
endcase
end
另请注意,always @(a or b or opcode)
是 Verilog-1995 编写敏感度列表的方式。自 Verilog-2001 以来,首选方式是 always @*
(或同义词 always @(*)
)。 SystemVerilog 在 always_comb
中更进了一步,如果推断出锁存器,一个好的工具应该标记错误。
您可能还想考虑 ANSI 样式模块 headers(自 Verilog-2001 起也可用),它比 Verilog-1995 模块 header 样式更简洁且更不容易出现错别字。
module alu_8fctn (
input [3:0] a, b,
input [2:0] opcode,
output reg [3:0] rslt,
output reg [7:0] rslt_mul );
//define operation codes
parameter add_op = 3'b000,
...