1、同步RS触发器
RS触发器分为同步触发器和异步触发器,二者的区别在于同步触发器有一个时钟端clk,只有在时钟端的信号沿时,触发器的输出才会发生变化。下面是Verilog代码:
module sy_rs_ff(clk,r,s,q,qb)
input clk,r,s;
output q,qb;
reg q;
assign qb = ~ q;
always @ (posedge clk) begin
case ({
r,s})
2'b00 : q <= q;
2'b01 : q <= 1;
2'b10 : q <= 0;
2'b11 : q <= 1'bx;
endcase
end
endmodule
他的RTL图可以在Vivado或者ISE上查看,仿真结果比较直观,所以就不放仿真结果图了。
2、同步T触发器
T触发器分为同步触发器和异步触发器,二者的区别在于同步触发器有一个时钟端clk,同步T触发器的逻辑功能为:但时钟沿到来时,如果T=0,则触发器状态保持不变,否则触发器输出端反转。R为复位端,R为高时,输出与时钟无关且Q=0。
Verilog代码如下
module sy_t_ff(clk,r,q,qb)
input clk,r;
output q,qb;
reg q;
assign qb = ~q;
always @ (posedge clk) begin
if(r)
q <= 0;
else
if(t)
q <= q;
else
q <= ~q;
end
endmodule
3、同步D触发器
功能为:D输入只能在时序信号clk的沿发生变化时才能被写入到存储器中,替换之前的值,常用于数据延迟以及数据存储模块中。Verilog代码如下:
module sy_d_ff (clk,d,q,qb)
input clk,d;
output q,qb;
reg q;
assign qb = ~q;
always @ (posedge clk) begin
q <= d;
end
endmodule
4、同步JK触发器
JK触发器常用于实现计数器。当clk=0时,触发器不工作;当clk=1时,功能如下:当JK为00,01以及10时,实现RS触发器功能;当JK为11时,实现T触发器功能。代码如下:
module sy_jk_ff (clk,j,k,q,qb)
input clk,j,k;
output q,qb;
reg q;
assign qb = ~q;
always @ (posedge clk) begin
case({
j,k})
2'b00:q <= q;
2'b01:q <= 0;
2'b10:q <= 1;
2'b11:q <= ~q;
endcase
end
endmodule
再说一下基本的时序处理模块吧
1、奇数与偶数分频电路
(1)偶数分频电路
偶数倍分频时最简单的一种分频模式,完全可以通过计数器计数实现。比如说要进行N倍偶数分频,那么可由待分频的时钟触发计数器计数,当计数器从0计数到N/2 -1时,输出时钟进行翻转,并给计数器一个复位信号,使下一个时钟从零开始计数,以此循环,便可以实现任意的偶数分频。下面给出一个16分频的电路。
module clk_div16 (clk_in,rst,clk_out)
input clk_in,rst;
output clk_out;
reg clk_out;
reg [2:0] cnt;
always @ (posedge clk_in) begin
if (!rst) begin
cnt <= 0;
clk_out <= 0;
end
else
if (cnt == 7) begin
cnt <= 0;
clk_out <= !clk_out;
end
else begin
cnt <= cnt + 1;
clk_out <= !clk_out;
end
end
endmodule
(2)奇数分频电路
奇数分频有很多方法,说一下常用的错位“异或”法。对于实现占空比为50%的N倍奇数分频,首先进行上升沿触发的模N计数,计数到某一选定值时进行输出时钟的翻转,然后经过(N-1)/2 个时钟再次进行翻转得到一个占空比非50%计数N分频时钟。同时进行下降沿触发的模N计数,到和上升沿触发输出时钟翻转选定值相同值时,输出时钟翻转,同样经过(N-1)/2 个时钟时,输出时钟再次翻转生成占空比非50%的计数N分频时钟。两个占空比非50%的N分频时钟相或运算,得到占空比50%的计数N分频时钟。以3分频代码为例:
module clk_div3(clk_in,rst,clk_out)
input clk_in,rst;
output clk_out;
reg [1:0] cnt,cnt1;
reg clk_1t3p,clk_1t3n;
always @ (posedge clk_in) begiin
if (!rst) begin
cnt <= 0;
cnt_1t3p <= 0;
end
else begin
if(cnt == 2'b10) begin
cnt <= 0;
cnt_1t3p <= cnt_1t3p;
end
else begin
cnt <= cnt + 1;
cnt_1t3p <= !cnt_1t3p;
end
end
end
always @ (negedge clk_in) begin
if (!rst) begin
cnt1 <= 0;
clk_1t3n <= 0;
end
else begin
if(cnt1 == 2'b10) begin
cnt1 <= 0;
clk_1t3n <= clk_1t3n;
end
else begin
cnt1 <= cnt1 + 1;
clk_1t3n <= !clk_1t3n;
end
end
end
assign clk_out = clk_1t3p|clk_1t3n;
endmodule
2、同步采样模块
在实际的应用中,外部输入的异步信号需要经过系统时钟的同步化,且将输入的异步信号转化成一个时钟长的脉冲信号。给一个Verilog代码看看吧。
module clk_syn(clk,rst,s_in,s_out)
input clk,rst,s_in;
output s_out;
reg s_out;
reg s_t1,s_t2;
always @(posedge clk) begin
if (!rst) begin
s_t1 <= 0;
s_t2 <= 0;
end
else begin
s_t1 <= s_in;
s_t2 <= s_t1;
end
end
assign s_out = s_t1 & (!s_t2);
endmodule
可以自己拿代码去Vivado或者Modelsim上运行一下看一下波形,仿真测试代码比较简单,我就不浪费时间了。