使用 Verilog 在 32 位 ALU 中实现一位标志
Implementing one-bit flags in a 32Bit ALU using Verilog
我正在做作业,有点迷茫,不知道如何开始。我需要在 32 位 ALU 中实现以下标志:
• Z ("Zero"):如果运算结果为零,则设置为 1 ("True")
• N("Negative"):如果结果的第一位为1,则设置为1("True"),表示负数
• O ("Overflow"):设置为1 ("True")表示操作溢出总线宽度。
此外,一个比较函数,比较输入 a 和输入 b,然后设置三个标志之一:
• LT 如果输入 a 小于输入 b
• GT 如果输入 a 大于输入 b
• EQ 如果输入 a 等于输入 b
我需要修改此 ALU 以包含三个标志和比较输出,然后更改测试台以测试所有这些修改。
这就是我收到的关于这项作业的所有信息,实际上没有教科书或任何其他资源。这是一个在线 class,我无法从我的导师那里得到回复。所以我对如何开始有点困惑。在数字逻辑方面,我仍然是一个新手,所以请多多包涵。我只需要一些帮助来理解这些标志和比较是如何工作的。如果有人能向我更好地解释一下它们的工作原理和作用,以及我可能如何将它们实施到 ALU 和测试台中,我将非常感激。
我不指望任何人完成我的作业,我真的只是需要帮助来理解它。
ALU
module alu32 (a, b, out, sel);
input [31:0] a, b;
input [3:0] sel;
output [31:0] out,
reg [31:0] out;
//Code starts here
always @(a, b, sel)
begin
case (sel)
//Arithmetic Functions
0 : out <= a + b;
1 : out <= a - b;
2 : out <= b - a;
3 : out <= a * b;
4 : out <= a / b;
5 : out <= b % a;
//Bit-wise Logic Functions
6 : out <= ~a; //Not
7 : out <= a & b; //And
8 : out <= a | b; //Or
9 : out <= a ^ b; //XOR
10 : out <= a ^~ b; //XNOR
//Logic Functions
11 : out <= !a;
12 : out <= a && b;
13 : out <= a || b;
default: out <= a + b;
endcase
end
endmodule
ALU 测试平台
module alu32_tb();
reg [31:0] a, b;
reg [3:0] sel;
wire [31:0] out;
initial begin
$monitor("sel=%d a=%d b=%d out=%d", sel,a,b,out);
//Fundamental tests - all a+b
#0 sel=4'd0; a = 8'd0; b = 8'd0;
#1 sel=4'd0; a = 8'd0; b = 8'd25;
#1 sel=4'd0; a = 8'd37; b = 8'd0;
#1 sel=4'd0; a = 8'd45; b = 8'd75;
//Arithmetic
#1 sel=4'd1; a = 8'd120; b = 8'd25; //a-b
#1 sel=4'd2; a = 8'd30; b = 8'd120; //b-a
#1 sel=4'd3; a = 8'd75; b = 8'd3; //a*b
#1 sel=4'd4; a = 8'd75; b = 8'd3; //a/b
#1 sel=4'd5; a = 8'd74; b = 8'd3; //a%b
//Bit-wise Logic Functions
#1 sel=4'd6; a = 8'd31; //Not
#1 sel=4'd7; a = 8'd31; b = 8'd31; //And
#1 sel=4'd8; a = 8'd30; b = 8'd1; //Or
#1 sel=4'd9; a = 8'd30; b = 8'd1; //XOR
#1 sel=4'd10; a = 8'd30; b = 8'd1; //XNOR
//Logic Functions
#1 sel=4'd11; a = 8'd25; //Not
#1 sel=4'd12; a = 8'd30; b = 8'd0; //And
#1 sel=4'd13; a = 8'd0; b = 8'd30; //Or
#1 $finish;
end
alu32 myalu (.a(a), .b(b), .out(out), .sel(sel));
endmodule
您可以将这些标记输出添加到设计。像下面这样。只需 连接 它们在测试平台中。
// In design:
output zero;
output overflow;
output negative;
// In testbench:
wire zero,overflow,negative;
alu32 myalu (.a(a), .b(b), .out(out), .sel(sel), .zero(zero), .overflow(overflow),.negative(negative));
对于逻辑部分,您可以使用连续赋值来完成。您可能需要添加一些逻辑 以便仅在 sel
的某些值 期间使用这些标志。
Z ("Zero"): Set to 1 ("True") if the result of the operation is zero
所以,我们可以有像 all 这样的条件 out
的位必须是 zero。这可以通过许多其他方式完成。
// Bit wise OR-ing on out
assign zero = ~(|out);
O ("Overflow"): Set to 1 ("True") to indicate that the operation overflowed the bus width.
根据此描述和显示的代码,您只需要 携带标志 here.That 是 签名扩展 加法运算。溢出条件参见this page on WikiPedia。
但是,溢出条件与进位位不相同。溢出表示数据丢失,而进位表示一位用于下一阶段的计算。
因此,执行以下操作可能会有用:
// Extend the result for capturing carry bit
// Simply use this bit if you want result > bus width
{carry,out} <= a+b;
// overflow in signed arithmetic:
assign overflow = ({carry,out[31]} == 2'b01);
N ("Negative"): Set to 1 ("True") if the first bit of the result is 1, which indicates a negative number
同样,这只是 out
寄存器的 MSB。但是,下溢条件完全是不同的。
// Depending on sel, subtraction must be performed here
assign negative = (out[31] == 1 && (sel == 1 || sel == 2));
此外,像 assign lt = (a<b) ? 1 : 0;
和其他简单条件可以 检测 输入 LT、GT 和 EQ 条件。
参考 the answer here for the overflow/underflow flag understanding. Overflow-Carry link 也可能有用。
有关 ALU 实现的更多信息,请参阅 Carryout-Overflow, ALU in Verilog and ALU PDF。
我正在做作业,有点迷茫,不知道如何开始。我需要在 32 位 ALU 中实现以下标志:
• Z ("Zero"):如果运算结果为零,则设置为 1 ("True")
• N("Negative"):如果结果的第一位为1,则设置为1("True"),表示负数
• O ("Overflow"):设置为1 ("True")表示操作溢出总线宽度。
此外,一个比较函数,比较输入 a 和输入 b,然后设置三个标志之一:
• LT 如果输入 a 小于输入 b
• GT 如果输入 a 大于输入 b
• EQ 如果输入 a 等于输入 b
我需要修改此 ALU 以包含三个标志和比较输出,然后更改测试台以测试所有这些修改。
这就是我收到的关于这项作业的所有信息,实际上没有教科书或任何其他资源。这是一个在线 class,我无法从我的导师那里得到回复。所以我对如何开始有点困惑。在数字逻辑方面,我仍然是一个新手,所以请多多包涵。我只需要一些帮助来理解这些标志和比较是如何工作的。如果有人能向我更好地解释一下它们的工作原理和作用,以及我可能如何将它们实施到 ALU 和测试台中,我将非常感激。
我不指望任何人完成我的作业,我真的只是需要帮助来理解它。
ALU
module alu32 (a, b, out, sel);
input [31:0] a, b;
input [3:0] sel;
output [31:0] out,
reg [31:0] out;
//Code starts here
always @(a, b, sel)
begin
case (sel)
//Arithmetic Functions
0 : out <= a + b;
1 : out <= a - b;
2 : out <= b - a;
3 : out <= a * b;
4 : out <= a / b;
5 : out <= b % a;
//Bit-wise Logic Functions
6 : out <= ~a; //Not
7 : out <= a & b; //And
8 : out <= a | b; //Or
9 : out <= a ^ b; //XOR
10 : out <= a ^~ b; //XNOR
//Logic Functions
11 : out <= !a;
12 : out <= a && b;
13 : out <= a || b;
default: out <= a + b;
endcase
end
endmodule
ALU 测试平台
module alu32_tb();
reg [31:0] a, b;
reg [3:0] sel;
wire [31:0] out;
initial begin
$monitor("sel=%d a=%d b=%d out=%d", sel,a,b,out);
//Fundamental tests - all a+b
#0 sel=4'd0; a = 8'd0; b = 8'd0;
#1 sel=4'd0; a = 8'd0; b = 8'd25;
#1 sel=4'd0; a = 8'd37; b = 8'd0;
#1 sel=4'd0; a = 8'd45; b = 8'd75;
//Arithmetic
#1 sel=4'd1; a = 8'd120; b = 8'd25; //a-b
#1 sel=4'd2; a = 8'd30; b = 8'd120; //b-a
#1 sel=4'd3; a = 8'd75; b = 8'd3; //a*b
#1 sel=4'd4; a = 8'd75; b = 8'd3; //a/b
#1 sel=4'd5; a = 8'd74; b = 8'd3; //a%b
//Bit-wise Logic Functions
#1 sel=4'd6; a = 8'd31; //Not
#1 sel=4'd7; a = 8'd31; b = 8'd31; //And
#1 sel=4'd8; a = 8'd30; b = 8'd1; //Or
#1 sel=4'd9; a = 8'd30; b = 8'd1; //XOR
#1 sel=4'd10; a = 8'd30; b = 8'd1; //XNOR
//Logic Functions
#1 sel=4'd11; a = 8'd25; //Not
#1 sel=4'd12; a = 8'd30; b = 8'd0; //And
#1 sel=4'd13; a = 8'd0; b = 8'd30; //Or
#1 $finish;
end
alu32 myalu (.a(a), .b(b), .out(out), .sel(sel));
endmodule
您可以将这些标记输出添加到设计。像下面这样。只需 连接 它们在测试平台中。
// In design:
output zero;
output overflow;
output negative;
// In testbench:
wire zero,overflow,negative;
alu32 myalu (.a(a), .b(b), .out(out), .sel(sel), .zero(zero), .overflow(overflow),.negative(negative));
对于逻辑部分,您可以使用连续赋值来完成。您可能需要添加一些逻辑 以便仅在 sel
的某些值 期间使用这些标志。
Z ("Zero"): Set to 1 ("True") if the result of the operation is zero
所以,我们可以有像 all 这样的条件 out
的位必须是 zero。这可以通过许多其他方式完成。
// Bit wise OR-ing on out
assign zero = ~(|out);
O ("Overflow"): Set to 1 ("True") to indicate that the operation overflowed the bus width.
根据此描述和显示的代码,您只需要 携带标志 here.That 是 签名扩展 加法运算。溢出条件参见this page on WikiPedia。
但是,溢出条件与进位位不相同。溢出表示数据丢失,而进位表示一位用于下一阶段的计算。
因此,执行以下操作可能会有用:
// Extend the result for capturing carry bit
// Simply use this bit if you want result > bus width
{carry,out} <= a+b;
// overflow in signed arithmetic:
assign overflow = ({carry,out[31]} == 2'b01);
N ("Negative"): Set to 1 ("True") if the first bit of the result is 1, which indicates a negative number
同样,这只是 out
寄存器的 MSB。但是,下溢条件完全是不同的。
// Depending on sel, subtraction must be performed here
assign negative = (out[31] == 1 && (sel == 1 || sel == 2));
此外,像 assign lt = (a<b) ? 1 : 0;
和其他简单条件可以 检测 输入 LT、GT 和 EQ 条件。
参考 the answer here for the overflow/underflow flag understanding. Overflow-Carry link 也可能有用。
有关 ALU 实现的更多信息,请参阅 Carryout-Overflow, ALU in Verilog and ALU PDF。