user10995546
user10995546

Reputation: 77

Verilog inout port assignment results in X

I am fairly new to Verilog and I am stuck on a particular problem of doing an assignment operation to an inout wire port. The issue I faced is after the assignment to the inout port -_memd_data in the processor_core module, I get XXXXXXXX as the result in the _memd_data variable when it should be 0x5b78193a.

Line with issue: assign _memd_data = (mem_dWE)? mem_o_data : 32'bz;

Before assigning the data, below are the lines of code that occured before the execution of that line above (can't figure out what is wrong, looks completely fine to me).

    STR: //Result store
    begin
    if(memAddr==7) begin
         
         csmemd = 1;     
        mem_o_data <= R[R1]; //STR r1, [r2]
        mem_dWE = 1;
        memAddr <= memAddr + Addr; 

Brief explanation of this small project: Basically it simulates the workings of a single cycle processor. The processor_core module should be able to fetch memory from the imem module based on a given address and decode the instruction fetched, then load the data from the data memory which is the dmem module, then condition_uct a XOR operation on the data with an encryption key(0x5a5b5c5d) fetched from the imem instruction address and compute the result and store the resulting data back to the dmem module to replace the old data. Also simulates an encryption of data.

Note: I only need to implement the processor_core module, feels like I am so close, but yet so far from getting it done..

I am using Vivado software to code this.

TestBench

`timescale 1ns / 1ps
module Nexys4_MAT_Top(
//CLK Input
  input         CLK100MHZ ,
  input         CPU_RESETN,
//Push Button Inputs
  input         BTNC      ,
// Slide Switch Inputs
  input  [15:0] SW        , 
// LED Outputs
  output [15:0] LED       ,
// Seven Segment Display Outputs
  output        CA        ,
  output        CB        ,
  output        CC        ,
  output        CD        ,
  output        CE        ,
  output        CF        ,
  output        CG        ,
  output [ 7:0] AN        ,
  output        DP        
);
//CLK: 100MHz
parameter       periodCLK_2     = 5; 
parameter       perioddump      = 10;
parameter       delay           = 1;
parameter       delay_in        = 2; 
   
//Clock & reset signals
wire          clk_main       ;
wire          rstn           ;

//Processor signals
wire [ 4:0] memAddr       ;
wire [31:0] memData_I       ;
wire [ 5:0] memAddr_d       ;
wire [31:0] _memd_data       ;
wire [31:0] _memd_data_cpu   ;
wire        dmem_wr         ;
wire        csmemd         ;

 
 
 reg             CLK_TB;
reg             RSTN;
 
  // CLK_TB //
initial 
begin
  CLK_TB = 1'b0;
  #(perioddump);
  CLK_TB = 1'b1;
  forever
  begin
    CLK_TB = !CLK_TB;
    #(periodCLK_2);
  end
end
initial begin 
  global_reset(); 
  repeat(1)  @(posedge CLK_TB); #delay;
 
  repeat(1) @(posedge CLK_TB); #delay;
  
  repeat(10) @(posedge CLK_TB);#delay; 
end

task global_reset;
begin
  repeat(2)  @(posedge CLK_TB);   #delay; 
 
  repeat(2)  @(posedge CLK_TB); #delay;
  RSTN          = 1'b0;
  
  repeat(2) @(posedge CLK_TB); #delay;
  RSTN          = 1'b1;
 
end
endtask
 
// Circuit implementation
clkrst u_clkrst(
  .CLK100MHZ   (CLK_TB      ),
  .rst_btn     (RSTN     ),
  .clk_out     (clk_main       ),
  .rstn        (rstn           ) 
);
processor_core u_processor(
  .clk         (clk_main      ),
  .rstn        (rstn          ),
  .memAddr   (memAddr     ),
  .memData_I   (memData_I     ),
  .memAddr_d   (_memd_data_cpu ),
  ._memd_data   (_memd_data     ),
  .mem_dWE     (mem_dWE       ),
  .csmemd     (csmemd       )
);


imem u_imem(
  .clk         (clk_main      ),
  .rstn        (rstn          ),
  .addr        (memAddr     ),
  .cs          (1'b1          ),
  .we          (1'b0          ),
  .data        (memData_I     ) 
);

dmem u_dmem(
  .clk         (clk_main      ),
  .rstn        (rstn          ),
  .addr        (_memd_data_cpu     ),
  .cs          (csmemd       ),
  .we          (mem_dWE       ),
  .data        (_memd_data     ) 
);
 
 

endmodule

Design sources

`timescale 1ns / 1ps


module processor_core(
  input         clk          ,//Input clock
  input         rstn         ,//Reset signal, low active
  output [ 4:0] memAddr    ,//instruction memory address
  input  [31:0] memData_I    ,//instruction memory data
  output [ 5:0] memAddr_d    ,//data memory address
  inout  [31:0] _memd_data    ,
  output        mem_dWE      ,
  output        csmemd       
);

// For I/O signals
reg    [ 4:0] memAddr      ;
reg    [ 5:0] memAddr_d      ;
reg           mem_dWE        ;
reg           csmemd        ;
 
// For internal signals
reg    [31:0] _memd_data_i    ;//The input data from dmem
reg    [31:0] mem_o_data    ;//The output data for dmem


parameter       AND        = 4'h2; 
parameter       SUB        = 4'h4; 
parameter       ORR        = 4'h5; 
parameter       XOR        = 4'h1; 
parameter       ADD        = 4'h2; 
parameter       MOV        = 4'h3; 
parameter       LDR        = 4'h5; 
parameter       STR        = 4'h6;  
parameter       CMP        = 4'h4; 
parameter N = 3;
parameter Z = 2;
parameter C = 1;
parameter V = 0;
   reg [3:0] nzcv_; 

parameter Addr = 1;
  
reg[31:0] condition_;
reg[0:0] condition_tionCarry;

reg[3:0] Aluchk;
reg[3:0]Opcde_chk;

reg[31:0]Br_check;
reg[7:0]IVal;
reg[23:0]branc_offs;

reg[3:0] R1;
reg[3:0] R2;
reg[3:0] R3;

reg[31:0] R[15:0];
reg     [31:0] b;
 
 integer index; 
 integer clk_count;
 
assign _memd_data = (mem_dWE)? mem_o_data : 32'bz; //Issue with assignment


always @ (posedge clk or negedge rstn) begin
  if (!rstn) begin
    _memd_data_i <= 32'h0;
  end
  else begin
    _memd_data_i <= _memd_data;
  end
end
 
always @ (posedge clk or negedge rstn)
begin 
    if(!rstn) begin
    
        nzcv_[N] = 0;
        nzcv_[Z] = 0;
        nzcv_[C] = 0;
        nzcv_[V] = 0;

        Br_check<=32'h0;
        IVal<=0;
        mem_o_data = 32'h0;
        R1<=0;
        R2<=0;
        R3<=0; 
    end
    else begin
        Aluchk = memData_I[31:31];

     R1 = memData_I[15:12]; 
    R2 = memData_I[11:8]; 
    R3 = memData_I[7:4]; 
    
    branc_offs = memData_I[27:4];
    Opcde_chk = memData_I[30:28];
    Br_check = memData_I[31:0]; 
    IVal = memData_I[27:16];

        case(Br_check)
        BEQ:
        begin
        if(nzcv_[Z] == 1'b1) //BEQ Done
             $stop; 
         end 
        BNE:
        begin
        if(nzcv_[Z] == 1'b0)
             memAddr <= memAddr - branc_offs; 
         end 

 
    case(Aluchk)
            1'b1:
        begin
            case(Opcde_chk) 
                XOR: //ADD ompute Result
                begin
                if(memAddr==6) begin
//                    csmemd = 0;
                    R[R1] = R[R2] ^ R[R3];
//                    mem_dWE = 1;
//                    csmemd = 1;   
                    mem_o_data <= R[R1];       
                    memAddr <= memAddr + Addr; 
                   
                end
                end
                ADD:
                begin
//                mem_dWE = 0;
                if(memAddr==8) begin
                    mem_dWE = 0;
//                    R[R2]<=R[R2]+IVal; 
                    memAddr_d<=memAddr_d+IVal; 
//                    memAddr_d = R[R2];
                    memAddr <= memAddr + Addr;      
                end
                end
 
            endcase
        end
        1'b0:
        begin
            case(Opcde_chk) 
                MOV:
                begin
                    clk_count = clk_count + 1;
                    if(memAddr==0) begin
                        R[R3][31:24] <= IVal; 
                    end
                    if(memAddr==4 && clk_count == 5) begin
                        R[R2] <= IVal; 
                    end
                        memAddr <= memAddr + Addr; 
                end
   
                LDR:
                begin
                if(memAddr==5) begin
                    csmemd = 1;
                    R[R1] = 0;
                    R[R1] = _memd_data_i;  //LDR r1, [r2]
                    memAddr <= memAddr + Addr; 
                end
                end
                STR: //Result store
                begin
                if(memAddr==7) begin
                     
                     csmemd = 1;     
                    mem_o_data <= R[R1]; 
                    mem_dWE = 1;
                    memAddr <= memAddr + Addr; 
                    
//                    mem_o_data = R[R1]; 
                end    
                end
            endcase
        end
        

    endcase    

end
end

endmodule

`timescale 1ns / 1ps



module dmem(
  input         clk          ,//Input clock
  input         rstn         ,//Reset signal, low active
  input  [ 5:0] addr         ,//memory address
  input         cs           , 
  input         we           , 
  inout  [31:0] data          
);
// For I/O signals

// For internal signals
reg  [31:0]   mem[0:63]      ; 
// Circuit implementation
assign data  = (cs) ? mem[addr] : 32'bz;

always @ (posedge clk or negedge rstn) begin
  if (!rstn) begin
    //The hard coded data, or plain text 
    mem[ 0] <= 32'h43314220;
    mem[ 1] <= 32'h42020032;
    mem[ 2] <= 32'h00650039;   
    mem[ 3] <= 32'h01150032;
    mem[ 4] <= 32'h01150097;
    mem[ 5] <= 32'h01020101;
    mem[ 6] <= 32'h00320116;
    mem[ 7] <= 32'h01010120;
    mem[ 8] <= 32'h01160032;
    mem[ 9] <= 32'h01190105;
    mem[10] <= 32'h01160104;
    mem[11] <= 32'h00320099;
    mem[12] <= 32'h01110100;
    mem[13] <= 32'h01010032;
    mem[14] <= 32'h00480120;
    mem[15] <= 32'h00490050;
    mem[16] <= 32'h00510052;
    mem[17] <= 32'h00330000; 
  end
  else begin
    if (we&&cs)
    begin
      mem[addr] <= data;
    end
  end
end

endmodule

`timescale 1ns / 1ps


`timescale 1ns / 1ps



module imem(
  input         clk          ,//Input clock
  input         rstn         ,//Reset signal, low active
  input  [ 4:0] addr         ,//memory address
  input         cs           , 
  input         we           , 
  inout  [31:0] data          
);
// For I/O signals

// For internal signals
reg  [31:0]   mem[0:11]      ; 
// Circuit implementation
assign data  = (cs) ? mem[addr] : 32'bz;

always @ (posedge clk or negedge rstn) begin
  if (!rstn) begin
 
    //The hard coded instructions
    mem[ 0] <= 32'h10330030;
    mem[ 1] <= 32'h203f0030;
    mem[ 2] <= 32'h30120030;
    mem[ 3] <= 32'h40220030;
    mem[ 4] <= 32'h30000230;
    mem[ 5] <= 32'h50001200;
    mem[ 6] <= 32'h90005130;
    mem[ 7] <= 32'h10006000;
    mem[ 8] <= 32'ha3011430;
    mem[ 9] <= 32'h40120400;
    mem[10] <= 32'h200000b1;
    mem[11] <= 32'h20000000; 
  end
  else begin 
    if (cs && we)
    begin 
      mem[addr] = data;
    end
  end
end

endmodule


module clkrst(
  input         CLK100MHZ   ,//On-board input clock
  input         rst_btn     ,//On-board reset from button, HIGH active
  output        clk_out     ,//The working clk for the rest of circuit
  output        rstn         //The working reset for the rest of circuit, LOW active
);
// For I/O signals
reg           clk_50m       ;
reg           clk_25m       ;

// For internal signals




// Circuit implementation
assign rstn  = rst_btn;
assign clk_out = CLK100MHZ;

endmodule


Upvotes: 1

Views: 793

Answers (1)

toolic
toolic

Reputation: 62037

In your testbench, the dmem_data wire is connected to 2 module instance output ports:

processor_core u_processor(
  .dmem_data   (dmem_data     ),
  //...
);

dmem u_dmem(
  .data        (dmem_data     ) 
  //...
);

That is fine, but only if one of them is active. Your problem is that both drivers are active at the same time. These are the 2 drivers:

assign dmem_data = (dmem_we)? dmem_data_o : 32'bz; //Issue with assignment
assign data  = (cs) ? mem[addr] : 32'bz;

Since dmem_we and cs are both 1 at the same time (starting at time 145ns, for example), both are trying to drive the same signal with different values. This results in contention which is why you get X (unknown).

Here is one place where the tristate enables are both set to 1:

        if(imem_addr==7) begin
             
             dmem_cs = 1;     
            dmem_data_o <= R[R1]; //STR r1, [r2]
            dmem_we = 1;

You need to change this logic.

Upvotes: 1

Related Questions