Verilog自学:关于门级,数据流级,行为级建模
我是桂林理工大三苦逼通信学子🐕,在前些日子,看到宿舍的电信学霸在用verilog写电路,不由得心生神往。于是便开始了我的verilog自学。这篇文章也算是写写我自学的收获吧,如有不对的地方,还望斧正。
什么是门级建模?
门级建模可以认为是用HDL规定的语言将一个逻辑电路图表示出来。换而言之,就是用Verilog语言中内置的12个基本门级元件,去表述逻辑电路图中元件与元件之间的连接关系。
什么是数据流级建模?
到了数据流级建模的阶段,我们去描述电路,更多的是使用运算符,不在局限于基本门级元件。其下可以触及门级电路之间的连接关系,上可以扩展到电路的功能描述。
什么是行为级建模?
行为级建模,我认为就是用多个并行的,动态的过程模块去描述系统的工作。主要就是去描述电路所具有的行为,或者说,就是当电路在哪些输入信号来临时会有怎样的输出。
12个基本门级元件?
有看过数电的朋友,应该都知道,12个基本门级元件包括:与,或,非,与非,或非,异或,异或非,缓冲器,以及高电平使能三态缓冲器,低电平使能三态缓冲器,高电平使能三态非门,低电平使能三态非门。不多赘述。
对于体现这三种建模方式的不同,我想最为直观的角度就是代码语句的差异。下面我将以全加器为例子。
module fulladd(s,cout,cin,a,b);//一位全加器
output s,cout;
input cin,a,b;
wire and1,and2,and3,and4; //全加器由三个与门,一个异或门,一个或门组成。
xor (s,cin,a,b);
and (and1,cin,a);
and (and2,a,b);
and (and3,cin,b);
or (cout,and1,and2,and3);
endmodule
module add4(s,COUT,CIN,x,y);//四位全加器模块的定义声明
output COUT;
output [3:0]s;//可以使用向量形式去尽可能减少标识符的个数,可以有效的降低代码规模。
input CIN;
input [3:0]x,y;
wire c0,c1,c2;
fulladd add0(.s(s[0]),.cout(c0),.cin(CIN),.a(x[0]),.b(y[0]));
fulladd add1(.s(s[1]),.cout(c1),.cin(c0),.a(x[1]),.b(y[1]));
fulladd add2(.s(s[2]),.cout(c2),.cin(c1),.a(x[2]),.b(y[2]));
fulladd add3(.s(s[3]),.cout(COUT),.cin(c2),.a(x[3]),.b(y[3]));
endmodule
电路结构如上图所示。
而从波形上看也是可以的。
数据流级建模全加器
module add4(S,COUT,CIN,X,Y);
output COUT;
output [3:0]S;
input [3:0]X,Y;
input CIN;
assign {COUT,S}=X+Y+CIN;//这条语句表示s为后三位变量之和,如有进位则放在cout中。
endmodule;
数据流建模,功能描述方面使用了一条assign语句,采用运算操作符完成四位信号的相加过程。
与门级建模的电路相比,电路相差甚远。这是因为其抽象层级较高,考虑的是功能的算法情况,而不关心,底层到底是如何实现的,所以这些语句最多就是个算数表达式,其进行综合,综合器会根据情况自动来选择如何完成电路。
行为级建模全加器
module add4(S,COUT,CIN,X,Y);
output COUT;
output [3:0]S;
input [3:0]X,Y;
input CIN;
reg[3:0]S;//建立可综合模型时赋值语句的左端必须是reg类型
reg COUT;
always@(X,Y,CIN)//这个是always结构,由@这个符号引导敏感事件列表,一旦这三个变量发生了变化,就会执行该语句
{COUT,S}=X+Y+CIN;
endmodule
这个角度来看,这就是在描述电路的行为,亦或者可以说是在描述电路的输入与输出的关系,所以使用行为级建模的话,其实际的电路图并没有太大的意义。
这也是行为级建模的优点,不用去过多的关注底层电路的实现形式,更多的是关注电路的行为。
至于如何把行为级建模的代码过渡到最后电路的可实现形式。我们可以不用care,因为我们可以把这项工作给EDA软件(老苦力了)去实现。