X 中的 Verilog inout 端口分配结果

Verilog inout port assignment results in X

我是 Verilog 的新手,我遇到了一个对 inout 线端口进行赋值操作的特殊问题。我遇到的问题是在 processor_core 模块中分配到 inout 端口 -_memd_data 之后,我得到 XXXXXXXX 作为 _memd_data 中的结果变量应该是 0x5b78193a.

有问题的行:assign _memd_data = (mem_dWE)? mem_o_data : 32'bz

在分配数据之前,下面是执行上面那行之前发生的代码行(无法弄清楚哪里出了问题,对我来说看起来完全没问题)。

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

这个小项目的简要说明:基本上它模拟了单个循环处理器的工作。 processor_core 模块应该能够根据给定的地址从 imem 模块中获取内存并对获取的指令进行解码,然后从 dmem 模块的数据内存中加载数据,然后 condition_uct 异或使用从 imem 指令地址获取的加密密钥 (0x5a5b5c5d) 对数据进行操作并计算结果并将结果数据存储回 dmem 模块以替换旧数据。还模拟数据加密。

注意:我只需要实现processor_core模块,感觉已经很接近了,但离实现还差得很远..

我正在使用 Vivado 软件对此进行编码。

测试台

`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

设计来源

`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


在您的测试台中,dmem_data 线连接到 2 个模块实例输出端口:

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

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

这很好,但前提是其中之一处于活动状态。您的问题是两个驱动程序同时处于活动状态。这些是 2 个驱动程序:

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

由于 dmem_wecs 同时为 1(例如从 145ns 开始),两者都试图以不同的值驱动相同的信号。这导致争用,这就是为什么你得到 X(未知)。

这里有一处三态使能都设置为1:

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

你需要改变这个逻辑。