Search code examples
verilogfpgavivado

My result for matrix multiplication using verilog is not getting displayed


I'm getting my matrix multiplication output waveform in hexadecimal but not in matrix form as shown in

this image link.

The Matrix answer (Res1) is given as {0,0},{0,0} whereas the expected answer would be {19,22},{43,50}. Why do I get this unexpected answer?

// Main file

module mat_mul(A,B,Res);

input [31:0] A;
input [31:0] B;
output [31:0] Res;

//internal variables 

reg [31:0] Res;
reg [7:0] A1 [0:1][0:1];
reg [7:0] B1 [0:1][0:1];
reg [7:0] Res1 [0:1][0:1]; 
integer i,j,k;

always@ (A or B)
begin
//Initialize the matrices-convert 1 D to 3D arrays
    {A1[0][0],A1[0][1],A1[1][0],A1[1][1]} = A;
    {B1[0][0],B1[0][1],B1[1][0],B1[1][1]} = B;
    i = 0;
    j = 0;
    k = 0;
    {Res1[0][0],Res1[0][1],Res1[1][0],Res1[1][1]} = 32'd0;

    //Matrix multiplication
    for(i=0;i < 2;i=i+1)
        for(j=0;j < 2;j=j+1)
            for(k=0;k < 2;k=k+1)
                Res1[i][j] = Res1[i][j] + (A1[i][k] * B1[k][j]);
    //final output assignment - 3D array to 1D array conversion.            
    Res = {Res1[0][0],Res1[0][1],Res1[1][0],Res1[1][1]};   

end 
endmodule

// Test Bench

module mat_mul_tb();

// Inputs
reg [31:0] A;
reg [31:0] B;
reg [7:0] A1[0:1][0:1];
reg [7:0] B1[0:1][0:1];

// Outputs
wire [31:0] Res;
reg [7:0] Res1[0:1][0:1];


// Instantiate the Unit Under Test (UUT)
mat_mul uut (.A(A),.B(B),.Res(Res));

initial begin
    // Apply Inputs
    A = 0;  B = 0;  #100;
    A = {8'd1,8'd2,8'd3,8'd4};
    B = {8'd5,8'd6,8'd7,8'd8};

    {A1[0][0],A1[0][1],A1[1][0],A1[1][1]} = A;
    {B1[0][0],B1[0][1],B1[1][0],B1[1][1]} = B;
    {Res1[0][0],Res1[0][1],Res1[1][0],Res1[1][1]} = Res;

    $display(A1);
    $display(B1);
    $display(Res1);

end
endmodule

Solution

  • There is a race condition between when Res1 is assigned and when you $display its value. You should make sure Res1 is updated whenever Res changes, and you can add a delay before displaying:

    always @* {Res1[0][0],Res1[0][1],Res1[1][0],Res1[1][1]} = Res;
    
    initial begin
        // Apply Inputs
        A = 0;  B = 0;  #100;
        A = {8'd1,8'd2,8'd3,8'd4};
        B = {8'd5,8'd6,8'd7,8'd8};
    
        {A1[0][0],A1[0][1],A1[1][0],A1[1][1]} = A;
        {B1[0][0],B1[0][1],B1[1][0],B1[1][1]} = B;
    //    {Res1[0][0],Res1[0][1],Res1[1][0],Res1[1][1]} = Res;
    
        #1; // Add some delay
        $display(A1);
        $display(B1);
        $display(Res1);
    end
    

    The @* syntax means that every time the RHS of an assignment (Res) changes, the LHS (Res1) is updated. Refer to the free IEEE Std 1800-2012, section 9.4.2.2 Implicit event_expression list.