組合邏輯&時序邏輯
- 波形圖中,表達時序邏輯時如果時鐘和數(shù)據(jù)是對齊的,則默認(rèn)當(dāng)前時鐘沿采集到的數(shù)據(jù)位在該時鐘上升沿前一時刻的值。表達組合邏輯時如果時鐘和數(shù)據(jù)是對齊的,則默認(rèn)當(dāng)前時鐘沿采集到的數(shù)據(jù)為該始終上升沿同一時刻的值。
- 組合邏輯和時序邏輯的區(qū)別:
主要是看數(shù)據(jù)工作是不是在時鐘沿下進行的。在 FPGA 的設(shè)計中,復(fù)雜的電路設(shè)計都要用到時序邏輯電路,往往都是以時序邏輯電路為主,組合邏輯為輔的混合邏輯電路。
- 組合邏輯會存在險競爭冒險,會引起電路的不穩(wěn)定性和工作時的不確定性
- 時序邏輯最基本的單元就是寄存器,寄存器一般由D觸發(fā)器構(gòu)成
- 時序電路“延一拍”,key_in為高,led_out延遲一拍才變高
寄存器、觸發(fā)器、鎖存器辨析
-
寄存器(register):用來存放數(shù)據(jù)的一些小型存儲區(qū)域,用來暫時存放參與運算的數(shù)據(jù)和運算結(jié)果,它被廣泛的用于各類數(shù)字系統(tǒng)和計算機中。其實寄存器就是一種常用的時序邏輯電路,但這種時序邏輯電路只包含存儲電路。寄存器的存儲電路是由鎖存器或觸發(fā)器構(gòu)成的,因為一個鎖存器或觸發(fā)器能存儲1位二進制數(shù),所以由N個鎖存器或觸發(fā)器可以構(gòu)成N位寄存器。 工程中的寄存器一般按計算機中字節(jié)的位數(shù)設(shè)計,所以一般有8位寄存器、16位寄存器等 ;
-
寄存器的應(yīng)用
a)可以完成數(shù)據(jù)的并串、串并轉(zhuǎn)換;
b)可以用做顯示數(shù)據(jù)鎖存器:許多設(shè)備需要顯示計數(shù)器的記數(shù)值,以8421BCD碼記數(shù),以七段顯示器顯示,如果記數(shù)速度較高,人眼則無法辨認(rèn)迅速變化的顯示字符。在計數(shù)器和譯碼器之間加入一個鎖存器,控制數(shù)據(jù)的顯示時間是常用的方法。
c)用作緩沖器;
d)組成計數(shù)器:移位寄存器可以組成移位型計數(shù)器,如環(huán)形或扭環(huán)形計數(shù)器。
https://blog.csdn.net/bleauchat/article/details/85312172
D觸發(fā)器(D Flip Flop,DFF)
- D觸發(fā)器的功能:
1、在一個脈沖信號上升沿或下降沿的作用下,將信號從輸入端D送到輸出端Q,如果時鐘脈沖的邊沿信號未出現(xiàn),即使輸入信號改變,輸出信號仍然保持原值。
2、寄存器擁有復(fù)位清零功能,復(fù)位分為同步復(fù)位和異步復(fù)位
3、能夠存儲一位二進制碼
- D觸發(fā)器分為兩種,一種是同步復(fù)位D觸發(fā)器,一種是異步觸發(fā)D觸發(fā)器。
- 電路符號
- 真值表
同步復(fù)位D觸發(fā)器
- 同步復(fù)位D觸發(fā)器,復(fù)位與時鐘同步。即時鐘上升沿到來時檢測到按鍵的復(fù)位操作才有效
- 代碼實現(xiàn)
//同步復(fù)位D觸發(fā)器
module filp_flop (
input wire sys_clk,sys_rst_n,
input wire key_in,
output reg led_out
);
always @(posedge sys_clk) begin
if(sys_rst_n == 1'b0) begin //rst低電平時復(fù)位,并且大前提是clk為上升沿。
led_out <= 1'b0; //sys_clk上升沿到來時,若檢測到rst為低電平時復(fù)位有效
end else begin
led_out <= key_in;
end
end
endmodule
異步復(fù)位D觸發(fā)器
- 異步復(fù)位觸發(fā)器,復(fù)位與時鐘不同步。寄存器不關(guān)心時鐘上升沿來不來,只要有按鍵按下,就立即執(zhí)行復(fù)位操作。但是復(fù)位釋放時仍需要等到時鐘上升沿才能檢測到key_in的值 并給led_out
- 代碼實現(xiàn)
module dff ( //異步復(fù)位
input wire sys_clk,sys_rst_n,
input wire key_in,
output reg led_out
);
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0) begin //rst低電平時復(fù)位,但是大前提不需要clk為一定上升沿。
led_out <= 1'b0; //檢測到 sys_rst_n 的下/降沿時立刻復(fù)位,不需等待 sys_clk 的上升沿來到后再復(fù)位
end else begin
led_out <= key_in;
end
end
endmodule
標(biāo)準(zhǔn)鎖存器
- 電路符號
// ===================================
// Description:
// Verilog module for general latch
//====================================
module sirv_gnrl_ltch # (
parameter DW = 32
) (
//input test_mode,
input lden,
input [DW-1:0] dnxt,
output [DW-1:0] qout
);
reg [DW-1:0] qout_r;
always @ *
begin : LTCH_PROC
if (lden == 1'b1)
qout_r <= dnxt;
end
assign qout = qout_r;
endmodule
標(biāo)準(zhǔn)DFF模塊大合集
為什么要使用標(biāo)準(zhǔn)DFF模塊
- 寄存器是數(shù)字同步電路中最基本的單元。使用 Verilog 進行數(shù)字電路設(shè)計時,最常見的
方式是使用 always 塊語法生成寄存器。蜂鳥 E200 處理器核推薦如下原則,本原則來自于嚴(yán)
謹(jǐn)?shù)墓I(yè)級開發(fā)標(biāo)準(zhǔn),其要點如下。
對于寄存器避免直接使用 always 塊編寫,而是應(yīng)該采用模塊化的標(biāo)準(zhǔn) DFF 模塊進
行例化。示例如下所示,一個名為 flg_dfflr 的寄存器,除了時鐘(clk)和復(fù)位信號(rst_n)
之外,還帶有使能信號 flg_ena 和輸入(flg_nxt)/輸出信號(flg_r)。
wire flg_r;
wire flg_nxt = ~flg_r;
wire flg_ena = (ptr_r == ('E203_OITF_DEPTH-1)) & ptr_ena;
//此處使用例化 sirv_gnrl_dfflr 的方式實現(xiàn)寄存器,而不是使用顯示的 always 塊
sirv_gnrl_dfflr #(1) flg_dfflrs(flg_ena, flg_nxt, flg_r, clk, rst_n);
使用標(biāo)準(zhǔn) DFF 模塊例化的好處包括以下內(nèi)容。
? 便于全局替換寄存器類型。
? 便于在寄存器中全局插入延遲。
? 明確的 load-enable 使能信號(如下例的 flg_ena)方便綜合工具自動插入寄存器級別
的門控時鐘以降低動態(tài)功耗(參見第 15.1.5 節(jié)了解更多此低功耗設(shè)計的信息)。
? 便于規(guī)避 Verilog 語法 if-else 不能傳播不定態(tài)的問題,有關(guān)此內(nèi)容可以參考第 5.3.2 節(jié)。
標(biāo)準(zhǔn)DFF代碼實現(xiàn)
sirv_gnrl_dfflrs //帶有 load-enable 使能,帶有異步 reset,復(fù)位默認(rèn)值為 1 的寄存器
sirv_gnrl_dfflr //帶有 load-enable 使能,帶有異步 reset,復(fù)位默認(rèn)值為 0 的寄存器
sirv_gnrl_dffl //帶有 load-enable 使能,不帶有 reset 的寄存器
sirv_gnrl_dffrs //不帶有 load-enable 使能,帶有異步 reset,復(fù)位默認(rèn)值為 1 的寄存器
sirv_gnrl_dffr //不帶有 load-enable 使能,帶有異步 reset,復(fù)位默認(rèn)值為 0 的寄存器
sirv_gnrl_ltch //Latch 鎖存器模塊
sirv_gnrl_dfflrs, load-enable使能/ 異步reset/ 復(fù)位值為1
// =========================================
// Description:
// Verilog module gnrl DFF with Load-enable and Reset
// Default reset value is 1
// =========================================
module gnrl_dfflrs #(
parameter DW = 8
) (
input lden,
input [DW-1:0] dnxt,
output [DW-1:0] qout,
input clk,
input rst_n
);
reg [DW-1:0] qout_r ;
always @(posedge clk or negedge rst_n)
begin: DFFLRS_PORC
if(rst_n == 1'b0) begin
qout_r <= {DW{1'b1}}; // Default reset value is 1
end
else if (lden == 1'b1) begin
qout_r <= #1 dnxt;
end
end
assign qout = qout_r;
endmodule
sirv_gnrl_dfflr,load-enable使能/ 異步reset/ 復(fù)位值為0
// ===========================================================================
// Description:
// Verilog module gnrl DFF with Load-enable and Reset
// Default reset value is 0
// ===========================================================================
module gnrl_dfflr # (
parameter DW = 8
) (
input lden,
input [DW-1:0] dnxt,
output [DW-1:0] qout,
input clk,
input rst_n
);
reg [DW-1:0] qout_r;
always @(posedge clk or negedge rst_n)
begin : DFFLR_PROC
if (rst_n == 1'b0)
qout_r <= {DW{1'b0}}; // Default reset value is 0
else if (lden == 1'b1)
qout_r <= #1 dnxt;
end
assign qout = qout_r;
endmodule
sirv_gnrl_dffl,load-enable使能/ 不帶reset
// ===========================================================================
// Description:
// Verilog module gnrl DFF with Load-enable, no reset
// ===========================================================================
module gnrl_dffl # (
parameter DW = 8
) (
input lden,
input [DW-1:0] dnxt,
output [DW-1:0] qout,
input clk
);
reg [DW-1:0] qout_r;
always @(posedge clk)
begin : DFFL_PROC
if (lden == 1'b1) //no reset
qout_r <= #1 dnxt;
end
assign qout = qout_r;
endmodule
sirv_gnrl_dffrs,不帶load-enable/ 帶異步reset/ 復(fù)位值為1
// ===========================================================================
// Description:
// Verilog module gnrl DFF with Reset, no load-enable
// Default reset value is 1
// ===========================================================================
module gnrl_dffrs # (
parameter DW = 8
) (
input [DW-1:0] dnxt,
output [DW-1:0] qout,
input clk,
input rst_n
);
reg [DW-1:0] qout_r;
always @(posedge clk or negedge rst_n)
begin : DFFRS_PROC
if (rst_n == 1'b0)
qout_r <= {DW{1'b1}}; //Default reset value is 1
else //no load-enable
qout_r <= #1 dnxt;
end
assign qout = qout_r;
endmodule
sirv_gnrl_dffr,不帶load-enable/ 帶異步reset/ 復(fù)位值為0
// ===========================================================================
// Description:
// Verilog module gnrl DFF with Reset, no load-enable
// Default reset value is 0
// ===========================================================================
module gnrl_dffr # (
parameter DW = 8
) (
input [DW-1:0] dnxt,
output [DW-1:0] qout,
input clk,
input rst_n
);
reg [DW-1:0] qout_r;
always @(posedge clk or negedge rst_n)
begin : DFFR_PROC
if (rst_n == 1'b0)
qout_r <= {DW{1'b0}}; // Default reset value is 0
else
qout_r <= #1 dnxt;
end
assign qout = qout_r;
endmodule
sirv_gnrl_ltch,Latch鎖存器模塊
// ===========================================================================
// Description:
// Verilog module for general latch
// ===========================================================================
module sirv_gnrl_ltch # (
parameter DW = 32
) (
//input test_mode,
input lden,
input [DW-1:0] dnxt,
output [DW-1:0] qout
);
reg [DW-1:0] qout_r;
always @ *
begin : LTCH_PROC
if (lden == 1'b1)
qout_r <= dnxt;
end
//assign qout = test_mode ? dnxt : qout_r;
assign qout = qout_r;
`ifndef FPGA_SOURCE//{
`ifndef DISABLE_SV_ASSERTION//{
//synopsys translate_off
always_comb
begin
CHECK_THE_X_VALUE:
assert (lden !== 1'bx)
else $fatal ("\n Error: Oops, detected a X value!!! This should never happen. \n");
end
//synopsys translate_on
`endif//}
`endif//}
endmodule
變體
時鐘雙沿觸發(fā)器*
構(gòu)建一個功能類似于雙邊沿觸發(fā)觸發(fā)器的電路:
知識拓展:
DDR在原有的SDRAM的基礎(chǔ)上改進而來,SDRAM在一個CLK周期傳輸一次數(shù)據(jù),而DDR在一個CLK周期傳輸兩次數(shù)據(jù),分別在上升沿和下降沿各傳輸一次數(shù)據(jù)
- 代碼實現(xiàn):
方法一:
//方法一簡單明了,但因為觸發(fā)器Tc_to_q延時的存在,輸出波形會產(chǎn)生glitch(毛刺)
//即p、q的值還沒更新,就已經(jīng)執(zhí)行了assign q = clk? q1:q2
module top_module (
input clk,
input d,
output q
);
reg pos_q, neg_q;
always@(posedge clk)begin pos_q <= d;end
always@(negedge clk)begin c<= d;end
assign q = clk ? pos_q : neg_q;
endmodule
方法二:
//推薦使用方法二進行雙邊檢測
//方法二相較于方法一少了使用clk信號進行選擇,可以避免產(chǎn)生毛刺,但電路也會復(fù)雜
module top_module (
input clk,
input d,
output q
);
reg pos_q,neg_q;
always@(posedge clk) begin pos_q <= d ^ neg_q; end
always@(negedge clk) begin neg_q <= d ^ pos_q; end
assign q = pos_q ^ neg_q;
endmodule
驗證結(jié)果:
帶字節(jié)使能的D觸發(fā)器
創(chuàng)建16個D觸發(fā)器,有時我們僅需要修改部分觸發(fā)器中的值。字節(jié)使能信號控制當(dāng)前時鐘周期中16個寄存器中哪個字節(jié)需被修改。byteena[1]控制高字節(jié)d[15:8],而byteena[0]控制低字節(jié)d[7:0]。
resetn是一個同步,低電平有效的復(fù)位信號。
所有的D觸發(fā)器由時鐘的上升沿觸發(fā)。
代碼實現(xiàn):
module top_module (
input clk,
input resetn,
input [1:0] byteena,
input [15:0] d,
output [15:0] q
);
always@(posedge clk)begin
if(!resetn)begin
q <= 16'd0;
end else begin
if(byteena[1] == 1'b1)begin
q[15:8] <= d[15:8];
end
if(byteena[0] == 1'b1)begin
q[7:0] <= d[7:0];
end
end
end
endmodule
- 驗證結(jié)果
Synchronous active-low reset
DFF with byte enables
JK觸發(fā)器
紀(jì)念Jack Kilby,德儀工程師,諾貝爾物理學(xué)獎獲得者,發(fā)明第一塊IC的人
J-K觸發(fā)器是時鐘邊沿敏感的基本存儲單元。邏輯電路和邏輯符號如下圖所示:文章來源:http://www.zghlxwxcb.cn/news/detail-774823.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-774823.html
- 真值表
- 代碼
module top_module (
input clk,
input j,
input k,
output Q);
always@(posedge clk) begin
case({j,k})
2'b00: Q <= Q;
2'b01: Q <= 1'b0;
2'b10: Q <= 1'b1;
2'b11: Q <= ~Q;
default: Q <= Q;
endcase
end
endmodule
- 驗證結(jié)果
參考鏈接
- 《手把手教你設(shè)計CPU.RISC-V處理器》
- 鎖存器、觸發(fā)器和寄存器
- 觸發(fā)器詳解——(二)JK觸發(fā)器
- 一步一步帶你理解DDR基本原理
到了這里,關(guān)于【IC設(shè)計】時序邏輯的基礎(chǔ)—鎖存器、觸發(fā)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!