ALU 总是返回 Z 作为结果
ALU always returning Z for the result
我制作了一个示例 ALU 以及一些测试平台代码。但出于某种原因,我的 ALU 总是返回一个 'Z' 作为结果。有人可以帮我吗?
这是 ALU:
`include "prj_definition.v"
module ALU(OUT, ZERO, OP1, OP2, OPRN);
// input list
input [`DATA_INDEX_LIMIT:0] OP1; // operand 1
input [`DATA_INDEX_LIMIT:0] OP2; // operand 2
input [`ALU_OPRN_INDEX_LIMIT:0] OPRN; // operation code
// output list
output [`DATA_INDEX_LIMIT:0] OUT; // result of the operation.
output ZERO;
//output registers
output reg OUT;
output reg ZERO;
always @(OP1 or OP2 or OPRN)
begin
// TBD - Code for the ALU
case (OPRN)
`ALU_OPRN_WIDTH'h01 : OUT = OP1 + OP2; // addition
`ALU_OPRN_WIDTH'h02 : OUT = OP1 - OP2; // subtraction
`ALU_OPRN_WIDTH'h03 : OUT = OP1 * OP2; // multiplication
`ALU_OPRN_WIDTH'h04 : OUT = OP1 >> OP2; // shift_right
`ALU_OPRN_WIDTH'h05 : OUT = OP1 << OP2; // shift_left
`ALU_OPRN_WIDTH'h06 : OUT = OP1 & OP2; // bitwise and
`ALU_OPRN_WIDTH'h07 : OUT = OP1 | OP2; // bitwise or
`ALU_OPRN_WIDTH'h08 : OUT = ~(OP1 | OP2); // bitwise nor
`ALU_OPRN_WIDTH'h09 : OUT = OP1 < OP2; // less than
default: OUT = `DATA_WIDTH'hxxxxxxxx;
endcase
end
always @(OUT) //whenever the output changes
begin
if(OUT == 0) ZERO = 1; //if result is 0, set the zero flag
else ZERO = 0; //otherwise keep the 0 flag false
end
endmodule
ALU 测试台:
`timescale 1ns/10ps
`include "prj_definition.v"
module alu_tb;
integer total_test;
integer pass_test;
reg [`ALU_OPRN_INDEX_LIMIT:0] oprn_reg;
reg [`DATA_INDEX_LIMIT:0] op1_reg;
reg [`DATA_INDEX_LIMIT:0] op2_reg;
wire [`DATA_INDEX_LIMIT:0] r_net;
wire [`DATA_INDEX_LIMIT:0] z_net;
// Instantiation of ALU
ALU alu_inst_01(.OUT(r_net), .ZERO(z_net), .OP1(op1_reg),
.OP2(op2_reg), .OPRN(oprn_reg));
// Drive the test patterns and test
initial
begin
op1_reg=0;
op2_reg=0;
oprn_reg=0;
total_test = 0;
pass_test = 0;
// test 15 + 3 = 18
#5 op1_reg=15;
op2_reg=3;
oprn_reg=`ALU_OPRN_WIDTH'h01;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h02;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h01;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
//
// TBD: Fill out for other operations
//
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h03;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h04;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h05;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h06;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h07;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h08;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h09;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 $write("\n");
$write("\tTotal number of tests %d\n", total_test);
$write("\tTotal number of pass %d\n", pass_test);
$write("\n");
$stop; // stop simulation here
end
//-----------------------------------------------------------------------------
// TASK: test_and_count
//
// PARAMETERS:
// INOUT: total_test ; total test counter
// INOUT: pass_test ; pass test counter
// INPUT: test_status ; status of the current test 1 or 0
//
// NOTES: Keeps track of number of test and pass cases.
//
//-----------------------------------------------------------------------------
task test_and_count;
inout total_test;
inout pass_test;
input test_status;
integer total_test;
integer pass_test;
begin
total_test = total_test + 1;
if (test_status)
begin
pass_test = pass_test + 1;
end
end
endtask
//-----------------------------------------------------------------------------
// FUNCTION: test_golden
//
// PARAMETERS: op1, op2, oprn and result
// RETURN: 1 or 0 if the result matches golden
//
// NOTES: Tests the result against the golden. Golden is generated inside.
//
//-----------------------------------------------------------------------------
function test_golden;
input [`DATA_INDEX_LIMIT:0] op1;
input [`DATA_INDEX_LIMIT:0] op2;
input [`ALU_OPRN_INDEX_LIMIT:0] oprn;
input [`DATA_INDEX_LIMIT:0] res;
input [`DATA_INDEX_LIMIT:0] zero;
reg [`DATA_INDEX_LIMIT:0] golden; // expected result
begin
$write("[TEST] %0d ", op1);
case(oprn)
`ALU_OPRN_WIDTH'h01 : begin $write("+ "); golden = op1 + op2; end
//
// TBD: fill out for the other operations
//
`ALU_OPRN_WIDTH'h02 : begin $write("- "); golden = op1 - op2; end
`ALU_OPRN_WIDTH'h03 : begin $write("* "); golden = op1 * op2; end
`ALU_OPRN_WIDTH'h04 : begin $write(">> "); golden = op1 >> op2; end
`ALU_OPRN_WIDTH'h05 : begin $write("<< "); golden = op1 << op2; end
`ALU_OPRN_WIDTH'h06 : begin $write("AND "); golden = op1 & op2; end
`ALU_OPRN_WIDTH'h07 : begin $write("OR "); golden = op1 | op2; end
`ALU_OPRN_WIDTH'h08 : begin $write("NOR "); golden = ~(op1 | op2); end
`ALU_OPRN_WIDTH'h09 : begin $write("< "); golden = op1 < op2; end
default: begin $write("? "); golden = `DATA_WIDTH'hx; end
endcase
$write("%0d = %0d , got %0d ... ", op2, golden, res);
test_golden = (res === golden)?1'b1:1'b0; // case equality
if (test_golden)
$write("[PASSED]");
else
$write("[FAILED]");
if(zero === 0)
$write("[ZERO FLAG SET]");
$write("\n");
end
endfunction
endmodule
提前感谢您的帮助!
在您的测试平台中,您定义:
wire [`DATA_INDEX_LIMIT:0] z_net;
ALU alu_inst_01( .ZERO(z_net) //..
但是模块内部的零被定义为一个位:
output reg ZERO;
因此该模块将仅驱动测试台的 LSB,其余 bis 未连接 (z
)。
你对输出的定义导致了一些错误。
module ALU(OUT, ZERO, OP1, OP2, OPRN);
// input list
input [`DATA_INDEX_LIMIT:0] OP1; // operand 1
input [`DATA_INDEX_LIMIT:0] OP2; // operand 2
input [`ALU_OPRN_INDEX_LIMIT:0] OPRN; // operation code
// output list
output [`DATA_INDEX_LIMIT:0] OUT; // result of the operation.
output ZERO;
//output registers
output reg OUT;
output reg ZERO;
您已重新声明为输出,宽度应包含在使用此语法的 reg 定义中正确的格式为:
module ALU(OUT, ZERO, OP1, OP2, OPRN);
// input list
input [`DATA_INDEX_LIMIT:0] OP1; // operand 1
input [`DATA_INDEX_LIMIT:0] OP2; // operand 2
input [`ALU_OPRN_INDEX_LIMIT:0] OPRN; // operation code
// output list
output OUT; // result of the operation.
output ZERO;
//output registers
reg [`DATA_INDEX_LIMIT:0] OUT;
reg ZERO;
现代风格是:
module ALU(
// output list
output reg [`DATA_INDEX_LIMIT:0] OUT, // result of the operation.
output reg ZERO,
// input list
input [`DATA_INDEX_LIMIT:0] OP1, // operand 1
input [`DATA_INDEX_LIMIT:0] OP2, // operand 2
input [`ALU_OPRN_INDEX_LIMIT:0] OPRN // operation code
);
我制作了一个示例 ALU 以及一些测试平台代码。但出于某种原因,我的 ALU 总是返回一个 'Z' 作为结果。有人可以帮我吗?
这是 ALU:
`include "prj_definition.v"
module ALU(OUT, ZERO, OP1, OP2, OPRN);
// input list
input [`DATA_INDEX_LIMIT:0] OP1; // operand 1
input [`DATA_INDEX_LIMIT:0] OP2; // operand 2
input [`ALU_OPRN_INDEX_LIMIT:0] OPRN; // operation code
// output list
output [`DATA_INDEX_LIMIT:0] OUT; // result of the operation.
output ZERO;
//output registers
output reg OUT;
output reg ZERO;
always @(OP1 or OP2 or OPRN)
begin
// TBD - Code for the ALU
case (OPRN)
`ALU_OPRN_WIDTH'h01 : OUT = OP1 + OP2; // addition
`ALU_OPRN_WIDTH'h02 : OUT = OP1 - OP2; // subtraction
`ALU_OPRN_WIDTH'h03 : OUT = OP1 * OP2; // multiplication
`ALU_OPRN_WIDTH'h04 : OUT = OP1 >> OP2; // shift_right
`ALU_OPRN_WIDTH'h05 : OUT = OP1 << OP2; // shift_left
`ALU_OPRN_WIDTH'h06 : OUT = OP1 & OP2; // bitwise and
`ALU_OPRN_WIDTH'h07 : OUT = OP1 | OP2; // bitwise or
`ALU_OPRN_WIDTH'h08 : OUT = ~(OP1 | OP2); // bitwise nor
`ALU_OPRN_WIDTH'h09 : OUT = OP1 < OP2; // less than
default: OUT = `DATA_WIDTH'hxxxxxxxx;
endcase
end
always @(OUT) //whenever the output changes
begin
if(OUT == 0) ZERO = 1; //if result is 0, set the zero flag
else ZERO = 0; //otherwise keep the 0 flag false
end
endmodule
ALU 测试台:
`timescale 1ns/10ps
`include "prj_definition.v"
module alu_tb;
integer total_test;
integer pass_test;
reg [`ALU_OPRN_INDEX_LIMIT:0] oprn_reg;
reg [`DATA_INDEX_LIMIT:0] op1_reg;
reg [`DATA_INDEX_LIMIT:0] op2_reg;
wire [`DATA_INDEX_LIMIT:0] r_net;
wire [`DATA_INDEX_LIMIT:0] z_net;
// Instantiation of ALU
ALU alu_inst_01(.OUT(r_net), .ZERO(z_net), .OP1(op1_reg),
.OP2(op2_reg), .OPRN(oprn_reg));
// Drive the test patterns and test
initial
begin
op1_reg=0;
op2_reg=0;
oprn_reg=0;
total_test = 0;
pass_test = 0;
// test 15 + 3 = 18
#5 op1_reg=15;
op2_reg=3;
oprn_reg=`ALU_OPRN_WIDTH'h01;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h02;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h01;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
//
// TBD: Fill out for other operations
//
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h03;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h04;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h05;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h06;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h07;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h08;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 op1_reg=15;
op2_reg=5;
oprn_reg=`ALU_OPRN_WIDTH'h09;
#5 test_and_count(total_test, pass_test,
test_golden(op1_reg,op2_reg,oprn_reg,r_net,z_net));
#5 $write("\n");
$write("\tTotal number of tests %d\n", total_test);
$write("\tTotal number of pass %d\n", pass_test);
$write("\n");
$stop; // stop simulation here
end
//-----------------------------------------------------------------------------
// TASK: test_and_count
//
// PARAMETERS:
// INOUT: total_test ; total test counter
// INOUT: pass_test ; pass test counter
// INPUT: test_status ; status of the current test 1 or 0
//
// NOTES: Keeps track of number of test and pass cases.
//
//-----------------------------------------------------------------------------
task test_and_count;
inout total_test;
inout pass_test;
input test_status;
integer total_test;
integer pass_test;
begin
total_test = total_test + 1;
if (test_status)
begin
pass_test = pass_test + 1;
end
end
endtask
//-----------------------------------------------------------------------------
// FUNCTION: test_golden
//
// PARAMETERS: op1, op2, oprn and result
// RETURN: 1 or 0 if the result matches golden
//
// NOTES: Tests the result against the golden. Golden is generated inside.
//
//-----------------------------------------------------------------------------
function test_golden;
input [`DATA_INDEX_LIMIT:0] op1;
input [`DATA_INDEX_LIMIT:0] op2;
input [`ALU_OPRN_INDEX_LIMIT:0] oprn;
input [`DATA_INDEX_LIMIT:0] res;
input [`DATA_INDEX_LIMIT:0] zero;
reg [`DATA_INDEX_LIMIT:0] golden; // expected result
begin
$write("[TEST] %0d ", op1);
case(oprn)
`ALU_OPRN_WIDTH'h01 : begin $write("+ "); golden = op1 + op2; end
//
// TBD: fill out for the other operations
//
`ALU_OPRN_WIDTH'h02 : begin $write("- "); golden = op1 - op2; end
`ALU_OPRN_WIDTH'h03 : begin $write("* "); golden = op1 * op2; end
`ALU_OPRN_WIDTH'h04 : begin $write(">> "); golden = op1 >> op2; end
`ALU_OPRN_WIDTH'h05 : begin $write("<< "); golden = op1 << op2; end
`ALU_OPRN_WIDTH'h06 : begin $write("AND "); golden = op1 & op2; end
`ALU_OPRN_WIDTH'h07 : begin $write("OR "); golden = op1 | op2; end
`ALU_OPRN_WIDTH'h08 : begin $write("NOR "); golden = ~(op1 | op2); end
`ALU_OPRN_WIDTH'h09 : begin $write("< "); golden = op1 < op2; end
default: begin $write("? "); golden = `DATA_WIDTH'hx; end
endcase
$write("%0d = %0d , got %0d ... ", op2, golden, res);
test_golden = (res === golden)?1'b1:1'b0; // case equality
if (test_golden)
$write("[PASSED]");
else
$write("[FAILED]");
if(zero === 0)
$write("[ZERO FLAG SET]");
$write("\n");
end
endfunction
endmodule
提前感谢您的帮助!
在您的测试平台中,您定义:
wire [`DATA_INDEX_LIMIT:0] z_net;
ALU alu_inst_01( .ZERO(z_net) //..
但是模块内部的零被定义为一个位:
output reg ZERO;
因此该模块将仅驱动测试台的 LSB,其余 bis 未连接 (z
)。
你对输出的定义导致了一些错误。
module ALU(OUT, ZERO, OP1, OP2, OPRN);
// input list
input [`DATA_INDEX_LIMIT:0] OP1; // operand 1
input [`DATA_INDEX_LIMIT:0] OP2; // operand 2
input [`ALU_OPRN_INDEX_LIMIT:0] OPRN; // operation code
// output list
output [`DATA_INDEX_LIMIT:0] OUT; // result of the operation.
output ZERO;
//output registers
output reg OUT;
output reg ZERO;
您已重新声明为输出,宽度应包含在使用此语法的 reg 定义中正确的格式为:
module ALU(OUT, ZERO, OP1, OP2, OPRN);
// input list
input [`DATA_INDEX_LIMIT:0] OP1; // operand 1
input [`DATA_INDEX_LIMIT:0] OP2; // operand 2
input [`ALU_OPRN_INDEX_LIMIT:0] OPRN; // operation code
// output list
output OUT; // result of the operation.
output ZERO;
//output registers
reg [`DATA_INDEX_LIMIT:0] OUT;
reg ZERO;
现代风格是:
module ALU(
// output list
output reg [`DATA_INDEX_LIMIT:0] OUT, // result of the operation.
output reg ZERO,
// input list
input [`DATA_INDEX_LIMIT:0] OP1, // operand 1
input [`DATA_INDEX_LIMIT:0] OP2, // operand 2
input [`ALU_OPRN_INDEX_LIMIT:0] OPRN // operation code
);