2015-04-02 65 views
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 

預先感謝您的幫助!

回答

2

在您的測試平臺定義:

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 
); 
+0

哇!非常感謝你的詳細解釋。我還有一個小問題。我的零標誌似乎永遠不會被設置。我不確定這是因爲我的ALU,還是測試臺沒有正確檢查。你能不能介意把它指向正確的方向? – aurora91 2015-04-02 15:58:40

+0

爲了在加法op1_reg上設置零標誌,op2_reg需要爲0.如果我設置了這個激勵,那麼該標誌被置位。 http://www.edaplayground.com/x/Pyh你的代碼對我來說看起來是正確的。我也建議你避免使用手動靈敏度列表,例如用'always @ *'替換'always @(OUT)' – Morgan 2015-04-02 21:01:33

+0

我將reg ZERO更改爲reg ['DATA_INDEX_LIMIT:0] ZERO,它現在可以很好地工作。再次感謝您的幫助! – aurora91 2015-04-02 23:35:16

相關問題