输出端口上的 XXX
XXX on output ports
我写了一个异步 fifo 缓冲区,但是当我 运行 它时,我在输出端口上得到 XXX。我提到了有关 SO 的相关问题,其中说断言复位信号应该可以正常工作,但尽管这样做了,我仍然面临同样的问题。
如有任何帮助,我们将不胜感激。
谢谢
module fifo
#(parameter width =8,
addr_width = 4,
depth = (1 << addr_width)
)
( // Read port
output [width - 1:0] dout,
output reg empty_out,
input wire rd_en,
input wire rclk,
//write port
input wire [width-1:0] din,
output reg full,
input wire wr_en,
input wire wclk,
input wire rst
);
(* ram_style = "bram" *)
reg [width-1:0] memory_s[depth-1:0];
reg [31:0] push_ptr;
reg [31:0] pop_ptr;
assign dout = memory_s[pop_ptr]; // assign cannot assign values to registers
always @(posedge wclk)
begin
if (rst == 1)
push_ptr <= 0;
else if(wr_en == 1)
begin
memory_s\[push_ptr\] <= din;
//$display("w: %d", push_ptr);
if (push_ptr == (depth -1))
push_ptr <= 0;
else
push_ptr <= push_ptr + 1;
end
end
always @ (posedge rclk)
if (rst == 1)
pop_ptr <= 0;
else if (rd_en ==1)
begin
//dout <= memory_s\[pop_ptr\];
//$display("r: %d", pop_ptr);
if (pop_ptr == depth-1)
pop_ptr <=0;
else
pop_ptr <= pop_ptr+1;
end
reg full_s;
reg overflow;
always @*
begin
if (rst == 1)
full_s <= 0;
else if (push_ptr <= pop_ptr)
if (push_ptr + 1 == pop_ptr)
begin
full_s <= 1;
$display("push,pop,full: %d %d %d", push_ptr,pop_ptr,full_s);
end
else
full_s <=0;
else
if(push_ptr + 1 == pop_ptr + depth)
begin
full_s <= 1;
$display("push,pop,full: %d %d %d", push_ptr,pop_ptr,full_s);
end
else
full_s <= 0;
end
endmodule]
这是一个波形:
(external link)
添加了测试平台
模块 fifoTb;
// Inputs
reg rd_en;
reg rclk;
reg [7:0] din;
reg wr_en;
reg wclk;
reg rst;
// Outputs
wire[7:0] dout;
wire empty_out;
wire full;
// Instantiate the Unit Under Test (UUT)
fifo uut (
.dout(dout),
.empty_out(empty_out),
.rd_en(rd_en),
.rclk(rclk),
.din(din),
.full(full),
.wr_en(wr_en),
.wclk(wclk),
.rst(rst)
);
initial begin
// Initialize Inputs
rd_en = 0;
rclk = 0;
wr_en = 0;
wclk = 0;
rst = 1;
din = 8'h0;
// Wait 100 ns for global reset to finish
#100;
rst = 0;
wr_en = 1;
din = 8'h1;
#101 din = 8'h2;
rd_en = 1;
// Add stimulus here
end
always begin #10 wclk = ~wclk; end
always begin #10 rclk = ~rclk; end
endmodule
我建议在您的输出 dout
信号上添加额外的逻辑
避免具有 'bxxx
值,因为 memory_s
具有初始值
的 'bxxx
:
assign dout = (rd_en) ? memory_s[pop_ptr] : 0;
创建测试台的其他技巧:
首先,尝试了解您的
设备工作。
阅读您的 RTL 代码后,我得出的结论是您的 fifo 在
以下方式:
写操作
always @(posedge wclk)
begin
if (rst == 1)
push_ptr <= 0;
else if(wr_en == 1)
begin
memory_s[push_ptr] <= din;
if (push_ptr == (depth -1))
push_ptr <= 0;
else
push_ptr <= push_ptr + 1;
end
end
当wr_en
为高电平时,进行两次运算
- 来自
din
的值将写在memory_s
上
push_ptr
在 wclk
的下一个上升沿。
如果push_ptr
等于(depth -1)
,0
将被写入
寄存器 push_ptr
否则寄存器 push_ptr
递增 1
相反。
当wr_en
为低电平时不执行写操作
读取操作
assign dout = memory_s[pop_ptr];
always @ (posedge rclk)
if (rst == 1)
pop_ptr <= 0;
else if (rd_en ==1)
begin
if (pop_ptr == depth-1)
pop_ptr <=0;
else
pop_ptr <= pop_ptr+1;
end
当 rd_en
为高电平时,将寄存器 pop_ptr
递增 1
如果
pop_ptr
不等于 depth-1
否则用 0
代替。
dout
会一直保持寄存器指向的 memory_s
的值
pop_ptr
.
为您要执行的每个操作创建任务
通常很方便。
wr_en = 1;
din = 8'h1;
#101 din = 8'h2;
rd_en = 1;
我为您创建了写入和读取任务作为示例,您可能需要
替换上面的代码。
task write(input [7:0] pdin);
$display("[ testbench ] writing data: %0x", pdin);
din <= pdin;
wr_en <= 1;
@(posedge wclk);
din <= 0;
wr_en <= 0;
endtask
task read(output [7:0] prdata);
rd_en <= 1;
@(posedge rclk);
prdata = dout;
rd_en <= 0;
$display("[ testbench ] reading data: %0x", prdata);
endtask
以下是任务的使用方法:
write(8'hAA);
read(read_data);
write(8'hCC);
read(read_data);
write(8'hBC);
read(read_data);
在写组合电路时,不建议加上
对其进行重置逻辑。
always @*
begin
if (rst == 1)
full_s <= 0; . . .
此外,大多数 EDA 工具供应商建议使用分块 (=
) 分配
在编写组合电路和非阻塞赋值 (<=
) 时
时序电路。
通过调用 $finish
结束模拟。
initial begin
#1000; $finish;
end
我写了一个异步 fifo 缓冲区,但是当我 运行 它时,我在输出端口上得到 XXX。我提到了有关 SO 的相关问题,其中说断言复位信号应该可以正常工作,但尽管这样做了,我仍然面临同样的问题。
如有任何帮助,我们将不胜感激。 谢谢
module fifo
#(parameter width =8,
addr_width = 4,
depth = (1 << addr_width)
)
( // Read port
output [width - 1:0] dout,
output reg empty_out,
input wire rd_en,
input wire rclk,
//write port
input wire [width-1:0] din,
output reg full,
input wire wr_en,
input wire wclk,
input wire rst
);
(* ram_style = "bram" *)
reg [width-1:0] memory_s[depth-1:0];
reg [31:0] push_ptr;
reg [31:0] pop_ptr;
assign dout = memory_s[pop_ptr]; // assign cannot assign values to registers
always @(posedge wclk)
begin
if (rst == 1)
push_ptr <= 0;
else if(wr_en == 1)
begin
memory_s\[push_ptr\] <= din;
//$display("w: %d", push_ptr);
if (push_ptr == (depth -1))
push_ptr <= 0;
else
push_ptr <= push_ptr + 1;
end
end
always @ (posedge rclk)
if (rst == 1)
pop_ptr <= 0;
else if (rd_en ==1)
begin
//dout <= memory_s\[pop_ptr\];
//$display("r: %d", pop_ptr);
if (pop_ptr == depth-1)
pop_ptr <=0;
else
pop_ptr <= pop_ptr+1;
end
reg full_s;
reg overflow;
always @*
begin
if (rst == 1)
full_s <= 0;
else if (push_ptr <= pop_ptr)
if (push_ptr + 1 == pop_ptr)
begin
full_s <= 1;
$display("push,pop,full: %d %d %d", push_ptr,pop_ptr,full_s);
end
else
full_s <=0;
else
if(push_ptr + 1 == pop_ptr + depth)
begin
full_s <= 1;
$display("push,pop,full: %d %d %d", push_ptr,pop_ptr,full_s);
end
else
full_s <= 0;
end
endmodule]
这是一个波形:
(external link)
添加了测试平台 模块 fifoTb;
// Inputs
reg rd_en;
reg rclk;
reg [7:0] din;
reg wr_en;
reg wclk;
reg rst;
// Outputs
wire[7:0] dout;
wire empty_out;
wire full;
// Instantiate the Unit Under Test (UUT)
fifo uut (
.dout(dout),
.empty_out(empty_out),
.rd_en(rd_en),
.rclk(rclk),
.din(din),
.full(full),
.wr_en(wr_en),
.wclk(wclk),
.rst(rst)
);
initial begin
// Initialize Inputs
rd_en = 0;
rclk = 0;
wr_en = 0;
wclk = 0;
rst = 1;
din = 8'h0;
// Wait 100 ns for global reset to finish
#100;
rst = 0;
wr_en = 1;
din = 8'h1;
#101 din = 8'h2;
rd_en = 1;
// Add stimulus here
end
always begin #10 wclk = ~wclk; end
always begin #10 rclk = ~rclk; end
endmodule
我建议在您的输出 dout
信号上添加额外的逻辑
避免具有 'bxxx
值,因为 memory_s
具有初始值
的 'bxxx
:
assign dout = (rd_en) ? memory_s[pop_ptr] : 0;
创建测试台的其他技巧:
首先,尝试了解您的 设备工作。
阅读您的 RTL 代码后,我得出的结论是您的 fifo 在 以下方式:
写操作
always @(posedge wclk)
begin
if (rst == 1)
push_ptr <= 0;
else if(wr_en == 1)
begin
memory_s[push_ptr] <= din;
if (push_ptr == (depth -1))
push_ptr <= 0;
else
push_ptr <= push_ptr + 1;
end
end
当wr_en
为高电平时,进行两次运算
- 来自
din
的值将写在memory_s
上push_ptr
在wclk
的下一个上升沿。 如果
push_ptr
等于(depth -1)
,0
将被写入 寄存器push_ptr
否则寄存器push_ptr
递增 1 相反。当
wr_en
为低电平时不执行写操作
读取操作
assign dout = memory_s[pop_ptr];
always @ (posedge rclk)
if (rst == 1)
pop_ptr <= 0;
else if (rd_en ==1)
begin
if (pop_ptr == depth-1)
pop_ptr <=0;
else
pop_ptr <= pop_ptr+1;
end
当 rd_en
为高电平时,将寄存器 pop_ptr
递增 1
如果
pop_ptr
不等于 depth-1
否则用 0
代替。
dout
会一直保持寄存器指向的 memory_s
的值
pop_ptr
.
为您要执行的每个操作创建任务 通常很方便。
wr_en = 1;
din = 8'h1;
#101 din = 8'h2;
rd_en = 1;
我为您创建了写入和读取任务作为示例,您可能需要 替换上面的代码。
task write(input [7:0] pdin);
$display("[ testbench ] writing data: %0x", pdin);
din <= pdin;
wr_en <= 1;
@(posedge wclk);
din <= 0;
wr_en <= 0;
endtask
task read(output [7:0] prdata);
rd_en <= 1;
@(posedge rclk);
prdata = dout;
rd_en <= 0;
$display("[ testbench ] reading data: %0x", prdata);
endtask
以下是任务的使用方法:
write(8'hAA);
read(read_data);
write(8'hCC);
read(read_data);
write(8'hBC);
read(read_data);
在写组合电路时,不建议加上 对其进行重置逻辑。
always @*
begin
if (rst == 1)
full_s <= 0; . . .
此外,大多数 EDA 工具供应商建议使用分块 (=
) 分配
在编写组合电路和非阻塞赋值 (<=
) 时
时序电路。
通过调用 $finish
结束模拟。
initial begin
#1000; $finish;
end