复习发现之前连最基本的东西都没理解透彻。先从组合逻辑和时序逻辑开始。首先是定义,组合逻辑:在逻辑功能上的特点是任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关,不涉及对信号跳变沿的处理,无存储电路,也没有反馈电路。通常可以通过真值表的形式表达出来。时序逻辑:从电路特征上看来,其特点为任意时刻的输出不仅取决于该时刻的输入,而且还和电路原来的状态有关。电路里面有存储元件(各类触发器,在FPGA 芯片结构中只有D 触发器)用于记忆信息。
组合逻辑
在组合逻辑中一般用户① 内置门原件描述 ②assign连续赋值语句描述 ③过程语句always块描述。举例一个三态门的组合逻辑描述如图1 。
图1.三态门的组合逻辑描述
其中内置门用的情况就不说了,而assign连续赋值语句一般用于简单的组合逻辑,因为当组合逻辑比较复杂时,需要多条assign语句或者使用很多重条件判断符“?”,这样代码的可读性就会比较差。一般比较复杂的组合逻辑都用always块来完成。举例一个简单的8-3优先译码器。
moduleencoder8_3(outcode,a,b,c,d,e,f,g,h);
output[2:0] outcode;
input a,b,c,d,e,f,g,h;
reg[2:0] outcode;
always @(a or b or c or d or e or f or g or h)
begin
if(h) outcode=3’b111;
else if(g) outcode=3’b110;
else if(f) outcode=3’b101;
else if(e) outcode=3’b100;
else if(d) outcode=3’b011;
else if(c) outcode=3’b010;
else if(b) outcode=3’b001;
else if(a) outcode=3’b000;
end
endmodule
图3.3-8优先译码模块符号
总之,无论用哪一种描述方式,组合逻辑都的输出都之与该时刻的输入有关,即不存在寄存器。虽然always块中的被赋值变量要求reg型,但这只是语法的要求,在生存的RTL级描述中,一般不存在寄存器。一般在组合逻辑中我们都使用“=”赋值。
时序逻辑
通常使用always块@(posedge clk)或@(negedge clk)来描述时序逻辑。如基本D触发器的描述module DFF(Q,D,CLK);
output Q;
input D,CLK;
reg Q;
always @(posedge CLK)
Q<=D;
endmodule
通常在always语句中引入条件判断语句组成复杂的时序逻辑。如带清零断和置1断的JK触发器。
module JK_FF(CLK,J,K,Q,RS,SET);
input CLK,J,K,SET,RS;
output Q;
reg Q;
always @(posedge CLK or negedge RS or negedge SET )
begin
if(!RS) Q<=1’B0;
else if(!SET) q<=1’B1;
else case({J,K})
2’b00: Q<=Q;
2’b01:Q<=1’b0;
2’b10:Q<=1’b1;
2’b11:Q<=~Q;
endcase
end
阻塞赋值和非阻塞赋值在时序逻辑和组合逻辑
在时序逻辑中<=与顺序无关,而=与顺序有关。在组合逻辑中=与顺序无关。阻塞性赋值语句“=”和非阻塞阻塞性赋值语句“=”和非阻塞性赋值语句“<=”的根本区别在于:阻塞性赋值是在下一语句执行之前完成当前赋值的,而非阻塞性赋值是在当前时步结束时完成赋值的。