verilog-hdl的故事之反应和调试过程_第1页
verilog-hdl的故事之反应和调试过程_第2页
verilog-hdl的故事之反应和调试过程_第3页
verilog-hdl的故事之反应和调试过程_第4页
verilog-hdl的故事之反应和调试过程_第5页
已阅读5页,还剩37页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第七章反应和调试过 输出的珍贵信 实验二十六:优化VGA的同步模 迟了一步的数 实验二十七:VGA模块仿 即时结果和非即时结 实验二十八:即时结果的需 波形图在我的脑海 总 输出中珍贵的信在这一章中,我们主要讨论的东西恰好是和前一章180度不同。一章中笔者说了,刺激在激励过程中怎样又怎样。反之这一章,笔者要说的东西是反应在激励过程中,怎样又怎样。“反应”在“激励”中是“输出”的意思,故“输出”不只是在仿真软件上看到的波形图而已,然而“输出”在仿真中也代表“模块的反应”。我们把“模块的反应”摊开先不说,毕竟面的实验,笔者有形或无形的提及过。还是先把焦点围绕着“波形图的身上。因为只要把波形图看懂了,自然而然读者什么都会明白。满许多有用的信息,可是要把这些信息看懂或者和VerilogHDL语言扯上关系(明白VerilogHDL语言对输出的影响说实话真这是一件苦差事而且过程比起建模更。在现实中就像普通人看病例书一样,完全都看不懂,但是医生却看得动,模块是,看看模块“哪里不舒服”和“吃错什么了”等。在这里,笔者就以《VerilogHDL那些事儿-建模篇》中实验九之一的vga模块里的sync_module.v作为实例。选择它的原因很简单,因为sync_module.v用不着编辑复杂的事情就是从仿真中调试sync_module.v,使得它更优化。(老实说,笔者这样作就像址,y地址和显示有效信号(Ready_Sigsync_module.v是负责着“显示标准”的工作。在这里我们以800x600x60Hz为例。800x600xabcde段-总共n个列HSYNC列像800x600xopqrs段-总共n个行VSYNC行像41上表是以800x600x60Hz显示标准的时序分段(具体的解释请参考建模篇。我们知道在VGA800x600x60Hz为显示25ns40Mhz为驱动频率。在仿真的时候我们不可能以一个时钟一个时钟去计以笔者将它们转换us。800x600x60Hz为显示标准:一个列像素=显示主频的周期=1/40Mhz=25ns=10561056*25800x600xabcde段-总共n个列HSYNC列像800x600xopqrs段-总共n个行VSYNC行像CLK,Column_Addr_Sig,Row_Addr_SiginputCLK;inputoutputVSYNC_Sig;outputHSYNC_Sig;outputReady_Sig;output[10:0]Row_Addr_Sig;regalways@(posedgeCLKornegedgeRSTn)if(!RSTn)Count_H<=elseif(Count_H==11'd1056Count_H<=Count_H<=Count_H+1'b1; regalways@(posedgeCLKornegedgeRSTnif(!RSTnCount_V<=elseif(Count_V==11'd628Count_V<=elseif(Count_H==11'd1056Count_V<=Count_V+1'b1; regalways@(posedgeCLKornegedgeRSTnif(!RSTnisReady<=elseif((Count_H>11'd216&&Count_H<11'd1017)(Count_V>11'd27&&Count_V<11'd627)isReady<= assignVSYNC_Sig=(Count_V<=11'd4)?1'b0:assignHSYNC_Sig=(Count_H<=11'd128)?1'b0: assignColumn_Addr_Sig=isReady?Count_H-11'd217:11'd0;//CountfromassignRow_Addr_Sig=isReady?Count_V-11'd28:11'd0;//Countfrom0 67.sync_module.v`timescale1ps/1moduleregCLK;wireHSYNC_Sig;wireVSYNC_Sig;wireReady_Sig;wiresync_moduleRSTn=0;;RSTn=CLK=0;forever#12500CLK=36.1ps800x600x60Hz25nsns,无法取得完整的半周期时间(12.5小数必须进位或者割舍。30行,笔者设置了ps1us的复位。然而在31行,笔者设置12500ps12.5ns12500psx225000ps25ns优化过a3.2us。C2~C3b2.2us。C3~C4d段,时间20us。C4~C5e1us。1056C1~C5,时间大约是26.4us(C5C1的时间。看来HYSNC_Sig的驱动很完美,没有什么东西好修改VSYNC_Sigao4*1056*25ns(C1~C2)亦即105.6us。从波形图上,我们看到VSYNC_Sig拉高之前,有5个1056*(C1~C3)的列像素。这有点问题,理论上是4个而已呀,怎么多了一个(C2~C3)? 25n(C1~C2嗯?VSYNC_Sig的o段出现问题,既然没有对一个行像素照成影响。在这里,一定是 assign assignVSYNC_Sig=(Count_V<=11'd4)?1'b0: assignVSYNC_Sig=(Count_V<=11'd3)?1'b0:sync_module.v55Count_V11'd4Count_V3。上图是经修改sync_module.v第55行代码后再一次仿真的结果。焦点依然是VSYNC_SigoVSYNC_Sigo4*1056*25ns(C1~C2,时间大约是105.6us。嗯,这个结果符合要求了。我们继续往下调式。VSYNC_Sigpp23*1056*25nsusC2~C31056*25ns(C3~C4?哪里又发生问题了?elseif((Count_H>11'd216&&Count_H<11'd1017)(Count_V>11'd27&&Count_V<11'd627)elseif((Count_H>=11'd216&&Count_H<11'd1017)(Count_V>=11'd27&&Count_V<11'd627)47~48Count_H11'd216Count_V11'd27,,上图是经过修改第47~48行后,重新仿真的结果。该焦点依然是VSYNC_Sigp段。(C1~C2_SigpVSYNC_SigpqColumn_Addr_Sig0开始计数,反之Row_Addr_Sig02047生在63行。 assign assignRow_Addr_Sig=isReady?Count_V-11'd28: assignRow_Addr_Sig=isReady?Count_V-11'd27:Count_V11'd28Count_V11'd2763行以后,VSYNC_Sigpq段,Row_Addr_Sig0开始)VSYNC_SigqHSYNC_SigC段,每一个列像xVSYNC_Sigqy地105612888(HSYNC_Siga+b段)个列像素开始,是当前y地址的0~799个列像素。但是在上面的仿真图中,Column_Addr_Sig(x地址)应该是0开始计数到799,但是它多计数1个列像素了(计数到800。然后再稍微注意一下Ready_Sig,它应该是Column_Addr_Sig计数到799之后拉低才合理吗?elseif((Count_H>=11'd216&&Count_H<11'd1017)(Count_V>=11'd27&&Count_V<11'd627)elseif((Count_H>=11'd216&&Count_H<11'd1016)(Count_V>=11'd27&&Count_V<11'd627)看来问题是发生在第47Count_H11'd1017,Count_H然后再一次启动仿上图是经过修改47行的仿真结果,当Column_Addr_Sig计数到799的时候,它停止Ready_SigVSYNC_Sigq段第一个行像素调式成功,接下来的599个行像素也是一样的结果。HYSNC_Siga~dVSYNC_Sigo~q段。剩下的只有VSYNC_Sig的r段。47C1~C2VSYNC_Sigq15840us。结果符合VSYNC_Sigqrr11056*,26.4usq800x600(Row_Addr_Sig599之后,Ready_Sig就拉低sync_module.v(CLK,Column_Addr_Sig, inputinputoutputoutputoutputoutputregalways@(posedgeCLKornegedgeRSTnif(!RSTnCount_H<=elseif(Count_H==11'd1056Count_H<=Count_H<=Count_H+1'b1; regalways@(posedgeCLKornegedgeRSTnif(!RSTnCount_V<=elseif(Count_V==11'd628Count_V<=elseif(Count_H==11'd1056Count_V<=Count_V+1'b1; regalways@(posedgeCLKornegedgeRSTnif(!RSTnisReady<=elseif((Count_H>=11'd216&&Count_H<11'd1016)//(*(Count_V>=11'd27&&Count_V<))//(*isReady<=isReady<=assignVSYNC_Sig=(Count_V<=11'd3)?1'b0: //(*assignHSYNC_Sig=(Count_H<=11'd128)?1'b0:assignReady_Sig=assignColumn_Addr_Sig=isReady?Count_H-11'd217:assignRow_Addr_Sig=isReady?Count_V-11'd27://(*.v(*),亦即,4748,55,63实验二十(波形图sync_module.v的代码修改,直到最终sync_module.v的输出达到可接受的范围。实验二十仿真中,比起验证部分,综合部分更加亲近模块的设计笔者之所以故意选sync_module.v作为仿真对象,就想表达一点“仿真最重要的不是学会编辑什么激励文很多时候VerilogHDL迟了一步的数一章节中,我们优化了sync_module.v模块。在这一章节之中,sync_module.v模块组合与《VerilogHDL那些事儿-建模篇》中实验九之一的vga模块里的vga_control_module.v,成为简单的vga模块并且执后从输(波形图)实验二十七:vga模块仿真我们稍微回忆一下《VerilogHDL那些事儿-建模篇》中实验九之一的vga模块里vga_control_module.vvga_control_module.vvga模块中,它是负责图像显示的工作。然而在《VerilogHDL那些事儿-建模篇中实验九之一里它是负责显示10(y0~y9长为799(x1~x799)不知道读者还是否记得,在《VerilogHDL那些事儿-建模篇》中实验九之一里,sync_module.v和vga_control_module.v使用了同样的时钟频率。其实这一句举动使得10x799xx1开始,x地址,使得该矩形从x2开始显示。预想结 实际结新对vga_control_module.v内容的认识。modulemodule(CLK,Red_Sig,Green_Sig,Blue_SiginputCLK;inputinput[10:0]Row_Addr_Sig;outputRed_Sig;outputoutputregalways@(posedgeCLKornegedgeRSTn)if(!RSTn)isRectangle<=elseif(Column_Addr_Sig>11'd0&&Row_Addr_Sig<11'd100isRectangle<=isRectangle<=assignRed_Sig=Ready_Sig&&isRectangle?1'b1:1'b0;assignGreen_Sig=Ready_Sig&&isRectangle?1'b1:1'b0;assignBlue_Sig=Ready_Sig&&isRectangle?1'b1:1'b0;37.在上面的内容中,第23行的if条件决定了该矩形的面积和显示位置。其中Coum_Addr_Sig11'd0x11~799,Row_Addr_Sig11'd100表示矩形从y00~99。在这里请注意,矩形的表示是以isRectangle标志寄存器来指示。无论是在“流水操和module(Red_Sig,Green_Sig,SQ_Ready,SQ_Column, inputinputinputoutputoutputoutputoutputoutputoutputoutputoutputwirewirewiresync_module(.RSTn(RSTn.VSYNC_Sig(VSYNC_Sig //output-to //output-to.Column_Addr_Sig(Column_Addr_Sig //output-to.Row_Addr_Sig(Row_Addr_Sig //output-to //output-to vga_control_module(.RSTn(RSTn//input-from.Column_Addr_Sig(//input-from.Row_Addr_Sig(Row_Addr_Sig//input-from.Red_Sig(Red_Sig//output-to.Green_Sig(Green_Sig//output-to.Blue_Sig(Blue_Sig//output-toassignSQ_Ready=assignSQ_Column=assignSQ_Row=vgavga_module.v组合模块不同的是,笔者拿掉pll_module.v,并且将3~4CLK_SyncCLK_Control的输入U1.CLK的输入信号(31行U2.CLK的输入信号(44(不知道是不是笔者人品的关系,每当笔者在做仿真的时候,凡是有ip出现的地方,仿真的工作会非常的不顺利...所以笔者在作仿真的时候都故意把ip拿掉,用其他办法来`timescale1ps/1moduleregCLK_40Mhz;regCLK_80Mhz;regRSTn;wireVSYNC_Sig;wirewirewirewirewirewirewireenv_vga_module(.SQ_Ready(SQ_Ready.SQ_Row(SQ_Row RSTn=0; ;RSTn=CLK_40Mhz= ;forever#12500CLK_40Mhz=CLK_80Mhz=1;forever#6250CLK_80Mhz=env_vga_module.v33~35行复位信号的刺激,38~4040Mhz43~4680Mhz里先无视那个CLK_80Mhz20~21行U1和U2亦即sync_module.vvga_control_module.vCLK_40Mhz4Mh4Mh:vga_control_module.v开始显示矩形的时候。SQ_Row,SQ_Column和SQ_Ready它们分别对应sync_module.v的输出Row_Addr_Sig,Column_Addr_SigReady_Sig。在(Cursor省略为)C1的未来,SQ_ReadC1这个时钟,sync_module.vSQ_RowSQ_Column也开始反馈当前的显示地址y想和x。由于vga_control_module.v和sync_module.v使用同样的时钟,在C1这个时候C2的时候,C2未来SQ_Row不变,SQ_Column已经递增为1。在这个时候vga_control_module.vSQ_Column的过去值,还是是逻辑0。它还是一样什么也没C3的时候,C3SQ_Column已经递增为2。在个时候vga_control_modul.v检测SQ_Column的过去值是1。if条件成立,它“决定”使能isRectangle寄存器。所以C3的未来Red/Green/Blue_Sig被拉高。上述的内容,如果简单归纳的话sync_module.v(U1)vga_control_module.v(U2)x0,y地址0的时候,U2U1U2x1,y0的时候,这时候的U2才反应过来,U2开始会意U1的时候,事实上它已经慢了一个时钟。最终结果,vga_control_module.vx2x1上图的仿真结果表示了,在该矩形的长度结束显示在799,因为在C2之前,亦即SQ_Column值为799之前,Red/Green/Blue_Sig的过去都是被拉高。换句话说,矩形从x2开始显示到x799结束显示,长度为798,亦即有一个长度显示失败。0~99C1之前,亦即SQ_Row在这里我们可以如此总结:矩形的高度显示没有问题,但是矩形的长度显示就有问题。它向右偏移了一个像素。上初学者们都会把sync_module.v和vga_module.v集成在一个文件里,亦即单文件主义。RTL的方式来编写模块,组合逻辑的过分出现不但会使代码的有一种更有效的办法,也是这一章节的重点,那就是 使用更的时钟频`timescale1ps/1moduleregCLK_40Mhz;regCLK_80Mhz;regRSTn;wireRed_Sig;wireBlue_Sig;wireGreen_Sig;wireSQ_Ready;wirewire.SQ_Ready(SQ_Ready.SQ_Row(SQ_RowRSTn=0;;RSTn=CLK_40Mhz= ;forever#12500CLK_40Mhz=CLK_80Mhz=1;forever#6250CLK_80Mhz=50.上面是env_vga_module.v的激励文件。其中在21行vga_control_module.vCLK_80Mhzsync_module.v4h/8h:sync_module.vC1SQ_Ready被拉高,SQ_Row和SQ_Column均反馈0,亦即当前显xy0C1~C2之间由于SQ_Column为0,所以vga_control_module无视。在C2的未来sync_module.v反馈了SQ_Column为1vga_control_module.v是由80Mhz的时钟频率驱动着。C2的未来亦即sync_module.v的vga_control_module.v在这个时候检测SQ_Column的过去值是0,它C3sync_module.vvga_control_module.v另一个新周期(上升沿。vga_control_module.vC3检测了if(开始显示矩形C2,C3C4vga_control_module.v的执行频率高于sync_module.v一倍。每当sync_module.v更新SQ_Column,vga_control_module.v在sync_module.v的后半周期就可以检测到sync_module.v更新以后的值,然后vga_control_module.v在自己当前时钟“决定”干些什么。由此一来,我们可以避免数上图的仿真结果,vga_control_module.v显示的矩形长度最长为799由于vga_control_module.v的执行频率比sync_module.v2倍。sync_module.v的输出一旦更新,vga_control_module.vsync_module.v的后vga_control_moduel.v只用sync_module.v的后半周期去更新和保留Red/Green/Blue_Sig的输出。vga_control_module.vsync_module的3/4Red/Green/Blue_SigRed/Green/Blue_Sigvga_control_module.vsync_module.v4倍的执行频率。但是这些事情不是强制性实验二十sync_module.vvga_control_module.v迟了一个时钟去。具体的原因是sync_module.v和vga_control_module.v使用了相同vga_control_module.v2sync_module.v的时钟频率以后,实验二十vga_control_module.v的时钟频率就可以解决数vga_control_module.v,而且解决问题的过程也只道sync_module.v和vga_control_module.v之间的沟通出现问题(数据延迟)了。这一个实验再一次证明,从波形图中(输出)(输出)的信息所使用的一套“思想”和建模的时候所使用的“思想”是一样的。即时结果和非即时结always”,无论它是否有没有在always区域里,它都是,“时间点”的概念,它多求得的初学者常常都会误会“<=”是always区域里的赋值运算符,其实“=”也可以使always=RTL级的设计乱了套。如果要在RTL级设计里区运用好“<=”,前提条件就是要掌握好基础。在这一个实验中笔者《VerilogHDL那些事儿-建模篇》实验十九演示中一段控制程inputinputoutput[3:0]SQ_i,output[4:0]SQ_X,output[6:0]SQ_Y,outputSQ_isCount,output parameterT1US=7'd80; regregregalways@(posedgeCLKornegedgeRSTnif(!RSTnC1<=elseif(C1==T1USC1<=elseif(isCountC1<=C1+C1<=regalways@(posedgeCLKornegedgeRSTnif(!RSTnCUS<=elseif(CUS==rTimesCUS<=elseif(C1==T1USCUS<=CUS+regregalways@(posedgeCLKornegedgeRSTnif(!RSTnY<=case(i0:Y<=2:Y<=4:Y<=6:Y<=8:Y<=10:Y<=regregregalways@(posedgeCLKornegedgeRSTnif(!RSTni<=rAddr<=X<=isCount<=rTimes<=case(i 0,2,4,6,8, if(X==16)beginrAddr<=7'd0;X<=5'd0;isWrite<=1'b0;i<=i+1'b1; elsebeginrAddr<=Y+X;X=X+1'b1;isWrite<=1'b1;end 1,3,5,7,9, if(CUS==rTimes)beginisCount<=1'b0;i<=i+1'b1; elsebeginrTimes<=10'd250;isCount<=1'b1;end i<= assignSQ_i=assignSQ_X=assignSQ_Y=assignSQ_Addr=rAddr;assignSQ_isCount=isCount;assignSQ_isWrite=110..vVerilogHDL-vga_interface_demo.v250ms,vgaRAM写入16wordsx16bits的数据。6~11行,笔者将i,X,Y,rAddr,isCount,isWrite全部引出来。该文件不再使用40Mhz80Mhzmsus171us21~47行分别1us定时器us级计数49~63行是根据不同i更新偏移量Y(注意:此时Y的赋值是使用非阻塞赋值)第69~97行是控制程序的部分,当步骤i是偶数的时候,Y更新偏移量,然后拉高isWriteY16i是奇数的时候就延迟`timescale1ps/1moduleregregwire[3:0]SQ_i;wire[4:0]SQ_X;wire[6:0]SQ_Y;wireSQ_isCount;wireSQ_isWrite;gm_control_moduleRSTn=0;;RSTn=CLK_80Mhz=1;forever#6250CLK_80Mhz=36.gm_control_module.v1ps1us80Mhz省略C)C1~C4Y值开始输16个递增的地址。C1的过去,由于是初始化的关016个递增地址的输出,SQ_Addr的输出从0~15。上图仿真结果表示了,每一次Y偏移量更新都需要延迟250us上图的仿真结果是当.v2的时候。C1~C4表示了第二次Y偏移量更新。C1的时候,.v文件检测到SQ_i的过去值是2Y偏移量,也就是说Y偏移量的更新发生在C1的未来。SQ_Addr的第一个输出应该是从16开始才对嘛?为什么会是Y(使用非阻塞赋值,C1YSQ_YC10C1的未来,SQ_Addr的输出是YX,(XSQ_XC10)rAddr00,0C2SQ_Addr取得是SQ_YC216SQ_Addr取得的XSQ_XC21C2的未来,SQ_Addr的输出是161,17SQ_Addr14个递增输都是正.v4Y偏移量更新。同样的问题也取得的YSQ_YC116(Y偏移量后的遗留结果。在同一个时间SQ_Addr也取得SQ_X在C1的过去值,亦即0。所以在C1的未来SQ_Addr的输出是rAddr<=16+0,结果是16而不是32。C2的时候,Y已经更新完毕,SQ_Addr取得的Y是SQ_Y在C2的过去值,亦即32SQ_Addr取得的XSQ_XC21C2的未来,SQ_Addr的输出是,rAddr<=32+1,结果是33。SQ_Addr其后的14个递增输出地址都是正4~6Y偏移量的更新,SQ_Addr第一个的输出地址都会不正常。可能读者SQ_Addr在读取第一个SQ_Y的值的时候都失败。要解决这个问题很简单,就是在.v文件里将Y所使用的非阻塞赋值“<=”改为阻塞inputinputoutput[3:0]SQ_i,output[4:0]SQ_X,output[6:0]SQ_Y,output output13. parameterT1US=7'd80; regregregalways@(posedgeCLKornegedgeRSTnif(!RSTnC1<=elseif(C1==T1USC1<=elseif(isCountC1<=C1+C1<=regalways@(posedgeCLKornegedgeRSTnif(!RSTnCUS<=elseif(CUS==rTimesCUS<=elseif(C1==T1USCUS<=CUS+regregalways@(posedgeCLKornegedgeRSTnif(!RSTnY<=case(i0:Y=2:Y=4:Y=6:Y=8:Y=10:Y=regregregalways@(posedgeCLKornegedgeRSTnif(!RSTni<=rAddr<=X<=isCount<=rTimes<=case(i 0,2,4,6,8, if(X==16)beginrAddr<=7'd0;X<=5'd0;isWrite<=1'b0;i<=i+1'b1; elsebeginrAddr<=Y+X;X=X+1'b1;isWrite<=1'b1;end 1,3,5,7,9, if(CUS==rTimes)beginisCount<=1'b0;i<=i+1'b1; elsebeginrTimes<=10'd250;isCount<=1'b1;end i<= assignSQ_i=i;assignSQ_X=X;assignSQ_Y=assignSQ_Addr=rAddr;assignSQ_isCount=isCount;assignSQ_isWrite=110.上面.v文件是经过修改的gm_control_module.v58~63行中都改为“。使用同样的激励文上图的仿真结果是.v文件在步骤0的时候C1~C4是SQ_Addr输出的16个地址。无论Y有没有取得“既是结不会影响SQ_Addr的输出。因为在初始化的时候,Y已经被初始化为0。上图仿真结果表示,每一次Y更新时候的延迟。时间大约是250us.vY偏移量的时候。C1~C4SQ_Addr输出的十在同一个时候,SQ_Addr取得的Y再也不是在C1,SQ_YY的“即时SQ_Addr取得的X是SQ_X的过去值,亦即0C1SQ_Addr的输出是rAddr<=16+0,结果是16。SQ_Addr在接下来15个递增输出地址都正常。.v文件第三次更新Y偏移量。C1~C4SQ_Addr输出的十六个递增地址。在C1的时候.v文件检测到SQ_i4,Y32。在同一个时候,SQ_Addr取得的YC1,SQ_YY的“即时SQ_Addr取得的X是SQ_X0C1SQ_Addr的输出是rAddr<=32+0,结果是32。SQ_Addr在接下来15个递增输出地址都正常。实验二十在实验二十八中,由于Y偏移量更新的时候是使用非阻塞赋值“<=”,即遵守“时间点”的概念。结果使得SQ_Addr的第一个输出地址带来错误(应该说是慢了一步。当更SQ_YSQ_Addr的第一个输出地址的错同样的问题也发生regalways@(posedgeCLKornegedgeRSTnif(!RSTnZ<=case(i0:Z<=2:Z<=《VerilogHDL那些事儿_control_module.v44~55

12'b100_100_000_000:Z<=时候,考虑到初学者对eriogL的不熟悉,笔者将图像的第一列和最后一列都空白处初次之外,读者可能要问:“为什么在激励文件中,不是使用其他的时钟频率,而是使用80Mhz的时钟频率?”笔者这样作,绝对有笔者的原因,具体的原因就自己去摸索吧,就当笔者卖个关子好了。实验二十真的虚拟实验的重点就VerilogHDL的基本功看是如何从波(输出波形图在我的脑海我们就以一个简单的例子来助读者回忆一些数码管接口的功能。smg_scan_module.v会每隔1ms低电平使能不同的数码管,smg_control_module.v1msNumber_Sigsmg_encode_module.v。smg_encode_module.v是加码模块,它会将Number_Data加码1ms。下面是数码管加码模块的部分代码,其中最关键的部分是第20~39行,它表示了数码管加码模块在加码数据的时候,由于该模块是用寄存器来寄存加码后的数据,所以它至少需要一个时钟的消耗。20.20.always@(posedgeCLKornegedgeRSTnif(!RSTnrSMG<=case(Number_Data4'd0:rSMG<=4'd1:rSMG<=4'd2:rSMG<=4'd3:rSMG<=4'd4:rSMG<=4'd5:rSMG<=4'd6:rSMG<=4'd7:rSMG<=4'd8:rSMG<=4'd9:rSMG<=假设笔者使用的时钟频率是20Mhz,那1ms的定时常1ms/(1/20Mhz)=1E-3/50E-9=也就是说每一位数码管在动态扫描中都使用大约20000个时钟。在第一个1ms的时候,由1SMG_Data19999Scan_Sig20000SMG_Data多了一个时钟。数码管动态显示的效果不会因为 的输出少了一个时钟而影响实际的效果(人类眼是很迟钝的,所以很多时候我们用不着特意去仿真这个数码管接口笔者再来举个例上图GUI系统中的led_control_module

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论