|
使用verilog进行时序逻辑设计时,为了保证电路的正常工作,往往会引入复位(rst_n)信号。虽然Steve kilts在《advanced FPGA design》的2.4节中详细讨论和分析了复位信号对整个设计的面积和时序所带来的影响。但是作为一个菜鸟级programer or coding farmer对于那些东西还是没有吃透的。为了保证功能小编儿还是在每一个always块语句的开头都加了那么一句:if (!rst_n) out_d<=8’d0;在一次实践中小编在某个底层文件upi_sch_curr_blk引入了下面的一段代码:
always @ (posedge clk or negedge rst_n) begin
if (!rst_n)
curr_blk <= upi_start_blk ;
else if (!upi_conf_ready)
curr_blk <= upi_start_blk ;
else if (valid)
curr_blk <= upi_next_blk ;
else
curr_blk <= curr_blk ;
end
经过quartus跑完之后发现有报warning,具体如下:“ Warning (13004): Presettable and clearable registers converted to equivalent circuits with latches. Registers power-up to an undefined state, and DEVCLRn places the registers in an undefined state.”
令人头疼的是将该warning展开后,其下面还有一大堆子条目,类似如下:“ Warning (13310): Register "upi_sch_curr_blk:mch_curr_blk_80[0].mch_curr_blk_inst|curr_blk[0]" is converted into an equivalent circuit using register "upi_sch_curr_blk: mch_curr_blk_80[0]. mch_curr_blk_inst|curr_blk[0]~_emulated" and latch "upi_sch_curr_blk: mch_curr_blk_80[0]. mch_curr_blk_inst|curr_blk[0]~1"”
更为糟糕的是,在小编的顶层文件中,对该模块调用了80次。引用代码如下:
genvar i ;
generate
for (i=0; i<80; i=i+1) begin:mch_curr_blk_80
upi_sch_curr_blk # (8)
mch_curr_blk_inst (
.clk ( clk_125m ),
.rst_n ( rst_n ),
.upi_start_blk ( upi_stat_blk[8*i+:8] ),
.upi_next_blk ( upi_next_blk_ram_rdd ),
.valid ( ch80_valids[i] ),
.upi_conf_ready ( upi_conf_ready[i] ),
.curr_blk ( mux80_in_curr_blks[8*i+:8] )
);
end
endgenerate
可想而知,当时的告警信息是多么的密集和令人眼花缭乱。更为糟糕的是,告警显示设计中引入了大量的latch,而这使得时序变的非常的糟糕,在默认1000MHz的约束下,整个时序只能跑到160M.哈哈哈,好在有一大堆的前人遇到过这种情况。小编儿在一个altera的外文论坛上发现了一个类似的例子。在热心网友的回复中,有这样一段话:“I'm having the same problem, it seems Quartus won't start (reset) a register with a value coming from a certain bus or wire with preset or clear. Did you solve this? ”虽然笔者没大明白什么意思,但是笔者似乎也明白了点什么。于是对最底层的设计进行了如下修改。
always @ (posedge clk or negedge rst_n) begin
if (!rst_n)
curr_blk <= {(BLK_NUM_WITH){1'd0}} ;
else if (!upi_conf_ready)
curr_blk <= upi_start_blk ;
else if (valid)
curr_blk <= upi_next_blk ;
else
curr_blk <= curr_blk ;
end
再进行综合时,笔者发现告警没有了。哈哈,又学到了一手:电路复位时,最好将寄存器清零或者赋值某个特定的值,最好不要在复位状态下将某一组总线赋值给寄存器。
笔者猜测,可能是因为设计中的复位时异步复位,在异步复位状态下对寄存器赋值时可能会被综合其误认为是异步设计,从而又引入锁存器。