verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx

上传人:b****1 文档编号:3140043 上传时间:2023-05-01 格式:DOCX 页数:14 大小:20.38KB
下载 相关 举报
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第1页
第1页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第2页
第2页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第3页
第3页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第4页
第4页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第5页
第5页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第6页
第6页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第7页
第7页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第8页
第8页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第9页
第9页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第10页
第10页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第11页
第11页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第12页
第12页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第13页
第13页 / 共14页
verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx_第14页
第14页 / 共14页
亲,该文档总共14页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx

《verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx》由会员分享,可在线阅读,更多相关《verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx(14页珍藏版)》请在冰点文库上搜索。

verilog基本电路设计包括时钟域同步无缝切换异步fifo去抖滤波Word下载.docx

always@(posedgeclkbornegedgerst_n)begin

if(!

rst_n)begin

levl_b_d1

levl_b_d2

levl_b_d3

end

elsebegin

endendassignpuls_b_pos=levl_b_d2&

(~levl_b_d3);

assignpuls_b_neg=levl_b_d3&

(~levl_b_d2);

assignlevl_b_out=levl_b_d2;

上面三个输出分别是经过同步之后,clkb下可以使用的0变1脉冲信号,1变0脉冲信号以及电平信号。

再次强调:

levl_a_in必须是clka的DFF信号!

下面是更常见的,clka下的脉冲信号,同步到clkb时钟域下,它对于clka与clkb的时钟频率关系没有任何限制,快到慢,慢到快都没问题。

其主要原理就是先把脉冲信号在clka下展宽,变成电平信号,再向clkb传递,当确认clkb已经“看见”信号同步过去之后,再清掉clka下的电平信号。

脉冲信号同步处理电路,有两个地方使用了上面的电平信号同步处理原则,请仔细揣摩原因。

详细见下面的RTL,其中省略了信号定义声明:

modulesync_pulse(

//input

rst_n,//systemreset

clka,//clockA

clkb,//clockB

puls_a_in,//pulseinputfromclka

//output

puls_b_out,//pulseoutputinclkb

levl_b_out//leveloutputinclkb

);

parameterDLY=1;

//always@(posedgeclkaornegedgerst_n)

begin

if(rst_n==1'

b0)

signal_a

elseif(puls_a_in)

elseif(signal_b1_a2)

else;

endalways@(posedgeclkbornegedgerst_n)

signal_b

else

b0)begin

signal_b_b1

signal_b_b2

endalways@(posedgeclkaornegedgerst_n)

signal_b1_a1

signal_b1_a2

endassignpuls_b_out=signal_b_b1&

(~signal_b_b2);

assignlevl_b_out=signal_b_b1;

endmodule

下一篇讲时钟切换电路。

留下一个思考题:

clka下的同一个寄存器信号signal_a,电平宽度对clkb而言足够长,如果同时调用两个相同的电平同步模块向clkb时钟传递,分别得到levl_b1和levl_b2,那么在clkb时钟域下看到的lev_b1和levl_b2信号是否一样?

这个问题是实际设计中一不小心就会犯错的,如果能够想明白正确回答这个问题,异步信号的理解就可以过关了。

Verilog基本电路设计之二:

时钟无缝切换(帖子链接:

写法很简单assignclk_o=sel_clkb?

clkb:

clka,当sel_clkb为1时选择clkb,否则选择clka。

不过在实际设计中,建议直接调用库里的MUX单元set_dont_touch,不要采用这里的assign写法,因为这种写法最后综合得到的可能不是MUX而是复杂组合逻辑,给前后端流程的时钟约束和分析带来不便。

无缝切换,就是切换时无毛刺时钟平稳过渡。

在时钟切换中,只要出现比clka或者clkb频率更高的窄脉冲,不论是窄的高电平还是窄的低电平,都叫时钟毛刺。

工作在切换后时钟clk_o下的电路模块,综合约束是在max{clka,clkb}频率下的,也就是说设计最后signoff的时候,只保证电路可以稳定工作的最高频率是max{clka,clkb},如果切换中出现更高频的时钟毛刺,电路可能出现无法预知的结果而出错。

无缝切换,一般用在处于工作状态的模块需要调频或者切换时钟源,比如内部系统总线,CPU等。

你刚用手机打完游戏后马上关屏听音乐,这两种场景中,CPU在满足性能前提下为了控制功耗,其工作频率会动态地从很高调至较低,此时就可能是在CPU一直处于工作状态下,通过无缝切换时钟源头实现的。

在无缝切换电路中,切换信号sel_clkb可以是任意时钟域下的信号,包括但不限于clka或者clkb域,但是sel_clkb必须是一个DFF输出信号;

clka与clkb的频率大小相位关系可以任意。

无缝切换需要解决两个问题,一是异步切换信号的跨时钟域同步问题,这里需要使用《Verilog基本电路设计之一》里的同步电路原理消除亚稳态;

二是同步好了的切换信号与时钟信号如何做逻辑,才能实现无毛刺。

下面写出无缝切换电路的主体部分,忽略了内部信号的定义声明等。

moduleclk_switch(

rst_n,

clka,

clkb,

sel_clkb,

clk_o

always@(posedgeclkaornegedgerst_n)

sel_clka_d0

sel_clka_d1

end//part2

//always@(posedgeclka_nornegedgerst_n)

sel_clka_dly1

sel_clka_dly2

sel_clka_dly3

end//part3

//always@(posedgeclkb_nornegedgerst_n)

always@(posedgeclkbornegedgerst_n)

sel_clkb_d0

sel_clkb_d1

end//part4

sel_clkb_dly1

sel_clkb_dly2

sel_clkb_dly3

end//part5

clk_gate_xxxclk_gate_a(.CP(clka),.EN(sel_clka_dly3),.Q(clka_g).TE(1'

b0));

clk_gate_xxxclk_gate_b(.CP(clkb),.EN(sel_clkb_dly3),.Q(clkb_g).TE(1'

//assignclka_g=clka&

sel_clka_dly3;

//assignclkb_g=clkb&

sel_clkb_dly3;

assignclk_o=clka_g|clkb_g;

上面是我认为比较合理的无缝切换电路,其他切换方式跟这个会有些许出入,但基本大同小异原理是一样的。

有几点说明:

1、抛开注释掉的电路不看,由于part5部分直接调用库里的clockgatingcell,使得整个切换电路全部只需要用到时钟上升沿,无需额外定义反向时钟,精简了DC综合的时钟约束;

直接调用gatingcell的另一个好处是,前后端工具会自动检查gatingcell的CP信号与EN信号的setup/hold时间,使得gating后的Q时钟输出无毛刺尖峰。

TE端可以根据实际需要接上scan测试模式信号。

如果使用part5部分的gatingcell实现,前面的part1,2,3,4全部替换成注释掉的反相时钟也是没有问题。

2、part2和part4部分,具体需要多少级DFF,甚至完全不要也是可以的,这就回到了《Verilog基本电路设计之一》里讨论的到底多少级DFF消除亚稳态才算合理的问题。

时钟频率很低可能无所谓,如果时钟频率达到GHz,这部分建议至少保留三级DFF,因为三级DFF延时也仅仅只有3ns的时间裕度。

没必要为了省这么几个DFF降低电路可靠性,在复杂IP以及大型SOC系统中,你会发现多几十个DFF,面积上可以忽略,系统可靠性和稳定性才是首要的。

3、如果part5部分希望使用注释掉的两行“与”逻辑实现时钟gating,此时part1与part3使用正相或者反相时钟都可以,但是必须把part2和part4部分改为注释掉的反相时钟实现,目的是初步从RTL设计上避免“与”逻辑的毛刺,同时还需要后端配合,因为很多后端工具对时钟“与”逻辑的clockgatingcheck未必会检查。

用clk下降沿拍出的en信号,再跟clk做与逻辑得到的门控时钟,在RTL仿真阶段看到的一定不会有毛刺,但是布线完成后,如果clk相对en后移,那与逻辑得到的门控时钟就有毛刺了。

这就是用与逻辑做门控的缺点,由于后端工具可能不会去检查这个与门的时序关系而导致出错。

但直接调用库里的gatingcell,工具天然就会去检查这个时序,免去人工确认的后顾之忧。

最后,请大家仔细看看sel_clka_d0(~sel_clkb_dly3)和sel_clkb_d0

Verilog基本电路设计之三:

异步FIFO(帖子链接:

asyn_fifo(

af_wclk,//async-FIFOclearinwriteclock

af_rclk,//async-FIFOclearinreadclock

af_wr_en,//async-FIFOwriteenable

af_rd_en,//async-FIFOreadenable

af_dati,//async-FIFOdatain

//output

af_full,//Async-FIFOfullflag

af_empty,//Async-FIFOemptyflag

af_dato//Async-FIFOdataout

//-------------------------datainput--------------------------

assignnxt_wptr_wclk=(af_wr_en&

&

!

af_full)?

(wptr_wclk+1'

b1):

wptr_wclk;

assignnxt_wptr_gray=(nxt_wptr_wclk>

>

1)^nxt_wptr_wclk;

always@(posedgeaf_wclkornegedgerst_n)

wptr_wclk

wptr_gray

endreg[31:

0]ram[15:

0];

//

always@(posedgeaf_wclk)

if(af_wr_en==1'

b1)

ram[wptr_wclk[3:

0]]

end//------------------------dataoutput---------------------------

assignnxt_rptr_rclk=(af_rd_en&

af_empty)?

(rptr_rclk+1'

rptr_rclk;

assignnxt_rptr_gray=(nxt_rptr_rclk>

1)^nxt_rptr_rclk;

always@(posedgeaf_rclkornegedgerst_n)

rptr_rclk

rptr_gray

endassignaf_dato=ram[rptr_rclk[3:

0]];

//syncreadpointer

rptr_sp1

rptr_sp2

end//syncwritepointer

wptr_sp1

wptr_sp2

endassignaf_full=(wptr_gray=={~rptr_sp2[4],~rptr_sp2[3],rptr_sp2[2:

0]});

assignaf_empty=(rptr_gray==wptr_sp2);

assignwptr_bin[4]=wptr_sp2[4];

assignwptr_bin[3]=(^wptr_sp2[4:

3]);

assignwptr_bin[2]=(^wptr_sp2[4:

2]);

assignwptr_bin[1]=(^wptr_sp2[4:

1]);

assignwptr_bin[0]=(^wptr_sp2[4:

0]);

assignrptr_bin[4]=rptr_sp2[4];

assignrptr_bin[3]=(^rptr_sp2[4:

assignrptr_bin[2]=(^rptr_sp2[4:

assignrptr_bin[1]=(^rptr_sp2[4:

assignrptr_bin[0]=(^rptr_sp2[4:

assignaf_wlevel=wptr_wclk-rptr_bin;

assignaf_rlevel=wptr_bin-rptr_rclk;

assignaf_half_full=(af_rlevel>

=5'

h7);

上面给出的是深度16,宽度32的示例,大家可以使用parameter参数化定义深度和宽度,方便不同需求下的调用。

除了空满信号标志,也可以根据需要做出半空半满之类信号。

上面需要注意的一点就是,格雷码必须在本时钟域下DFF输出,再往另一个时钟域同步。

同步FIFO呢,就不用有格雷码转换,设计更加简单,就不专门开贴描述了。

Verilog基本电路设计之四:

去抖滤波(帖子链接:

parameterBIT_NUM=4;

reg[BIT_NUM-1:

0]signal_deb;

always@(posedgeclkornegedgerst_n)

b0)

signal_deb

else

endalways@(posedgeclkornegedgerst_n)

signal_o

elseif(signal_deb[3:

1]==3'

b111)

b000)

end

上面的电路,第一个always,还兼顾了去亚稳态作用。

它可以滤掉的宽度是两个clk的cycle,对于大于两个cycle而小于三个cycle的信号,有些可以滤掉,有些不能滤掉,这与signal_i相对clk的相位有关。

根据希望滤除的宽度相关,换算到clk下是多少个cycle数,从而决定使用多少级DFF。

如果希望滤除的宽度相对cycle数而言较大,可以先在clk下做一个计数器,产生固定间隔的脉冲,再在脉冲信号有效时使用多级DFF去抓signal_i;

或者直接将clk分频后再使用。

结束

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2