【问题标题】:Verilog inout port assignment results in XVerilog inout 端口分配导致 X
【发布时间】:2021-11-06 07:05:17
【问题描述】:

我对 Verilog 还很陌生,我遇到了一个特殊的问题,即对 inout 线端口进行分配操作。我面临的问题是在处理器核心模块中分配给输入输出端口 -_memd_data 之后,我在 _memd_data 变量中得到 XXXXXXXX 作为结果,而它应该是 0x5b78193a em>。

有问题的一行: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 模块的数据内存中加载数据,然后使用加密密钥对数据进行 XOR 操作(0x5a5b5c5d) 从 imem 指令地址获取并计算结果并将结果数据存储回 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


【问题讨论】:

    标签: verilog vivado


    【解决方案1】:

    在您的测试台中,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;
    

    你需要改变这个逻辑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多