此博客为个人博客,不涉及商业用途,仅提供学习参考,内容均来自个人原创以及互联网转载和摘录。
此博客上带有原创标识的文章、图片、文件等,未经本人允许,不得用于商业用途以及传统媒体。
本文首发于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;//生成本地时钟50Minitial beginwclk = 0;forever begin#(CYCLE/2)wclk=~wclk; endendinitial beginrclk = 0;forever begin#(CYCLE1/2)rclk=~rclk;endend//产生复位信号initial beginwrst_n = 1;#2 wrst_n = 0;#(CYCLE*3) wrst_n = 1;#1000 $stop;endinitial beginrrst_n = 1;#2 rrst_n = 0;#(CYCLE*3) rrst_n = 1;endalways @(posedge wclk or negedge wrst_n)beginif(wrst_n==1'b0)beginw_req <= 0;endelse beginw_req <= $random;endendalways @(posedge rclk or negedge rrst_n)beginif(rrst_n==1'b0)begin r_req <= 0;endelse begin r_req <= $random;endendalways@(*)beginif(w_req == 1)wdata = $random ;elsewdata = 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 cyclelocalparam CYCLE = 20;localparam CYCLE1 = 40;//生成本地时钟50Minitial beginwclk = 0;forever begin#(CYCLE/2) beginwclk=~wclk;w_req_val <= $random;endendendinitial beginrclk = 0;forever begin#(CYCLE1/2) beginrclk=~rclk;r_req_val <= $random;endendend//产生复位信号initial beginwrst_n = 1;#2 wrst_n = 0;#(CYCLE*3) wrst_n = 1;#2000 $stop;endinitial beginrrst_n = 1;#2 rrst_n = 0;#(CYCLE*3) rrst_n = 1;endalways@(*)beginwdata_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 domainsync_r2w sync_r2w0(.wq2_rptr (wq2_rptr),.rptr (rptr ), .wclk (wclk ), .wrst_n (wrst_n ) );// synchronize the write pointer into the read-clock domainsync_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 logicwptr_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)beginif(wrst_n==1'b0)beginw_req <= 0;endelse beginw_req <= w_req_val;endendalways @(posedge rclk or negedge rrst_n)beginif(rrst_n==1'b0)begin r_req <= 0;endelse begin r_req <= r_req_val;endendalways @(*)beginif(w_req == 1)wdata = temp;elsewdata = 0;endalways @(posedge w_req) begintemp = temp + 1;end
endmodule
最后生成的RTL电路为:
————————————————
感谢您的阅读,如果您有收获,请给我一个三连吧!
如果您觉得这还不够,可以点击 打赏 按钮,告诉我: 你币有了!