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_we
和 cs
同时为 1(例如从 145ns 开始),两者都试图以不同的值驱动相同的信号。这导致争用,这就是为什么你得到 X
(未知)。
这里有一处三态使能都设置为1:
if(imem_addr==7) begin
dmem_cs = 1;
dmem_data_o <= R[R1]; //STR r1, [r2]
dmem_we = 1;
你需要改变这个逻辑。
我是 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_we
和 cs
同时为 1(例如从 145ns 开始),两者都试图以不同的值驱动相同的信号。这导致争用,这就是为什么你得到 X
(未知)。
这里有一处三态使能都设置为1:
if(imem_addr==7) begin
dmem_cs = 1;
dmem_data_o <= R[R1]; //STR r1, [r2]
dmem_we = 1;
你需要改变这个逻辑。