此博客为个人博客,不涉及商业用途,仅提供学习参考,内容均来自个人原创以及互联网转载和摘录。
此博客上带有原创标识的文章、图片、文件等,未经本人允许,不得用于商业用途以及传统媒体。
本文首发于CSDN,版权所有,禁止转载。
如需转载,请在评论区留言或私信申请,经同意后可转载,否则属于侵权行为。
————————————————
2021.3.31更新:
在xilinx的论坛上发布了问题,有好心人给出了答案,和之前推断的基本一致。链接。
引用其回答如下:
To run the synthesis, do not set testbench module as the top module since testbench module has no ports and initial blocks are non synthesizable.
Rearrange your logic in 2 modules, 1 with Testbench & other with synthesizable logics. For synthesis, set Synthesizable module as top module & run the synthesis.
如果嫌麻烦,可以直接把testbench从project里删去,也能直接出RTL电路。
————————————————
写了一个异步fifo的工程,在Vivado上利用testbench仿真通过以后,想要查看RTL电路,结果出现了以下错误:
[Synth 8-462] no clock signal specified in event control [“J:/Verilog_Develop/asyn_fifo/fifo_tb.v”:61]
fifo_tb.v的代码如下:
`timescale 1ns / 1ps
module fifo_tb();
parameter DATASIZE = 8;
reg [DATASIZE-1:0] wdata;
reg w_req, wclk, wrst_n;
reg r_req, rclk, rrst_n;
wire [DATASIZE-1:0] rdata;
wire wfull;
wire rempty;
fifo fifo0 (
.rdata(rdata),
.wfull(wfull),
.rempty(rempty),
.wdata (wdata),
.w_req (w_req),
.wclk (wclk),
.wrst_n(wrst_n),
.r_req(r_req),
.rclk(rclk),
.rrst_n(rrst_n)
);
//时钟周期,单位为ns,可在此修改时钟周期。
localparam CYCLE = 20;
localparam CYCLE1 = 40;
//生成本地时钟50M
initial begin
wclk = 0;
forever begin
#(CYCLE/2)
wclk=~wclk;
end
end
initial begin
rclk = 0;
forever begin
#(CYCLE1/2)
rclk=~rclk;
end
end
//产生复位信号
initial begin
wrst_n = 1;
#2 wrst_n = 0;
#(CYCLE*3) wrst_n = 1;
#1000 $stop;
end
initial begin
rrst_n = 1;
#2 rrst_n = 0;
#(CYCLE*3) rrst_n = 1;
end
always @(posedge wclk or negedge wrst_n)begin
if(wrst_n==1'b0)begin
w_req <= 0;
end
else begin
w_req <= $random;
end
end
always @(posedge rclk or negedge rrst_n)begin
if(rrst_n==1'b0)begin
r_req <= 0;
end
else begin
r_req <= $random;
end
end
always@(*)begin
if(w_req == 1)
wdata = $random ;
else
wdata = 0;
end
endmodule
61行:
always @(posedge wclk or negedge wrst_n)begin
这里对wclk和wrst_n两个时钟进行了使用。Vivado不允许testbench里生成的时钟又在testbench中用来生成其他模块里需要使用的信号。因为这是不可综合的。
所以,这里将w_req、r_req和wdata的生成都放到了顶层模块中。但顶层模块必须是可综合的,不允许使用$random。所以,为了保证随机性,这里重新定义了w_req_val和r_req_val变量来传递信号给顶层模块。同时,在顶层模块中利用temp变量主动递增以产生wdata。
修改后的代码:
fifo_tb.v:
`timescale 1ns / 1ps
module fifo_tb();
parameter DATASIZE = 8;
reg [DATASIZE-1:0] wdata_val = 0;
reg w_req_val, wclk, wrst_n;
reg r_req_val, rclk, rrst_n;
wire [DATASIZE-1:0] rdata;
wire wfull;
wire rempty;
fifo fifo0 (
.rdata(rdata),
.wfull(wfull),
.rempty(rempty),
.wdata_val (wdata_val),
.w_req_val (w_req_val),
.wclk (wclk),
.wrst_n(wrst_n),
.r_req_val(r_req_val),
.rclk(rclk),
.rrst_n(rrst_n)
);
//clock cycle
localparam CYCLE = 20;
localparam CYCLE1 = 40;
//生成本地时钟50M
initial begin
wclk = 0;
forever begin
#(CYCLE/2) begin
wclk=~wclk;
w_req_val <= $random;
end
end
end
initial begin
rclk = 0;
forever begin
#(CYCLE1/2) begin
rclk=~rclk;
r_req_val <= $random;
end
end
end
//产生复位信号
initial begin
wrst_n = 1;
#2 wrst_n = 0;
#(CYCLE*3) wrst_n = 1;
#2000 $stop;
end
initial begin
rrst_n = 1;
#2 rrst_n = 0;
#(CYCLE*3) rrst_n = 1;
end
always@(*)begin
wdata_val = wdata_val + 1;;
end
endmodule
fifo.v:
module fifo
#(
parameter DATASIZE = 8,
parameter ADDRSIZE = 4
)
(
output [DATASIZE-1:0] rdata,
output wfull,
output rempty,
input w_req_val, wclk, wrst_n,
input r_req_val, rclk, rrst_n
);
wire [ADDRSIZE-1:0] waddr, raddr;
wire [ADDRSIZE:0] wptr, rptr, wq2_rptr, rq2_wptr;
reg w_req, r_req;
reg [DATASIZE-1:0] wdata;
reg [DATASIZE-1:0] temp = 0;
// synchronize the read pointer into the write-clock domain
sync_r2w sync_r2w0
(
.wq2_rptr (wq2_rptr),
.rptr (rptr ),
.wclk (wclk ),
.wrst_n (wrst_n )
);
// synchronize the write pointer into the read-clock domain
sync_w2r sync_w2r0
(
.rq2_wptr(rq2_wptr),
.wptr(wptr),
.rclk(rclk),
.rrst_n(rrst_n)
);
//this is the FIFO memory buffer that is accessed by both the write and read clock domains.
//This buffer is most likely an instantiated, synchronous dual-port RAM.
//Other memory styles can be adapted to function as the FIFO buffer.
fifomem
#(DATASIZE, ADDRSIZE)
fifomem0
(
.rdata(rdata),
.wdata(wdata),
.waddr(waddr),
.raddr(raddr),
.wclken(w_req),
.wfull(wfull),
.wclk(wclk)
);
//this module is completely synchronous to the read-clock domain and contains the FIFO read pointer and empty-flag logic.
rptr_empty
#(ADDRSIZE)
rptr_empty0
(
.rempty(rempty),
.raddr(raddr),
.rptr(rptr),
.rq2_wptr(rq2_wptr),
.r_req(r_req),
.rclk(rclk),
.rrst_n(rrst_n)
);
//this module is completely synchronous to the write-clock domain and contains the FIFO write pointer and full-flag logic
wptr_full
#(ADDRSIZE)
wptr_full0
(
.wfull(wfull),
.waddr(waddr),
.wptr(wptr),
.wq2_rptr(wq2_rptr),
.w_req(w_req),
.wclk(wclk),
.wrst_n(wrst_n)
);
always @(posedge wclk or negedge wrst_n)begin
if(wrst_n==1'b0)begin
w_req <= 0;
end
else begin
w_req <= w_req_val;
end
end
always @(posedge rclk or negedge rrst_n)begin
if(rrst_n==1'b0)begin
r_req <= 0;
end
else begin
r_req <= r_req_val;
end
end
always @(*)begin
if(w_req == 1)
wdata = temp;
else
wdata = 0;
end
always @(posedge w_req) begin
temp = temp + 1;
end
endmodule
最后生成的RTL电路为:
————————————————
感谢您的阅读,如果您有收获,请给我一个三连吧!
如果您觉得这还不够,可以点击 打赏 按钮,告诉我: 你币有了!