Verilog Icarus 给出未定义的值
Verilog Icarus giving undefined values
我正在从事一个项目,在该项目中我正在使用 Icarus Verilog 0.9.7 设计一个简单的 RISC 机器。
此代码是模块化的,最后我将把几个组件放在一起,但我在处理内存控制器时 运行 遇到了问题。对于我所有的测试值,我得到未定义的输出,或 'Z'。我怎样才能解决这个问题?我看不出有任何理由不填充这些值。
定义内存控制器应该具有的所有行为超出了这个问题的范围,所以我会尽量保持简短并以 Verilog 为主题。
这是我当前的 Verilog 代码。 workbench 有两个文件,mem.sv 和 SrcMemoryController.sv:
`default_nettype none
module SrcMemoryController(
inout [31:0] cpu_bus,
inout [31:0] mem_bus,
input ma_in,
input md_in,
input md_out,
input read,
input enable,
output [15:0] address
);
reg [31:0] ma = 32'bz;
reg [31:0] md = 32'bz;
wire [31:0] cpb = cpu_bus;
wire [31:0] meb = mem_bus;
always @(*) begin
if(ma_in) ma = cpb;
if(md_in) md = cpb;
if(read) begin
if(enable) md = meb;
end
end
assign cpu_bus = (md_out) ? md : 32'bz;
assign mem_bus = (~read && enable) ? md : 32'bz;
assign address = ma;
endmodule
mem.sv 目前有效,不是这个问题的根源。无论如何我都会包括它以防它有帮助。
`default_nettype none
module Memory (
inout [31:0] mem_bus,
input [15:0] address,
input read,
input enable
);
reg [31:0] storage [65535:0];
always @(enable) begin
if(enable) begin
if(read) begin
end
if(!read) begin
storage[address] = mem_bus;
end
end
end
assign mem_bus = (read) ? storage[address] : 32'bz;
endmodule
这也是测试平台。可能不需要,但发布它可能会有所帮助。
`default_nettype none
`include "mem.sv"
module tb_MemoryController;
wire [31:0] mem_bus;
wire [31:0] cpu_bus;
reg [31:0] bus_sim;
reg bus_sim_out = 0;
// Tri-state buffer
assign cpu_bus = bus_sim_out ? bus_sim : 32'bz;
reg ma_in, md_in, md_out;
reg read, enable;
wire [15:0] address;
Memory vmem( mem_bus, address, read, enable );
SrcMemoryController dut( cpu_bus, mem_bus, ma_in, md_in, md_out,
read, enable, address );
initial begin
$dumpfile("mem_file.vcd");
$dumpvars(0, dut);
$dumpvars(0, vmem);
test_memory(0, 0);
test_memory(10, 0);
#1 assert_empty(mem_bus);
#1 assert_empty(cpu_bus);
test_memory(65535, 65535);
test_memory(1231, 123);
test_memory(1231231, 65535);
test_memory(0, 65535);
test_memory(100, 100);
test_memory(515, 515);
#1 assert_empty(mem_bus);
#1 assert_empty(cpu_bus);
$finish();
end
task test_memory;
input [31:0] data;
input [15:0] addr;
begin
#1
zero_inputs();
#1
write_value(data, addr);
#1
load_spoof();
#1
read_value(addr);
#1
assertEquals(cpu_bus, data);
zero_inputs();
end
endtask
task write_value;
input [31:0] data;
input [15:0] addr;
begin
#1
enable <= 0;
bus_sim <= addr;
bus_sim_out <= 1;
ma_in <= 1;
#1
bus_sim <= data;
bus_sim_out <= 1;
ma_in <= 0;
md_in <= 1;
read <= 0;
enable <= 1;
end
endtask
task read_value;
input [15:0] addr;
begin
#1
enable <= 0;
bus_sim <= addr;
bus_sim_out <= 1;
ma_in <= 1;
#1
ma_in <= 0;
read <= 1;
enable <= 1;
bus_sim_out <= 0;
md_out <= 1;
end
endtask
task load_spoof;
begin
#1
bus_sim <= 32'hABCDABCD;
bus_sim_out <= 1;
ma_in <= 1;
md_in <= 1;
read <= 0;
enable <= 0;
#1
zero_inputs();
end
endtask
task zero_inputs;
begin
ma_in <= 0;
md_in <= 0;
md_out <= 0;
read <= 0;
enable <= 0;
bus_sim_out <= 0;
end
endtask
task pulseClock;
begin
end
endtask
task assertEquals;
input [31:0] val;
input [31:0] exp;
begin
if (val == exp) $display("[TEST][PASSED] %d", val);
else $display("[TEST][FAILED] Got %d, expected %d", val, exp);
end
endtask
task assert_empty;
input [31:0] a;
begin
if (a === 32'bz) $display("[TEST][PASSED] (Bus empty)", a);
else $display("[TEST][FAILED] (Value on bus)", a, 32'bz);
end
endtask
endmodule
感谢所有帮助。谢谢!
凯文在评论中给出的答案,我将详细说明它是如何修复的。
我将 mem.sv 中的 always @(enable) 更改为 always @(*),在更改后,其余代码立即开始工作并具有完整功能。非常感谢 Kevin1494!
我正在从事一个项目,在该项目中我正在使用 Icarus Verilog 0.9.7 设计一个简单的 RISC 机器。
此代码是模块化的,最后我将把几个组件放在一起,但我在处理内存控制器时 运行 遇到了问题。对于我所有的测试值,我得到未定义的输出,或 'Z'。我怎样才能解决这个问题?我看不出有任何理由不填充这些值。
定义内存控制器应该具有的所有行为超出了这个问题的范围,所以我会尽量保持简短并以 Verilog 为主题。
这是我当前的 Verilog 代码。 workbench 有两个文件,mem.sv 和 SrcMemoryController.sv:
`default_nettype none
module SrcMemoryController(
inout [31:0] cpu_bus,
inout [31:0] mem_bus,
input ma_in,
input md_in,
input md_out,
input read,
input enable,
output [15:0] address
);
reg [31:0] ma = 32'bz;
reg [31:0] md = 32'bz;
wire [31:0] cpb = cpu_bus;
wire [31:0] meb = mem_bus;
always @(*) begin
if(ma_in) ma = cpb;
if(md_in) md = cpb;
if(read) begin
if(enable) md = meb;
end
end
assign cpu_bus = (md_out) ? md : 32'bz;
assign mem_bus = (~read && enable) ? md : 32'bz;
assign address = ma;
endmodule
mem.sv 目前有效,不是这个问题的根源。无论如何我都会包括它以防它有帮助。
`default_nettype none
module Memory (
inout [31:0] mem_bus,
input [15:0] address,
input read,
input enable
);
reg [31:0] storage [65535:0];
always @(enable) begin
if(enable) begin
if(read) begin
end
if(!read) begin
storage[address] = mem_bus;
end
end
end
assign mem_bus = (read) ? storage[address] : 32'bz;
endmodule
这也是测试平台。可能不需要,但发布它可能会有所帮助。
`default_nettype none
`include "mem.sv"
module tb_MemoryController;
wire [31:0] mem_bus;
wire [31:0] cpu_bus;
reg [31:0] bus_sim;
reg bus_sim_out = 0;
// Tri-state buffer
assign cpu_bus = bus_sim_out ? bus_sim : 32'bz;
reg ma_in, md_in, md_out;
reg read, enable;
wire [15:0] address;
Memory vmem( mem_bus, address, read, enable );
SrcMemoryController dut( cpu_bus, mem_bus, ma_in, md_in, md_out,
read, enable, address );
initial begin
$dumpfile("mem_file.vcd");
$dumpvars(0, dut);
$dumpvars(0, vmem);
test_memory(0, 0);
test_memory(10, 0);
#1 assert_empty(mem_bus);
#1 assert_empty(cpu_bus);
test_memory(65535, 65535);
test_memory(1231, 123);
test_memory(1231231, 65535);
test_memory(0, 65535);
test_memory(100, 100);
test_memory(515, 515);
#1 assert_empty(mem_bus);
#1 assert_empty(cpu_bus);
$finish();
end
task test_memory;
input [31:0] data;
input [15:0] addr;
begin
#1
zero_inputs();
#1
write_value(data, addr);
#1
load_spoof();
#1
read_value(addr);
#1
assertEquals(cpu_bus, data);
zero_inputs();
end
endtask
task write_value;
input [31:0] data;
input [15:0] addr;
begin
#1
enable <= 0;
bus_sim <= addr;
bus_sim_out <= 1;
ma_in <= 1;
#1
bus_sim <= data;
bus_sim_out <= 1;
ma_in <= 0;
md_in <= 1;
read <= 0;
enable <= 1;
end
endtask
task read_value;
input [15:0] addr;
begin
#1
enable <= 0;
bus_sim <= addr;
bus_sim_out <= 1;
ma_in <= 1;
#1
ma_in <= 0;
read <= 1;
enable <= 1;
bus_sim_out <= 0;
md_out <= 1;
end
endtask
task load_spoof;
begin
#1
bus_sim <= 32'hABCDABCD;
bus_sim_out <= 1;
ma_in <= 1;
md_in <= 1;
read <= 0;
enable <= 0;
#1
zero_inputs();
end
endtask
task zero_inputs;
begin
ma_in <= 0;
md_in <= 0;
md_out <= 0;
read <= 0;
enable <= 0;
bus_sim_out <= 0;
end
endtask
task pulseClock;
begin
end
endtask
task assertEquals;
input [31:0] val;
input [31:0] exp;
begin
if (val == exp) $display("[TEST][PASSED] %d", val);
else $display("[TEST][FAILED] Got %d, expected %d", val, exp);
end
endtask
task assert_empty;
input [31:0] a;
begin
if (a === 32'bz) $display("[TEST][PASSED] (Bus empty)", a);
else $display("[TEST][FAILED] (Value on bus)", a, 32'bz);
end
endtask
endmodule
感谢所有帮助。谢谢!
凯文在评论中给出的答案,我将详细说明它是如何修复的。
我将 mem.sv 中的 always @(enable) 更改为 always @(*),在更改后,其余代码立即开始工作并具有完整功能。非常感谢 Kevin1494!