关于verilog if 多个条件封装module的一个小问题

VerilogHDL扫盲 - zhliao - 博客园
随笔 - 119
以下大部分内容摘自VerilogHDL扫盲篇:
学习VerilogHDL语言不像学习一些高级语言,对于高级语言来说它们已经是完成品了,其外它们还有很多被隐藏的指令,这些好处无疑是减轻了学习者的负担。相反的VerilogHDL语言既是完成品,既不是完成品,就是因为它太自由了... 所以往往会让学习者感到疑惑,很疲惫和浮躁(我不学了!)。学习VerilogHDL语言需要一段过渡期的,快则半年,普通则1~2年,慢则很多年。即使经过了过渡期这也不表示已经掌握VerilogHDL语言了。所以呀朋友,希望你们可以沉住气,&欲速则不达&这是老祖先的智慧,它非常适合用在学习VerilogHDL语言的路上。VerilogHDL语言既不是顺序语言而且也非常的自由,VerilogHDL语言不像C语言那样有丰富的库支持,甚至库的概念也不适合用在它身上。但是即使它们是两个世界的居民,但是偶尔VerilogHDL语言可以在很多地方向C语言借签。相反的C语言就不能向VerilogHDL语言借签了。此外VerilogHDL语言还有两大阵列,就是综合语言和验证语言,这更是给学习者雪上加霜&太多的学习者会困惑在这两种语言的中间,所谓的困惑是思路的困惑。在这里,笔者建议先无视验证语言,先把综合语言学好(综合语言也没什么好学的,就如在前面章节笔者所举例的那样,关键字和操作符少得可怜),最重要还是掌握结构(建模)和使用规则(用法)。它们就像挥动着倚天剑和屠龙宝刀的招式,没有了这些招式倚天剑和屠龙宝刀不过是一件单纯的金属而已。至于验证语言,在未来有需要的时候再学也不迟,当阅读他人模块的时候,不要过于转牛角尖的看懂他人的思路,只要明白其中的内容就好。最重要还是如何使用自己的结构和方法去建立他人的思路,从中读者会学得更多。这一点是绝对的事实。就算现在的读者没有能力建立自己的结构也没有关系,来日方长读者有的就是时间。如果读者很钟爱笔者所建立的结构和方法,笔者很乐意也很荣欣被应用(这也是笔者写笔记的初衷)。
沉住气朋友,掌握VerilogHDL语言需要的不只是技术而已,最重要是那颗安静的心,安静的心会带读者乘风破浪,一方通行。此外记录笔记的习惯更为重要,向自己学习比起向他人学习更有学习的价值
一,建模是VerilogHDL语言的中心思想之二
二,时序是VerilogHDL语言的中心思想之二
在笔者的眼中,总结上C语言和VerilogHDL语言之间的区别会是如上的图表。关于高级语言和VerilogHDL语言区别的内容笔者讨论到这里就好了,读者不要过于深入区分谁是谁,谁又不是谁,如此纠结对学习没有任何好处,更多认识,当读者们深入以后就会自然了解。
我们知道驱使(RTL级)模块行动的最小单位就是时钟,即时发生延迟也只是延迟一个时钟,又或者2~3个时钟,绝对不会出现什么延迟2ns~3ns(物理路径延迟)等的问题。
在笔者的眼中&时序&的思想非常简单,就是如何读懂波形图,如何把波形图和模块的内容作联系。
例子1-reg 和wire的尴尬:
reg 和wire如果站在RTL级建模的角度上,reg 就是寄存器,作用是用来暂存内容,而且也提供操作空间;wire就是连线,作用仅此而已。但是站在组合逻辑级建模上reg和wire已经是傻傻分不清楚了
举个例子:
moduleomg_module(output[7:0]Q);
wire[3:0]A=4'd0;
wire[3:0]B=4'd2;
wire[3:0]C=4'd3;
assignQ=A+B+C;
以上的一段代码,请问wire的作用是连线还是寄存内容了?呵呵,笔者没有说这样的使用方法有错呀。在这里笔者只是提出一个有趣的例子而已,对于一些初学者来说可能会非常的疑惑,尤其是那些习惯&面向对象&思想的人们...
moduleomg_module(output[7:0]Q);
reg[3:0]A;
reg[3:0]B;
reg[3:0]C;
always@(*)
assignQ=A+B+C;
如果笔者换成这样写法的话,是不是觉得更有道理呢?always(*) 的使用暗示了这是一个组合逻辑,然而寄存器A的值是4'd0,寄存器B的值是4'd2,寄存器C的值是4'd3,Q的驱动输出是寄存器A,B,C的值综合。
更有趣得是,经过编译两段代码所生成的RTL视图都一样!?(⊙o⊙)?... 在这里,笔者是要告诉读者一个信息,当我们建模的时候&解读能力&的优先级往往都高过&内容精简性&。要一度过于&贪小便宜&而把内容的解读能力跨下了,虽然这两个代码都没有错,而且结果一致。但是一个潜在的问题是,我们人类都是习惯把&东西分类&以便管理和理解,既然wire在字面上都是&连线&的意思了,就干脆把它当&连线&来使用...
例子2-always@() 的多样性
1.always@(posedgeCLKornegedgeRSTn)// 当CLK和RSTn变化的时候
2.always@(*) // 什么时候都变化, 亦即默认为组合逻辑
3.always@(A) // 当A变化的时候
always@() 的用法很多,但是用得最多的就是第1个和第2个。
always@(posedgeCLKornegedgeRSTn)
上面一段代码是笔者最爱的&基于仿顺序操作想法&的基本&用法模板&,在后期里它可是大展拳脚。
always@(*)A=4'd9; // 常数赋值
always@(*) // 选择器
if(Start_Sig[0])rQ=U1_Q;
elseif(Start_Sig[1])rQ=U2_Q;
至于第二种always@() 的用法,笔者估计它是用得最&泛滥&了,尤其是在组合逻辑建模里,不过笔者使用的比较不多, 除了&常数赋值&和&输出选择器&以外。
最后的第一种always@()的用法,基本上只要懂得上面两种always@() 用法以后,自然而然也会了。
例子3- 最头疼的=和&=赋值
基本上要搞懂这两个赋值操作符号的作用,就必须把&时序&的概念搞懂先。
宏观上,如同参考书中所说的一样;微观上,在时序中&=&是引发&即时事件&,&&=&则是引发&时间点事件&
例子4- 要慎用的*/%数学运算符
当读者使用*/ 和%的数学运算符的时候,笔者请你们再三的三思(九思?呵呵!),因为使用它们的代价很大。如果读者所使用的FPGA有内嵌硬件乘法器又或者除法器的话,那么这些乘法器和除法器就会被消耗。相反的,如果读者说使用的FPGA是没有包含这些东西的话,资源逻辑的消耗是很大的。一般上,如果是为了求出*2 *4 *8 *16又或者/2 /4 /8 /16 笔者建议使用位操作的运算符,亦即&&和&&,它们也可以求出同样的结果。如果想要求出的结果是不在2N范围之内的话,读者还是求与其他的方法... 只有在用尽办法的时候才使用它们。至于%的数学运算符,它真的是一个罪恶,没有可以替代的第三方法....在这里笔者要强调一下,笔者不是说不可以使用它们,笔者只是建议如果可以的话不要过度依赖它们,它们尽是一些逻辑资源的大食怪,不把资源吃光才怪。
在这里,笔者再强调一下HDL语言是一种非常自由的语言,它没有固定的结构,也没有固定的使用方法。参考书在乎&如何使用HDL语言去完成设计&,然而笔者比较在乎&如何有效使用HDL语言&。这两者之间都没有问题,不过是笔者的笔记比较偏向学习的口味,没有参考书那样死沉沉的气氛,比较愉快和轻松
话句话说,VerilogHDL语言可以应用的地方只适合&逻辑和底层设计&.... 不不不,这是天大的误会。就这样,随之又产生&C语言驱动的东西,既然用VerilogHDL语言去驱动&类似的声音。是谁规定C语言可以驱动的东西,VerilongHDL语言就不能驱动?相反的,C语言可以驱动的东西,如果读者也能使用VerilogHDL语言去驱动,那么这才是真正的学习。之所以会产生如此的声音,就如笔者在前几章节讲述的那样:&VerilogHDL语言的结构自由,使用方法也自由,自由到好像没有一样&很多的设计都不包含结构和使用方法,只要设计可以发挥预期般的效果就Okay~如果读者明白了这个简单的道理,读者自然会明白自定义VerilogHDL语言的结构和使用方法是非常的重要和基础。VerilogHDL语言的建模不是越复杂就越伟大,反之越直接的建模才是学习的方向。在这里,听笔者说:&当你放下偏见,你才可以接触到真理&,这简单的智慧在哪里都行得通,学习VerilogHDL语言也是这样一回事。
笔者来说说为什么单文件主义远离了VerilogHDL语言的本质呢?VerilogHDL语言,本质上是并行而且又有&面向对象&的味道。但是这&面向对象&的概念和C++语言中的概念有所不同,然而它更接近现实中的&管理系统&(详解请看建模篇)。读者尝试想象,有没有可能一个系统的操作,没有部门,没有团队,没有小组?对,就是不可能。单文件主义恰恰好就是违反了这个简单的道理。
上文中所说的&没有分类&的烂漫约会,如果也&没有顺序操作&的支持... 会是一个非常糟糕的情形。因为这个系统操作(约会过程)没有结构的支持, 这个情形也反映出了单文件主义的致命缺点。笔者有一句很经典的话:&解读能力差的模块是最糟糕的&,这一句话完全迎合单文件主义下所建立的模块。
低级建模的基本单元有:功能模块,控制模块,组合模块。
? 功能模块的内容包含了最基本的动作。
? 控制模块的内容包含了动作的控制步骤。
? 组合模块的内容包含了所有功能模块和控制模块之间的组合。
建模层次有:基础(模块)建模,仿顺序操作建模,接口建模,系统建模。
? 基础(模块)建模的内容包含了最小功能的模块。
? 仿顺序操作建模,这一个比较特别,主要是模仿了C语言中的函数。
? 接口建模的内容包含了一个已经封装完成的模块。
? 系统建模的内容包含了一个特定功能的模块。
举个例子,就拿串口来作个比方:
在串口硬件模块(串口系统建模)里,分类了发送接口和接受接口。发送发送接口包含了FIFO模块,波特率产生模块和串口发送控制模块。串口接收串口包含了FIFO模块,波特率产生模块,串口接收控制模块。串口发送模块是组合了波特率产生模块和串口发送控制模块,串口接收模块是组合了波特率产生模块和串口接收控制模块。
串口系统建模之间的模块基本单元分类:
串口系统建模之间的层次分类:
在这里笔者只是简介了笔者最爱的&低级建模&的结构分类而已,事实上每一个基本单元和每一个层次都有严谨的定义。建模是VerilogHDL语言的结构,越庞大的设计建模所带来的后期影响是读者/笔者远远都猜想不到的。故建模对于VerilogHDL语言来说是非常重要的基础。VerilogHDL语言的结构是自由的,然而笔者的&低级建模&是笔者自定义的结构而已。当然读者也可以建立自己的结构。
仿顺序操作是什么?就是利用VerilogHDL语言自身的特质去模仿一些顺序语言如C语言,故称为&仿顺序操作&
always@(posedgeCLKornegedgeRSTn)
begin....i&=i+1'b1;end
就以流水灯来说话吧:
always@(posedgeCLKornegedgeRSTn)
rLED&=4'b0000;
beginrLED&=4'b0001;i&=i+1'b1;end
if(Timer==T10MS)i&=i+1'b1;end
beginrLED&=4'b0010;i&=i+1'b1;end
if(Timer==T10MS)i&=i+1'b1;end
beginrLED&=4'b0100;i&=i+1'b1;end
if(Timer==T10MS)i&=i+1'b1;end
beginrLED&=4'b1000;i&=i+1'b1;end
if(Timer==T10MS)i&=4'd0;end
在case... endcase 之间,步骤i 等于0,2,4,6的时候是更新LED(流水操作),步骤i等于1,3,5,7的时候是延迟10ms。
此外,还可以把步骤i当成简单的循环。上面一段代码表达了,当步骤i等于0,2,4,6的时候就更新rLED,。反之,当步骤i等于1,3,5,7的时候就延迟10ms。在步骤i等于8的时候是步骤返回操作。
always@(posedgeCLKornegedgeRSTn)
rLED&=4'b0001;
beginrLED&={rLED[0],rLED[3:1]};i&=i+1'b1;end
if(Timer==T10MS)i&=i-1'b1;end
又或者更进一步的压缩步骤,使得代码更直接而且更节省资源。在上面一段代码当中,只有两个步骤,亦即步骤0和1。步骤0是更新rLED,步骤1是延迟10ms,然而这两个步骤之间交互交替使而产生流水灯效果
当然,步骤i的用法不仅而已,如果把&时序&的概念引入的话:
always@(posedgeCLKornegedgeRSTn)
Mper&=8'd0;
Mcand&=8'd0;
Sum&=8'd0;
beginMper&=Mper_SMcand&=Mcand_SSum&=8'd0i&=i+1'b1;end
if(Mcand==0)i&=i+1'b1;
elseSum&=Sum+MMcand&=Mcand-1'b1;end
以上一段代码是简单的乘法运算,Mper是乘数的暂存器,Mcand是被乘数的暂存器,Sum是累加空间。当步骤i等于0的时候初始化相关的寄存器,在步骤i等于1的时候执行乘法操作... 在这里读者也可这样说:&在T0的时候初始化相关的寄存器,在接下来的时钟执行乘法操作... (有点闷,看不太懂,实力还不够(⊙o⊙))
总结之下,这个用法可以伸缩的范围非常之大。除外,它所带来的好处也非常之多:
? 提供了VerilogHDL语言顺序操作的支持。
? 提高了模块的表达能力。
? 提供了仿顺序操作&建模的结构基础。
但是它也带来一些限制:
? 不推荐嵌套case...endcase 和if。
? 该用法不推荐出现过多在同一个模块中。
这些限制是笔者标记下来的,这之间和&低级建模&有多少关系。当然,如果读者不遵守的话也没有问题。显然这个用法也不是万能的,尤其是一些紧密的RTL级建模,如:VGA驱动,它就显得无用武之地了。事实上这个用法到目前为止,笔者还在不停的研究当中,越深入学习它,就越发现它的潜能很深...
认识RTL级设计(建模)
用凡人的话来说CLK代表了一个模块的心跳节拍,这个心跳节拍提供模块可以消耗的动力。但是CLK信号真正可以被模块所用到不是它的高电平又或者低电平,而是上升沿(低电平到高电平的变化)和下降沿(高电平到低电平的变化)。
always@(posedgeCLK)
对于RTL级设计来说CLK是模块的心跳,没有心跳模块就不能活动,没有心跳就没有时序图。换另一句话说,构成RTL级最基本的设计需要&寄存器&为最小的建模单位,然后再加上模块可以活动的CLK信号。
always@(posedgeCLK)
Counter1&=Counter1+1'b1;
always@(posedgeCLK1/2)
Counter2&=Counter2+1'b1;
上面有一段代码是Counter1+CLK和Counter2+CLK1/2促成最简单的RTL级设计。Counter1在每一个CLK时钟内递增,然而Counter2在每一个CLK1/2时钟内递增。到目前为止Counter1和Counter2还是独立关系。
图0.13b是Counter1+CLK和Counter2+CLK1/2产生的时序图。在这里Counter2所使用的频率是Counter1的一半。在每一个CLK的上升沿Counter1都递增,然而在每一个CLK1/2的上升沿Counter2都递增
always@(posedgeCLK)
Counter1&=Counter1+1'b1;
always@(posedgeCLK1/2)
Counter2&=Counter1;
假设笔者把Counter1和Counter2联系起&关系&的话,如上面的一段代码所述。又会产生怎样的时序图呢?
图0.13c是Counter1和Counter2建立关系以后多产生的时序图。在CLK是T0的时候,CLK_1/2也是在T0。由于在T0之前Counter1什么也没有,所以Counter什么也读不到(一般上0为复位值)。在CLK_1/2是T1,Counter2尝试读取Counter1的&过去值&,结果Counter2读到值2,所以在CLK_1/2的T1,Counter2的&未来值&是2。类似的事情也发生在CLK_1/2的T2,T3和T4的时候。在这里读者先不用管&过去值&和&未来值&的定义,这是笔者在时序篇里的专用词。读者需要焦距的是,每一次Counter1成功递增是发生在CLK的上升沿,然而Counter2每一次成功读取Counter1的值都是发生在CLK_1/2的上升沿。换句话说,CLK的上升沿是触发Counter1递增,CLK_1/2的上升沿是触发Counter读取Counter1的过去值。以上的内容就是RTL级设计最基本的思想。
至于组合逻辑级设计呢?在VerilogHDL语言中,如果我们把VerilogHDL语言看成是理想的语言,那么组合逻辑就可以直接无视被CLK的影响,因为组合逻辑取得的是即时的结果。假设读者不把VerilogHDL语言看成是&理想&的话,组合逻辑会产生&物理&上的延迟。但是笔者还是建议读者把VerilogHDL语言看成是一个理想的工具为好。换另一个角度来看的话,C语言和VerilogHDL语言都是工具,难道C语言会产生&物理&上的延迟吗?此外这样的想法对于VerilogHDL语言的设计会带来很大的好处,尤其是看懂波形图(时序图)哪一环,效果会更加明显。
AbstractVerilog由於在語法上向C靠攏,若熟悉C語言,學Verilog倍感親切,但也由於語法類似,若把Verilog當成C語言來思考,怎很難抓到硬體的精神。IntroductionVerilog有3點思維與C語言不一樣1.軟體是循序的,而硬體是並行的C語言是一行一行的執行,就算組合語言也是一樣,或許你會說threading,但在微觀下仍是循序地執行。但硬體電路就不一樣,電路只要一插上電,所有電路就同時工作。如以下的Verilog
1&always@(posedge&clk)&begin2&&&e&&=&a&&&b;3&&&f&&=&c&&&d;4&end
雖然看起來是 e &= a &&b; 在 f &= c &前面,但實際上合成電路後如下圖所示
由上圖得知,e和f並沒有先後之分,是並行的。2.硬體要循序,要靠clock和FSM或許你會說,『我的演算法就是要循序一步一步的做,如C語言那樣,那怎麼辦?』,若Verilog要這樣,就得靠clock並且搭配FSM,當一個state完成後,進入下一個state,這樣就能依照clock的進行,而達成循序的要求。3.Verilog程式碼沒有先後之分除了blocking assignment有先後執行順序,而nonblocking assignment同時執行外,Verilog的程式沒有前後順序之分,所以才稱為硬體『描述』語言,而非硬體『程式』語言,先寫的不代表先執行,後寫的也不代表後執行,只是代表硬體的架構的描述,也就是說,將原來的電路圖,變成文字描述而已。4.多用RTL Viewer和ModelSim觀察自己寫的codeVerilog寫法小小的差異,合成出來的硬體就可能有天壤之別,多用RTL Viewer觀察合成出來的硬體是否和自己預期的一樣,並多用ModelSim觀察跑出來的波形,這樣會增加你對Verilog的掌握度。Conclusion
很多人學了Verilog,還是把它當C語言寫,事實上他們只是語法類似,但背後的思維並不一樣,唯有『心中有硬體』,才能設計出好的電路。&verilog编译中模块复用方面的一个小问题求解_百度知道
verilog编译中模块复用方面的一个小问题求解
错误提示:ERROR:HDLCompilers:102 - &FSM.v& line 15 Connection to output port 'y' must be a net lvalue对应的行为:seqdet FF0(dout[cnt], clk, rst, din[cnt]);附源代码:module FSM(clk, rst, din, dout);input
[15:0] output wire [15:0] reg [3:0]always@(posedge clk)begin cnt &= cnt + 4'b0001;endseqdet FF0(dout[cnt], clk, rst, din[cnt]);endmodule module seqdet(y, clk, rst, seq);parameter s0=2'b00;parameter s1=2'b01;parameter s2=2'b10;parameter s3=2'b11;reg [3:0] state, next_
always@(posedge clk or rst) begin if(rst)
state &= s0; else
state &= next_endalways @(posedge clk)begin case(state)
s0: next_state=((seq==1)?s0:s1);
s1: next_state=((seq==1)?s2:s1);
s2: next_state=((seq==1)?s0:s3);
s3: next_state=((seq==1)?s0:s1);
default: next_state=((seq==1)?s0:s1); endcase endalways @(posedge clk) begin case(state)
s0: y=1'b0;
s1: y=1'b0;
s2: y=1'b0;
s3: y=1'b1;
default: y=1'b0; endcase endendmodule
提问者采纳
它这里的意思很明确,就如同你不能写:assign dout[cnt] = 一样这里也不能这么写。seqdet FF0(dout[cnt], clk, rst, din[cnt]);应该写成:assign din_cnt = din[cnt];seqdet FF0(dout_cnt, clk, rst, din_cnt);always@* begin
dout[cnt] = dout_end
按照你说的修改后,忽然有出现了这样的问题:ERROR:Xst:528 - Multi-source in Unit &seqdet& on signal &y&; this signal is connected to multiple drivers.wo又茫然了= =怎么搞, 跪谢
我知道了~我又改出了问题。。,谢谢!
提问者评价
太给力了,你的回答完美地解决了我的问题,非常感谢!
其他类似问题
为您推荐:
问题求解的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁下次自动登录
现在的位置:
& 综合 & 正文
Verilog 关于用task仿真应注意的一个问题
  最近在做verilog仿真的时候用到了task,但是我想用task来操作外部的一些变量时遇到了一些问题,搞了好久才的一解决。
我的问题很简单,就类似于用task来生成一个时钟信号,而我的task里面的变量是按照我的正常的设想生成的一个时钟信号,但是当我通过task的端口将这个变量传输出去的时候总是遇到外部的与task对应管教链接的变量一直是个常量的问题,就是外部并没有按照task里面对应变量来翻转,后来在网上查阅资料才发现:task 和 function总是在task执行完毕之后才将值船体出去,这样我就不能按照我预想的那样用task来生成我想要的时钟信号,后来在老师的帮助下才的一解决,就是让task直接操作你module里面对应的变量,相当于全局变量的概念,这样我就不用在task里面声明新的变量而是直接操作外部的信号,在调用task的时候,task的参数列表直接空着就可以了……
&&&&推荐文章:
【上篇】【下篇】Verilog模块概念和实例化-Jason
享受孤独和寂寞,没有抱怨没有诉苦。
模块的概念
模块(module)是verilog最基本的概念,是v设计中的基本单元,每个v设计的系统中都由若干module组成。
1、模块在语言形式上是以关键词module开始,以关键词endmodule结束的一段程序。
2、模块的实际意义是代表硬件电路上的逻辑实体。
3、每个模块都实现特定的功能。
4、模块的描述方式有行为建模和结构建模之分。
5、模块之间是并行运行的。
6、模块是分层的,高层模块通过调用、连接低层模块的实例来实现复杂的功能。
7、各模块连接完成整个系统需要一个顶层模块(top-module)。
无论多么复杂的系统,总能划分成多个小的功能模块。系统的设计可以按照下面三个步骤进行:
(1)把系统划分成模块;
(2)规划各模块的接口;
(3)对模块编程并连接各模块完成系统设计。
模块的结构
module &模块名&(&端口列表&);
&模块条目&
&模块名&是模块唯一的标识符;
&端口列表&是输入、输出和双向端口的列表,这些端口用来与其他模块进行连接。
&定义&是一段程序,用来指定数据对象为寄存器型、存储器型、线型以及过程块,诸如函数块和任务块;
&模块条目&也是一段程序,将上面&定义&和&端口&组合起来,是说明这个模块要做什么的语句;
endmodule之后没有分号。
模块的调用
在做模块划分时,通常会出现这种情形:某个大的模块中包含了一个或多个功能子模块。verilog是通过模块调用或称为模块实例化的方式来实现这些子模块与高层模块的连接的。
调用模块实例的一般形式为:
&模块名&&参数列表&&实例名&(&端口列表&);
module_nameinstance_name(port_associations)&;
其中参数列表是传递到子模块的参数值,参数传递的典型应用是定义门级时延。
信号端口可以通过位置或名称关联;但是关联方式不能够混合使用。
port_expr &&&&&&&&&//位置关联
.PortName (port_expr)&&&&&&//名称关联
定义模块:module Design(端口1,端口2,端口3……);
1)引用时,严格按照模块定义的端口顺序来连接,不用标明原模块定义时规定的端口名。
Design u_1(u_1的端口1,u_1的端口2,u_1的端口3,u_1的端口……);//和Design对应
2)引用时用”.”符号,标明原模块定义时规定的端口名:
Design u_2(&&&&.(端口1(u_1的端口1),
&&&&&&&&&&&&&&&&&&&&&&&&&.(端口2(u_1的端口2),
&&&&&&&&&&&&&&&&&&&&&&&&&.(端口3(u_1的端口3),
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&……&&);&&//建议:在例化的端口映射中采用名字关联,这样,当被调用的模块管脚改变时不易出错。
module and (C,A,B);
input A,B;
and A1 (T3,A,B);&//实例化时采用位置关联,T3对应输出端口C,A对应A,B对应B。
and A2 (&&&&&.C(T3),
&&&&&&&&&&&&&&&&&&&&.A(A),
&&&&&&&&&&&&&&&&&&&&.B(B)&);//实例化时采用名字关联,.C是and器件的端口,其与信号T3相连
port_expr 可以是以下的任何类型:
1)&标识符(reg 或net&)如&.C(T3),T3&为wire&型标识符。
2)&位选择,如&.C(D[0]),C 端口接到D&信号的第0bit&位。
3)&部分选择,如&.Bus (Din[5:4])。
4)&上述类型的合并,如&.Addr({ A1,A2[1:0]}。
5)&表达式(只适用于输入端口),如&.A (wire Zire = 0 )。
参数传递:引用模块时,注意对运用参数编写的模块的灵活引用。
module Decoder(A,F);
&&&&&&&& parameterWidth=1,Polarity=1;
&&&&&&&&&…….
&&&&&&&& wire[3:0] A4;
&&&&&&&& wire[4:0] A5;
&&&&&&&& wire[15:0] F16;
&&&&&&&& wire[31:0] F32;
&&&&&&&& Decoderu_D1(A4,F16);&&&&//u_D1使用默认参数,Width为1,Polarity为1
Decode #(4,0) u_D2(A4,F16);&&&//u_D2的Width为4,Polarity为0
#(4,0)这个参数改变方法是内容对应于被引用的module的,参数的改变还可以像module的引用一样使用”.”:
module_name #(&.parameter_name(para_value),.parameter_name(para_value)) inst_name (port map);
悬空端口的处理
在实例化中,可能有些管脚没用到,可在映射中采用空白处理。
DFF d1 (&&&&&.Q(QS),
&&&&&&&&&&&&&&&&&&&&.Qbar (&),
&&&&&&&&&&&&&&&&&&&&.Data (D&)&,
&&&&&&&&&&&&&&&&&&&&.Preset (&),&//&该管脚悬空
&&&&&&&&&&&&&&&&&&&&.Clock (CK)&);&//名称对应方式。
输入管脚悬空,该管脚输入为高阻 Z,
输出管脚悬空,该管脚废弃不用。

我要回帖

更多关于 verilog 封装 成软核 的文章

 

随机推荐