0
我做了一個樣本ALU以及一些測試平臺代碼。但由於某種原因,我的ALU總是返回一個「Z」作爲結果。有人可以幫我嗎?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
預先感謝您的幫助!
哇!非常感謝你的詳細解釋。我還有一個小問題。我的零標誌似乎永遠不會被設置。我不確定這是因爲我的ALU,還是測試臺沒有正確檢查。你能不能介意把它指向正確的方向? – aurora91 2015-04-02 15:58:40
爲了在加法op1_reg上設置零標誌,op2_reg需要爲0.如果我設置了這個激勵,那麼該標誌被置位。 http://www.edaplayground.com/x/Pyh你的代碼對我來說看起來是正確的。我也建議你避免使用手動靈敏度列表,例如用'always @ *'替換'always @(OUT)' – Morgan 2015-04-02 21:01:33
我將reg ZERO更改爲reg ['DATA_INDEX_LIMIT:0] ZERO,它現在可以很好地工作。再次感謝您的幫助! – aurora91 2015-04-02 23:35:16