最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

【轉(zhuǎn)】RTL概念與常用RTL建模

2023-07-15 14:50 作者:ACFUN-AK  | 我要投稿


RTL概念與常用RTL建模

? ? ? ? ? ? ? ? ? ?

lzhang97 ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ?于?2021-06-11 16:00:15?發(fā)布 ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ?30756 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?收藏 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?366 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

分類(lèi)專(zhuān)欄: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Verilog學(xué)習(xí)筆記 ? ? ? ? ? ? ? ? ? ? ? ? ? ?文章標(biāo)簽: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?fpga ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?verilog ? ? ? ? ? ? ? ? ? ?

版權(quán) ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Verilog學(xué)習(xí)筆記 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?專(zhuān)欄收錄該內(nèi)容 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

7 篇文章 ? ? ? ? ? ? ? ? ? ? ? ?19 訂閱

訂閱專(zhuān)欄 ? ? ? ? ? ? ? ? ? ?

RTL和綜合的概念

RTL(Register Transfer Level,寄存器傳輸級(jí))指:不關(guān)注寄存器和組合邏輯的細(xì)節(jié)(如使用了多少邏輯門(mén),邏輯門(mén)之間的連接拓?fù)浣Y(jié)構(gòu)等),通過(guò)描述寄存器到寄存器之間的邏輯功能描述電路的HDL層次。RTL級(jí)是比門(mén)級(jí)更高的抽象層次,使用RTL級(jí)語(yǔ)言描述硬件電路一般比門(mén)級(jí)描述簡(jiǎn)單高效得多。

  • RTL級(jí)語(yǔ)言的最重要的特性是:RTL級(jí)描述是可綜合的描述層次
    綜合(Synthesize)是指將HDL語(yǔ)言、原理圖等設(shè)計(jì)輸入翻譯成由與、或、非門(mén)等基本邏輯單元組成的門(mén)級(jí)連接(網(wǎng)表),并根據(jù)設(shè)計(jì)目標(biāo)與要求(約束條件)優(yōu)化所生成的邏輯連接,輸出門(mén)級(jí)網(wǎng)表文件。RTL級(jí)綜合指將RTL級(jí)源碼翻譯并優(yōu)化為門(mén)級(jí)網(wǎng)表。

RTL級(jí)的基本要素和設(shè)計(jì)步驟

典型的RTL設(shè)計(jì)包含一下3個(gè)部分

  1. 時(shí)鐘域描述:描述所使用的所有時(shí)鐘,時(shí)鐘之間的主從與派生關(guān)系,時(shí)鐘域之間的轉(zhuǎn)換;

  2. 時(shí)序邏輯描述(寄存器描述):根據(jù)時(shí)鐘沿的變換,描述寄存器之間的數(shù)據(jù)傳輸方式;

  3. 組合邏輯描述:描述電平敏感信號(hào)的邏輯組合方式與邏輯功能。

書(shū)中推薦的設(shè)計(jì)步驟:

  1. 功能定義與模塊劃分:根據(jù)系統(tǒng)功能的定義和模塊劃分準(zhǔn)則劃分各個(gè)功能模塊;

  2. 定義所有模塊的接口:首先清晰定義每個(gè)模塊的接口,完成每個(gè)模塊的信號(hào)列表,這種思路與Modular Design(模塊化設(shè)計(jì)方法)一致,利于模塊重用、調(diào)試、修改;

  3. 設(shè)計(jì)時(shí)鐘域:根據(jù)設(shè)計(jì)的時(shí)鐘復(fù)雜程度定義時(shí)鐘之間的派生關(guān)系,分析設(shè)計(jì)中有哪些時(shí)鐘域,是否存在異步時(shí)鐘域之間的數(shù)據(jù)交換;對(duì)于PLD器件設(shè)計(jì),還需要確認(rèn)全局時(shí)鐘是否使用PLL/DLL完成時(shí)鐘的分頻、倍頻、移相等功能,哪些時(shí)鐘使用全局時(shí)鐘資源布線,哪些時(shí)鐘使用第二全局時(shí)鐘資源布線;全局時(shí)鐘的特點(diǎn)是:幾乎沒(méi)有Clock Skew(時(shí)鐘傾斜),有一定的Clock Delay(時(shí)鐘延遲),驅(qū)動(dòng)能力最強(qiáng);第二全局時(shí)鐘的特點(diǎn)是:有較小的Clock Shew,較小的Clock Delay,時(shí)鐘驅(qū)動(dòng)能力較強(qiáng);

    • 補(bǔ)充:時(shí)鐘抖動(dòng)(Clock Jitter):指芯片的某一個(gè)給定點(diǎn)上時(shí)鐘周期發(fā)生暫時(shí)性變化,使得時(shí)鐘周期在不同的周期上可能加長(zhǎng)或縮短。時(shí)鐘偏移(Clock Skew):是由于布線長(zhǎng)度及負(fù)載不同引起的,導(dǎo)致同一個(gè)時(shí)鐘信號(hào)到達(dá)相鄰兩個(gè)時(shí)序單元的時(shí)間不一致。區(qū)別:Jitter是在時(shí)鐘發(fā)生器內(nèi)部產(chǎn)生的,和晶振或者PLL內(nèi)部電路有關(guān),布線對(duì)其沒(méi)有影響。Skew是由不同布線長(zhǎng)度導(dǎo)致的不同路徑的時(shí)鐘上升沿到來(lái)的延時(shí)不同。

  4. 考慮設(shè)計(jì)的關(guān)鍵路徑:關(guān)鍵路徑是指設(shè)計(jì)中時(shí)序要求最難以滿足的路徑,設(shè)計(jì)的時(shí)序要求主要體現(xiàn)在頻率、建立時(shí)間、保持時(shí)間等時(shí)序指標(biāo)上,;在設(shè)計(jì)初期,設(shè)計(jì)者可以根據(jù)系統(tǒng)的頻率要求,粗略的分析出設(shè)計(jì)的時(shí)序難點(diǎn)(如最高頻率路徑、計(jì)數(shù)器的最低位、包含復(fù)雜組合邏輯的時(shí)序路徑等),通過(guò)一些時(shí)序優(yōu)化手段(如Pipeline、Retiming、邏輯復(fù)制等)從代碼上緩解設(shè)計(jì)的時(shí)序壓力,這種方法以但依靠綜合與布線工具的自動(dòng)優(yōu)化有效的多;

  5. 頂層設(shè)計(jì):RTL設(shè)計(jì)推薦使用自頂而下的設(shè)計(jì)方法,因?yàn)檫@種設(shè)計(jì)方法與模塊規(guī)劃的順序一致,而且更有利于進(jìn)行Modular Design,可以并行開(kāi)展設(shè)計(jì)工作,提高模塊復(fù)用率;

  6. FSM設(shè)計(jì):FSM是邏輯設(shè)計(jì)最重要的內(nèi)容之一;

  7. 時(shí)序邏輯設(shè)計(jì):首先根據(jù)時(shí)鐘域規(guī)劃好寄存器組,然后描述各個(gè)寄存器組之間的數(shù)據(jù)傳輸方式;

  8. 組合邏輯設(shè)計(jì):一般來(lái)說(shuō),大段的組合邏輯最好與時(shí)序邏輯分開(kāi)描述,這樣更有利于時(shí)序約束和時(shí)序分析,使綜合器和布局布線器達(dá)到更好的優(yōu)化效果。

常用RTL級(jí)建模

非阻塞賦值、阻塞賦值、連續(xù)賦值

  1. 對(duì)于時(shí)序邏輯,即always塊的敏感信號(hào)列表為邊沿敏感信號(hào),統(tǒng)一使用非阻塞賦值“<=”;

  2. 對(duì)于always塊敏感信號(hào)列表為電平敏感的組合邏輯,統(tǒng)一使用阻塞賦值“=”;

  3. 對(duì)于assign關(guān)鍵字描述的組合邏輯,統(tǒng)一使用阻塞賦值“=”,變量被定義為wire型信號(hào)。

寄存器電路建模

寄存器和組合邏輯是數(shù)字邏輯電路的兩大基本要素,寄存器一般和同步時(shí)序邏輯關(guān)聯(lián),其特點(diǎn)是僅當(dāng)時(shí)鐘的邊沿到達(dá)時(shí),才有可能發(fā)生輸出的改變。

  1. 寄存器變量聲明:寄存器定義為reg型,但要注意的是,反之不一定成立;

  2. 時(shí)鐘輸入:在每個(gè)時(shí)鐘的正沿或負(fù)沿對(duì)數(shù)據(jù)從進(jìn)行處理。

  3. 異步復(fù)位/置位:絕大多數(shù)目標(biāo)器件的寄存器模型都包含異步復(fù)位/置位端;

  4. 同步復(fù)位/置位:任何寄存器都可以實(shí)現(xiàn)同步復(fù)位/置位功能;

  5. 同時(shí)使用時(shí)鐘上升沿和下降沿的問(wèn)題:有時(shí)因?yàn)閿?shù)據(jù)采樣或者調(diào)整數(shù)據(jù)相位等需求,設(shè)計(jì)者會(huì)在一個(gè)always的敏感信號(hào)列表中同時(shí)使用時(shí)鐘的posedge和negedge,或者在兩個(gè)always的敏感信號(hào)列表中分別使用posedge和nesedge對(duì)某個(gè)寄存器電路操作;這兩種描述下,時(shí)鐘上升沿和下降沿到來(lái)時(shí),寄存器電路都會(huì)做相應(yīng)的操作,這個(gè)雙邊沿電路等同于使用了原來(lái)時(shí)鐘的倍頻時(shí)鐘的單邊沿操作電路,這種操作是不推薦的;芯片內(nèi)部的PLL/DLL和一些時(shí)鐘電路往往只能對(duì)一個(gè)邊沿有非常好的指標(biāo),而另一個(gè)沿的抖動(dòng)、偏移、斜率等指標(biāo)不見(jiàn)得非常優(yōu)化,有時(shí)同時(shí)使用時(shí)鐘的正負(fù)邊沿會(huì)因?yàn)闀r(shí)鐘的抖動(dòng)、偏斜、占空比、斜率等問(wèn)題造成一定的性能惡化;一般推薦將原時(shí)鐘通過(guò)PLL/DLL倍頻,然后使用倍頻時(shí)鐘的單邊沿進(jìn)行操作。

組合邏輯建模

always 模塊的敏感信號(hào)列表為電平敏感信號(hào)的組合邏輯電路

always模塊的敏感信號(hào)列表為所有判定條件和輸入信號(hào),在使用這種結(jié)構(gòu)描述組合邏輯時(shí)一定要將敏感列表列寫(xiě)完整。在always塊中可以使用高級(jí)編程語(yǔ)言,使用阻塞賦值“=”,雖然信號(hào)被定義位reg型,但最終綜合實(shí)現(xiàn)結(jié)果并不是寄存器,而是組合邏輯,定義為reg型是純語(yǔ)法需要。

assign 等語(yǔ)句描述的組合邏輯電路

這種形式描述組合邏輯電路適用于描述那些相對(duì)簡(jiǎn)單的組合邏輯,信號(hào)一般被定義位wire型。

雙向端口與三態(tài)信號(hào)建模

所有的雙向總線應(yīng)該在頂層模塊定義為三態(tài)信號(hào),禁止在頂層以外的其他子層次定義雙向端口。為了避免仿真和綜合實(shí)現(xiàn)結(jié)果不一致,并便于維護(hù),強(qiáng)烈建議僅在頂層定義雙向總線和例化三態(tài)信號(hào),禁止在除頂層以外的其他層次賦值高阻態(tài)"Z",在頂層將雙向信號(hào)分為輸入和輸出信號(hào)兩種類(lèi)型,然后根據(jù)需要分別傳遞到不同的子模塊中,這樣做的另一個(gè)好處是便于描述仿真激勵(lì)。

module bibus (clk, rst, sel, data_bus, addr); input ? ? ? clk, rst, sel; input [7:0] addr; inout [7:0] data_bus; wire [7:0] data_in, data_out; assign data_in = data_bus; assign data_bus = (sel) ? data_out : 8'bZ; decode decode_inst (.clock (clk), ? ? ? ? ? ? ? ? ? ?.reset (rst), ? ? ? ? ? ? ? ? ? ?.data_bus_in (data_in), ? ? ? ? ? ? ? ? ? ?.addr_bus (addr), ? ? ? ? ? ? ? ? ? ?.data_bus_out (data_out) ? ? ? ? ? ? ? ? ? ?); endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16


如果三態(tài)總線的使能關(guān)系比較復(fù)雜,不是單一信號(hào),此時(shí)可以使用嵌套的問(wèn)號(hào)表達(dá)式,或者使用case語(yǔ)句描述。

  • 嵌套的問(wèn)號(hào)表達(dá)式

module complex_bibus (clk, rst, sel1, sel2, sel3, data_bus, addr); input ? ? ? clk, rst; input ? ? ? sel1, sel2, sel3; input [7:0] addr; inout [7:0] data_bus; wire [7:0] data_in; //wire [7:0] data_out; //use wire type wire [7:0] decode_out; wire [7:0] cnt_out; assign data_in = data_bus; assign data_bus = (sel1)? decode_out : ((sel2)? cnt_out : ((sel3)? 8'b11111111: 8'bZZZZZZZZ)); decode decode_inst (.clock (clk), ? ? ? ? ? ? ? ? ? ?.reset (rst), ? ? ? ? ? ? ? ? ? ?.data_bus_in (data_in), ? ? ? ? ? ? ? ? ? ?.addr_bus (addr), ? ? ? ? ? ? ? ? ? ?.data_bus_out (decode_out) ? ? ? ? ? ? ? ? ? ?); ? ? ? ? ? ? ? ? ? ? counter counter_inst (.clock (clk), ? ? ? ? ? ? ? ? ? ?.reset (rst), ? ? ? ? ? ? ? ? ? ?.data_bus_in (data_in), ? ? ? ? ? ? ? ? ? ?.cnt_out (cnt_out) ? ? ? ? ? ? ? ? ? ?); ? ? ? ? ? ? endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27


  • case語(yǔ)句(如果使能情況比較復(fù)雜,通過(guò)case進(jìn)行羅列,更清晰)

input sel1, sel2, sel3; input [7:0] addr; inout [7:0] data_bus; wire [7:0] data_in; reg ?[7:0] data_out; //use reg type, but not registers wire [7:0] decode_out; wire [7:0] cnt_out; assign data_in = data_bus; decode decode_inst (.clock (clk), ? ? ? ? ? ? ? ? ? ?.reset (rst), ? ? ? ? ? ? ? ? ? ?.data_bus_in (data_in), ? ? ? ? ? ? ? ? ? ?.addr_bus (addr), ? ? ? ? ? ? ? ? ? ?.data_bus_out (decode_out) ? ? ? ? ? ? ? ? ? ?); ? ? ? ? ? ? ? ? ? ? counter counter_inst (.clock (clk), ? ? ? ? ? ? ? ? ? ?.reset (rst), ? ? ? ? ? ? ? ? ? ?.data_bus_in (data_in), ? ? ? ? ? ? ? ? ? ?.cnt_out (cnt_out) ? ? ? ? ? ? ? ? ? ?); ? ? ? ? ? ? ? ? ? ? always @ (decode_out or cnt_out or sel1 or sel2 or sel3) ? ?begin ? ? ? case ({sel1, sel2, sel3}) ? ? ? ? 3'b100: ?data_out = decode_out; ? ? ? ? 3'b010: ?data_out = cnt_out; ? ? ? ? 3'b001: ?data_out = 8'b11111111; ? ? ? ? default: data_out = 8'bZZZZZZZZ; ? ? ? endcase ? ?end assign data_bus = data_out; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35


mux 建模

簡(jiǎn)單的使用assign和?,相對(duì)復(fù)雜的使用always和if…else、case等條件判斷語(yǔ)句建模。

存儲(chǔ)器建模

邏輯電路設(shè)計(jì)經(jīng)常使用一些單口RAM、雙口RAM和ROM等存儲(chǔ)器。Verilog 語(yǔ)法中基本的存儲(chǔ)單元定義格式為:

reg [datawidth] MemoryName [addresswidth]

  • 1


如定義一個(gè)數(shù)據(jù)位寬為8bit,地址為63為的RAM8x64:

reg [7:0] RAM8x64 [0:63];

  • 1


在使用存儲(chǔ)單元時(shí),不能直接操作存儲(chǔ)器某地址的某位,需要先將存儲(chǔ)單元賦值給某個(gè)寄存器,然后再對(duì)該存儲(chǔ)器的某位進(jìn)行相關(guān)操作。

module ram_basic (clk, CS, WR, addr, data_in, data_out, en); input ? ? ? ? clk; input ? ? ? ? CS; ?//CS = 1, RAM enable input ? ? ? ? WR; ?//WR =1 then WRite enable; WR = 0 then read enable input ? ? ? ? en; ?//data_out enable, convert the data sequency input ?[5:0] ?addr; input ?[7:0] ?data_in; output [7:0] ?data_out; reg [7:0] RAM8x64 [0:63]; reg [7:0] mem_data; always @ (posedge clk) ? ?if (WR && CS) //WRite ? ? ? ?RAM8x64 [addr] <= data_in [7:0]; ? ?else if (~WR && CS ) // read ? ? ? ?mem_data <= RAM8x64 [addr]; ? ? ? ? assign data_out = (en)? mem_data[7:0] : {~mem_data[7], mem_data[6:0]}; endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20


  • FPGA中內(nèi)嵌的RAM資源分為兩類(lèi):塊RAM(Block RAM)資源和分布式RAM(Distributed RAM)資源,BRAM作為FPGA內(nèi)部硬件資源,使用時(shí)不會(huì)占用其他邏輯資源,分布式RAM是通過(guò)查找表和觸發(fā)器實(shí)現(xiàn)的RAM結(jié)構(gòu)。

  • 使用RAM等資源時(shí)通常不使用這種Verilog語(yǔ)言進(jìn)行建模,一般使用廠商提供IP核通過(guò)GUI完成相關(guān)參數(shù)配置,并生成相關(guān)IP。

簡(jiǎn)單的時(shí)鐘分頻電路

  • 偶數(shù)分頻十分簡(jiǎn)單,只需要用高速時(shí)鐘驅(qū)動(dòng)一個(gè)同步計(jì)數(shù)器;

module clk_div_phase (rst, clk_200K, clk_100K, clk_50K, clk_25K); input ? ? ? ?clk_200K; input ? ? ? ?rst; output ? ? ? clk_100K, clk_50K, clk_25K; wire ? ? ? ? clk_100K, clk_50K, clk_25K; reg [2:0] cnt; ? always @ (posedge clk_200K or negedge rst) ? if (!rst) ? ? ?cnt <= 3'b000; ? else ? ? ?cnt <= cnt + 1; assign clk_100K = ~cnt [0];//2分頻 assign clk_50K ?= ~cnt [1];//4分頻 assign clk_25K ?= ~cnt [2];//8分頻 endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19


上例通過(guò)對(duì)計(jì)數(shù)器每個(gè)bit的反向,完成了所有分頻后的時(shí)鐘調(diào)整,保證了3個(gè)分頻后時(shí)鐘的相位嚴(yán)格同相,也與源時(shí)鐘同相,有共同的上升沿。

  • 奇數(shù)分頻

module clk_3div (clk,reset,clk_out); input clk, reset; output clk_out; reg[1:0] state; reg clk1; always @(posedge clk or negedge reset) if(!reset) ? ?state<=2'b00; else ? ?case(state) ? ? ? ?2'b00:state<=2'b01; ? ? ? ?2'b01:state<=2'b11; ? ? ? ?2'b11:state<=2'b00; ? ? ? ?default:state<=2'b00; ? ?endcase always @(negedge clk or negedge reset) ? ?if(!reset) ? ? ? ?clk1<=1'b0; ? ?else ? ? ? ?clk1<=state[0]; assign clk_out=state[0]&clk1; endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24


串/并轉(zhuǎn)換建模

根據(jù)數(shù)據(jù)的排序和數(shù)量的要求,可以選用移位寄存器、RAM等實(shí)現(xiàn);對(duì)于數(shù)量比較小的設(shè)計(jì)可以采用移位寄存器完成串/并轉(zhuǎn)換(串轉(zhuǎn)并:先移位,再并行輸出;并轉(zhuǎn)串:先加載并行數(shù)據(jù),再移位輸出);對(duì)于排列順序有規(guī)律的串/并轉(zhuǎn)換,可以使用case語(yǔ)句進(jìn)行判斷實(shí)現(xiàn);對(duì)于復(fù)雜的串/并轉(zhuǎn)換,還可以用狀態(tài)機(jī)實(shí)現(xiàn)。

同步復(fù)位與異步復(fù)位

同步復(fù)位

建模

module syn_rst (clk, rst_, cnt1, cnt2); input ? ? ? ?clk; input ? ? ? ?rst_; output [4:0] cnt1 , cnt2; reg ? ?[4:0] cnt1 , cnt2; always @ (posedge clk) ? if (!rst_) ? ? ?begin ? ? ? ?cnt1 <= 4'b0; ? ? ? ?cnt2 <= 4'b0; ? ? ?end ? else ? ? ?begin ? ? ? ?if (cnt1 < 2'b11) ? ? ? ? ? ?cnt1 <= cnt1 + 1; ? ? ? ?else ? ? ? ? ? ?cnt1 <= cnt1; ? ? ? ? ? ? ? ? ? ? ? ?cnt2 <= cnt1 - 1; ? ? ? ? ? ?end endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21


很多目標(biāo)器件的觸發(fā)器本身本身并不包含同步復(fù)位端口,則同步復(fù)位可以通過(guò)下圖結(jié)構(gòu)實(shí)現(xiàn):

優(yōu)點(diǎn)

  • 同步復(fù)位利于基于周期機(jī)制的仿真器仿真;

  • 使用同步復(fù)位可以設(shè)計(jì)100%的同步時(shí)序電路,利于時(shí)序分析,其綜合結(jié)果的頻率往往更高;

  • 同步復(fù)位僅在時(shí)鐘的上升沿生效,可以有效的避免因復(fù)位電路毛刺造成的亞穩(wěn)態(tài)和錯(cuò)誤;在進(jìn)行復(fù)位和釋放復(fù)位信號(hào)時(shí),都是僅當(dāng)時(shí)鐘沿采到復(fù)位電平變化時(shí)才進(jìn)行相關(guān)操作,如果復(fù)位信號(hào)樹(shù)的組合邏輯出現(xiàn)了某些毛刺,此時(shí)時(shí)鐘邊沿采集到毛刺的概率非常低,通過(guò)時(shí)鐘沿采樣,可以十分有效地過(guò)濾復(fù)位電路的組合邏輯毛刺,增強(qiáng)電路的穩(wěn)定性。

缺點(diǎn)

  • 很多目標(biāo)器件的觸發(fā)器本身不包含同步復(fù)位端口,使用同步復(fù)位會(huì)增加很多邏輯資源;

  • 同步復(fù)位的最大問(wèn)題在于必須保證復(fù)位信號(hào)的有效時(shí)間足夠長(zhǎng),才能保證所有觸發(fā)器都有效復(fù)位,所以同步復(fù)位信號(hào)的持續(xù)時(shí)間必須大于設(shè)計(jì)的最長(zhǎng)時(shí)鐘周期,以保證所有時(shí)鐘的有效沿都能采樣到同步復(fù)位信號(hào)。

  • 其實(shí)僅僅保證同步復(fù)位信號(hào)的持續(xù)時(shí)間大于最慢的時(shí)鐘周期還是不夠的,設(shè)計(jì)中還要考慮到同步復(fù)位信號(hào)樹(shù)通過(guò)所有組合邏輯路徑的延時(shí)以及由于時(shí)鐘布線產(chǎn)生的偏斜(skew),只有同步復(fù)位大于時(shí)鐘最大周期加上同步信號(hào)穿過(guò)的組合邏輯路徑延時(shí)加上時(shí)鐘偏斜時(shí),才能保證同步復(fù)位可靠、徹底。

  • 上圖中,假設(shè)同步復(fù)位邏輯樹(shù)組合邏輯的延時(shí)為t1,復(fù)位信號(hào)傳播路徑的最大延遲為t2,最慢時(shí)鐘的周期為Period max,時(shí)鐘的skew為clk2-clk1,則同步復(fù)位的周期Tsys_rst應(yīng)滿足:Tsys_rst > Period max + (clk2-clk1) + t1 + t2;

異步復(fù)位

建模

module asyn_rst (clk, rst_, cnt1, cnt2); input ? ? ? ?clk; input ? ? ? ?rst_; output [4:0] cnt1 , cnt2; reg ? ?[4:0] cnt1 , cnt2; always @ (posedge clk or negedge rst_) ? if (!rst_) ? ? ?begin ? ? ? ?cnt1 <= 4'b0; ? ? ? ?cnt2 <= 4'b0; ? ? ?end ? else ? ? ?begin ? ? ? ?if (cnt1 < 2'b11) ? ? ? ? ? ?cnt1 <= cnt1 + 1; ? ? ? ?else ? ? ? ? ? ?cnt1 <= cnt1; ? ? ? ? ? ? ? ? ? ? ? ?cnt2 <= cnt1 - 1; ? ? ? ? ? ?end endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21


優(yōu)點(diǎn)

  • 多數(shù)器件包含異步復(fù)位端口,異步復(fù)位會(huì)節(jié)約邏輯資源;

  • 異步復(fù)位設(shè)計(jì)簡(jiǎn)單;

  • 大多數(shù)FPGA,都有專(zhuān)用的全局復(fù)位/置位資源(GSR,Globe Set Reset),使用GSR資源,異步復(fù)位達(dá)到所有寄存器的偏斜(skew)最小。

缺點(diǎn)

  • 異步復(fù)位的作用和釋放與時(shí)鐘沿沒(méi)有直接關(guān)系,在異步復(fù)位神效時(shí)問(wèn)題并不明顯,但當(dāng)異步復(fù)位釋放時(shí),如果異步復(fù)位釋放時(shí)間和時(shí)鐘的有效沿到達(dá)時(shí)間幾乎一致,則容易造成觸發(fā)器輸出亞穩(wěn)態(tài),造成邏輯錯(cuò)誤;

  • 如果異步復(fù)位邏輯樹(shù)的組合邏輯產(chǎn)生了毛刺,則毛刺的有效沿會(huì)使觸發(fā)器誤復(fù)位,造成邏輯錯(cuò)誤。

推薦的復(fù)位電路設(shè)計(jì)方式——異步復(fù)位,同步釋放

  • 推薦的復(fù)位電路設(shè)計(jì)方式是異步復(fù)位,同步釋放,這種方式可以有效的繼承異步復(fù)位設(shè)計(jì)簡(jiǎn)單的優(yōu)勢(shì),并克服異步復(fù)位的風(fēng)險(xiǎn)與缺陷;相較于純粹的異步復(fù)位,降低了異步復(fù)位信號(hào)釋放導(dǎo)致的亞穩(wěn)態(tài)的可能性,相較于同步復(fù)位,能夠識(shí)別到同步復(fù)位中檢測(cè)不到的復(fù)位信號(hào)。

  • 在FPGA中使用異步復(fù)位,同步釋放可以節(jié)約器件資源,并獲得穩(wěn)定可靠的復(fù)位效果。

  • 異步復(fù)位同步釋放,既能很快的檢測(cè)到復(fù)位信號(hào),不需要復(fù)位保持超過(guò)一個(gè)時(shí)鐘周期,又能解決釋放時(shí)的亞穩(wěn)態(tài)問(wèn)題(降低亞穩(wěn)態(tài)發(fā)生的概率)。

  • 異步復(fù)位,同步釋放的具體設(shè)計(jì)方法很多,關(guān)鍵是如何保證同步地釋放復(fù)位信號(hào),本例舉例的方法是在復(fù)位信號(hào)釋放時(shí),用系統(tǒng)時(shí)鐘采樣后再將復(fù)位信號(hào)送到寄存器的異步復(fù)位端。

  • 所謂“異步復(fù)位”是針對(duì)D觸發(fā)器的復(fù)位端口,它是異步的,但是設(shè)計(jì)中已經(jīng)同步了異步復(fù)位信號(hào),所以筆者(Crazybingo)認(rèn)為這只是某種意義上的“異步復(fù)位”。

  • 所謂“同步釋放”,實(shí)際上是由于我們?cè)O(shè)計(jì)了同步邏輯電路,外部復(fù)位信號(hào)不會(huì)在出現(xiàn)釋放時(shí)與clk信號(hào)競(jìng)爭(zhēng),整個(gè)系統(tǒng)將與全局時(shí)鐘clk信號(hào)同步。

  • 使用時(shí)鐘將外部輸入的異步復(fù)位信號(hào)寄存一個(gè)節(jié)拍后,再送到觸發(fā)器異步復(fù)位端口的設(shè)計(jì)方法的另一個(gè)好處在于:做STA(靜態(tài)時(shí)序分析)分析時(shí),時(shí)序工具會(huì)自動(dòng)檢查同步后的異步復(fù)位信號(hào)和時(shí)鐘的到達(dá)(Recovery)/撤銷(xiāo)(Removal)時(shí)間關(guān)系,如果因布線造成的skew導(dǎo)致該到達(dá)/撤銷(xiāo)時(shí)間不能滿足,STA工具會(huì)上報(bào)該路徑,幫助設(shè)計(jì)者進(jìn)一步分析問(wèn)題。

module system_ctrl ? ? //異步復(fù)位,同步釋放——by 特權(quán)同學(xué) //==================<端口>================================================== ( //globel clock ---------------------------------- input ?wire ? ? ? ? ? ? ? ? clk ? ? ? ? ? ? ? ? , //時(shí)鐘,50Mhz input ?wire ? ? ? ? ? ? ? ? rst_n ? ? ? ? ? ? ? , //復(fù)位,低電平有效 //user interface -------------------------------- input ?wire ? ? ? ? ? ? ? ? a ? ? ? ? ? ? ? ? ? , //輸入信號(hào) output reg ? ? ? ? ? ? ? ? ?b ? ? ? ? ? ? ? ? ? ? //輸出信號(hào) ); //========================================================================== //== ? ?異步復(fù)位的同步化設(shè)計(jì) //========================================================================== reg ? ? ? ?sys_rst_n_r; reg ? ? ? ?sys_rst_n; always @(posedge clk or negedge rst_n) begin ? ?if(!rst_n) begin ? ? ? ?sys_rst_n_r <= 1'b0; ? ? ? ?sys_rst_n ? <= 1'b0; ? ?end ? ?else begin ? ? ? ?sys_rst_n_r <= 1'b1; ? ? ? ?sys_rst_n ? <= sys_rst_n_r; //注意這里的rst_sync_n才是我們真正對(duì)系統(tǒng)輸出的復(fù)位信號(hào) ? ?end end always @(posedge clk or negedge sys_rst_n) ? //注意這里將同步后的信號(hào)仍作為異步復(fù)位信號(hào)進(jìn)行處理,Altera推薦 begin ? ?if(!sys_rst_n) ? ? ? ?b <= 0; ? ?else ? ? ? ?b <= a; end endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35

  • 36

  • 37

  • 38


上圖是Altera推薦的異步復(fù)位,同步釋放示意圖

module reset_gen ( output rst_sync_n, input clk, rst_async_n); ?//此模塊對(duì)應(yīng)前一個(gè)黃框中的邏輯,輸出信號(hào)在后級(jí)電路中仍作為異步復(fù)位信號(hào)進(jìn)行處理 reg rst_s1, rst_s2; wire rst_sync_n ; always @ (posedge clk, posedge rst_async_n) ? ?if (rst_async_n) ? ? ? ? begin ? ? ? ? ? ?rst_s1 <= 1'b0; ? ? ? ? ? ?rst_s2 <= 1'b0; ? ? ? ?end ? ?else ? ? ? ?begin ? ? ? ? ? ?rst_s1 <= 1'b1; //針對(duì)Altera FPGA ? ? ? ? ? ?rst_s2 <= rst_s1; ? ? ? ?end assign rst_sync_n = rst_s2; //注意這里的rst_sync_n才是我們真正對(duì)系統(tǒng)輸出的復(fù)位信號(hào) endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19


Xilinx

Xilinx的FPGA,高電平復(fù)位其Filp-Flop同時(shí)支持同步/異步復(fù)位,復(fù)位準(zhǔn)則:

  1. 盡量少使用復(fù)位,特別是少用全局復(fù)位,能不用復(fù)位就不用,一定要用復(fù)位的使用局部復(fù)位;

  2. 如果必須要復(fù)位,在同步和異步復(fù)位上,則盡量使用同步復(fù)位(BRAM DSP48不支持異步復(fù)位),一定要用異步復(fù)位的地方,采用“異步復(fù)位、同步釋放”;

  3. 復(fù)位電平選擇高電平復(fù)位;

只要存在復(fù)位都會(huì)增加布局布線的負(fù)擔(dān),因?yàn)閺?fù)位會(huì)像時(shí)鐘一樣連接到每一個(gè)寄存器上,是相當(dāng)復(fù)雜的工程,會(huì)增加時(shí)序收斂的難度。

對(duì)于同一個(gè)觸發(fā)器邏輯,因?yàn)橥瑫r(shí)支持異步和同步復(fù)位,所以異步復(fù)位并不會(huì)節(jié)省資源;對(duì)于其他的資源,比如 DSP48 等,同步復(fù)位更加節(jié)省資源。

首先,對(duì)于 DSP48,其內(nèi)部還帶有一些寄存器(只支持同步復(fù)位),如果使用異步復(fù)位,則會(huì)額外使用外部 Slice 中帶異步復(fù)位的寄存器,而使用同步復(fù)位時(shí),可以利用 DSP48 內(nèi)部的寄存器;Xilinx 的 FPGA,對(duì)于 DSP48、BRAM 資源,使用同步復(fù)位比異步復(fù)位更節(jié)省資源。

對(duì)于高電平復(fù)位,使用異步復(fù)位同步釋放,則第一個(gè)寄存器的 D 輸入是 0,這里使用了 4 個(gè)觸發(fā)器打拍同步。The number of flip-flops in the chain determines the minimum duration of the reset pulse issued to the localized network.

always @(posedge clk or posedge rst_async) begin ? ?if(rst_async == 1'b1) begin ? ? ? ?rst_sync_reg1 <= 1'b1; //Xilinx的FPGA高電平復(fù)位 ? ? ? ?rst_sync_reg2 <= 1'b1; ? ? ? ?rst_sync_reg3 <= 1'b1; ? ? ? ?rst_sync_reg4 <= 1'b1; ? ?end ? ?else begin ? ? ? ?rst_sync_reg1 <= 1'b0; ? ? ? ?rst_sync_reg2 <= rst_sync_reg1; ? ? ? ?rst_sync_reg3 <= rst_sync_reg2; ? ? ? ?rst_sync_reg4 <= rst_sync_reg3; ? ?end end ? wire sys_rst; assign sys_rst = rst_sync_reg4; always @(posedge clk) ? ?//同步后的信號(hào)當(dāng)作同步復(fù)位信號(hào)處理 begin ? ?if(sys_rst == 1'b1) begin ? ? ? ?data_out_rst_async <= 1'b0; ? ?end ? ?else begin ? ? ? ?data_out_rst_async <= a & b & c & d; ? ?end end

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28


同步后的信號(hào)如果作為同步復(fù)位信號(hào)進(jìn)行處理:

rst_async異步復(fù)位一旦給出,用于同步的4個(gè)寄存器rst_sync_reg1~4立刻輸出高電平“1”,在下一個(gè)時(shí)鐘上升沿檢測(cè)到同步復(fù)位并將輸出data_out_rst_async復(fù)位;

異步復(fù)位信號(hào)釋放后,經(jīng)過(guò)同步的sys_rst經(jīng)過(guò)一定周期后在時(shí)鐘邊沿同步釋放;

同步后的信號(hào)如果作為異步復(fù)位信號(hào)進(jìn)行處理:

區(qū)別在于異步復(fù)位信號(hào)rst_async一旦產(chǎn)生,輸出立刻復(fù)位,且同樣是同步釋放,好像這種處理才更符合異步復(fù)位、同步釋放。

那么為什么Xilinx白皮書(shū)還是將sys_rst按照同步復(fù)位去做的呢? 綜合考慮可能有這樣的因素:

  1. 當(dāng)作同步復(fù)位的差別只在于復(fù)位時(shí)間會(huì)稍晚一些,要在時(shí)鐘的下一個(gè)邊沿檢測(cè)到,但是還是能夠識(shí)別到輸入的rst_async異步復(fù)位信號(hào),所以從復(fù)位角度來(lái)說(shuō),都能夠后實(shí)現(xiàn)復(fù)位效果;

  2. 根據(jù)Xilinx復(fù)位準(zhǔn)則,我們知道同步復(fù)位相比異步復(fù)位有很多好處,具體參見(jiàn):Xilinx FPGA 復(fù)位策略白皮書(shū)(WP272) 公眾號(hào)-FPGA探索者做了翻譯可以參考,既然兩者對(duì)后級(jí)復(fù)位沒(méi)有功能上的差別,那么優(yōu)先選擇同步復(fù)位;

Xilinx 推薦的復(fù)位準(zhǔn)則:

  1. 盡量少使用復(fù)位,特別是少用全局復(fù)位,能不用復(fù)位就不用,一定要用復(fù)位的使用局部復(fù)位;

  2. 如果必須要復(fù)位,在同步和異步復(fù)位上,則盡量使用同步復(fù)位,一定要用異步復(fù)位的地方,采用“異步復(fù)位、同步釋放”;

  3. 復(fù)位電平選擇高電平復(fù)位;

Altera

Altera的FPGA,低電平復(fù)位,其觸發(fā)器只有異步復(fù)位端口,所以如果想要用同步復(fù)位,需要額外的資源來(lái)實(shí)現(xiàn),這也是“異步復(fù)位節(jié)省資源”這一說(shuō)法的原因。

具體電路及代碼見(jiàn)上文

用case和if…else建模

可綜合的Verilog語(yǔ)法子集

在RTL建模時(shí),使用可綜合的Verilog語(yǔ)法是整個(gè)Verilog語(yǔ)法中的非常小的一個(gè)子集。其實(shí)可綜合的Verilog常用關(guān)鍵字非常有限,這恰恰體現(xiàn)了Verilog語(yǔ)言是硬件描述語(yǔ)言的本質(zhì),Verilog作為HDL,其本質(zhì)在于把電路流暢、合理的轉(zhuǎn)換為語(yǔ)言形式,而使用較少的一些關(guān)鍵字就可以有效的將電路轉(zhuǎn)換到可綜合的RTL語(yǔ)言結(jié)構(gòu)。
常用的RTL語(yǔ)法結(jié)構(gòu)列舉:

  • 模塊聲明:module…endmodule;

  • 端口聲明:input、outpu、inout;

  • 信號(hào)類(lèi)型:wire、reg、tri等,integer通常用于for語(yǔ)句中索引;

  • 參數(shù)定義:parameter

  • 運(yùn)算操作符:邏輯操作、移位操作、算術(shù)操作;

  • 比較判斷:case…endcase(casex/casez)、if…else;

  • 連續(xù)賦值:assign、問(wèn)號(hào)表達(dá)式

  • always模塊:建模時(shí)序和組合邏輯

  • 語(yǔ)法分割符:begin…end

  • 任務(wù)定義:task…endtask

  • 循環(huán)語(yǔ)句:for

CPU讀/寫(xiě)PLD寄存器接口設(shè)計(jì)實(shí)例

  • CS:片選(低有效、input)

  • OE:輸出使能信號(hào)(低有效、input)

  • WR:讀/寫(xiě)指示,低-讀數(shù)據(jù),高-寫(xiě)數(shù)據(jù)(input)

  • Address:地址總線(input)

  • Data:雙向數(shù)據(jù)總線(inout)

地址譯碼器電路

module decode (CS_, OE_, WR_, Addr, my_wr, my_rd, CS_reg1, CS_reg2, CS_reg3); input ? ? ? ?CS_, OE_, WR_; input ?[7:0] Addr; output ? ? ? my_wr, my_rd; output ? ? ? CS_reg1, CS_reg2, CS_reg3; reg ? ? ? ? ?CS_reg1, CS_reg2, CS_reg3; assign my_wr = (!WR_) && (!CS_) && (!OE_); assign my_rd = (WR_) ?&& (!CS_) && (!OE_); always @ (Addr or CS_) ?if (!CS_) ? ? begin ? ? ? case (Addr) ? ? ? ? ?8'b 11110000: CS_reg1 <= 1'b1; ? ? ? ? ?8'b 00001111: CS_reg2 <= 1'b1; ? ? ? ? ?8'b 10100010: CS_reg3 <= 1'b1; ? ? ? ? ?default: ? ? begin ? ? ? ? ? ? ? ? ? ? ? ? ? CS_reg1 <= 1'b0; ? ? ? ? ? ? ? ? ? ? ? ? ? CS_reg2 <= 1'b0; ? ? ? ? ? ? ? ? ? ? ? ? ? CS_reg3 <= 1'b0; ? ? ? ? ? ? ? ? ? ? ? end ? ? ? endcase ? ? end ? ? ? ? ? ? ? endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30


讀寄存器

module read_reg (clk, rst, data_out, ?my_rd, CS_reg1, CS_reg2, CS_reg3, reg1, reg2, reg3); input ? ? ? ?clk, rst, my_rd, CS_reg1, CS_reg2, CS_reg3; input ?[7:0] reg1, reg2, reg3; output [7:0] data_out; reg ? ?[7:0] data_out; ?always @ (posedge clk or negedge rst) ? ? ?if (!rst) ? ? ? ? data_out <= 8'b0; ? ? ?else ? ? ? ? begin ? ? ? ? ? ?if (my_rd) ? ? ? ? ? ? ? ?begin ? ? ? ? ? ? ? ? ? ? if (CS_reg1) ? ? ? ? ? ? ? ? ? ? ? ? data_out <= reg1; ? ? ? ? ? ? ? ? ? ? else if (CS_reg2) ? ? ? ? ? ? ? ? ? ? ? ? data_out <= reg2; ? ? ? ? ? ? ? ? ? ? else if (CS_reg3) ? ? ? ? ? ? ? ? ? ? ? ? data_out <= reg3; ? ? ? ? ? ? ? ?end ? ? ? ? ? ?else ? ? ? ? ? ? ? ?data_out <= 8'b0; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? end endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27


寫(xiě)寄存器

module write_reg (clk, rst, data_in, ?my_wr, CS_reg1, CS_reg2, CS_reg3, reg1, reg2, reg3); input ? ? ? ?clk, rst, my_wr, CS_reg1, CS_reg2, CS_reg3; input ?[7:0] data_in; output [7:0] reg1, reg2, reg3; reg ? ?[7:0] reg1, reg2, reg3; ?always @ (posedge clk or negedge rst) ? ? ?if (!rst) ? ? ? ? begin ? ? ? ? ? ? ?reg1 <= 8'b0; ? ? ? ? ? ? ?reg2 <= 8'b0; ? ? ? ? ? ? ?reg3 <= 8'b0; ? ? ? ? ? ? ? ? end ? ? ?else ? ? ? ? begin ? ? ? ? ? ?if (my_wr) ? ? ? ? ? ? ? ?begin ? ? ? ? ? ? ? ? ? ? if (CS_reg1) ? ? ? ? ? ? ? ? ? ? ? ? reg1 <= data_in; ? ? ? ? ? ? ? ? ? ? else if (CS_reg2) ? ? ? ? ? ? ? ? ? ? ? ? reg2 <= data_in; ? ? ? ? ? ? ? ? ? ? else if (CS_reg3) ? ? ? ? ? ? ? ? ? ? ? ? reg3 <= data_in; ? ? ? ? ? ? ? ?end ? ? ? ? ? ?else ? ? ? ? ? ? ? ?begin ? ? ? ? ? ? ? ? ? ? reg1 <= reg1; ? ? ? ? ? ? ? ? ? ? reg2 <= reg2; ? ? ? ? ? ? ? ? ? ? reg3 <= reg3; ? ? ? ? ? ? ? ?end ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? end endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35


頂層

module top (clk_cpu, rst, CS_, OE_, WR_, Addr, data_bus); input ? clk_cpu, rst; input ? CS_, OE_, WR_; input [7:0] Addr; inout [7:0] data_bus; wire [7:0] data_in; wire [7:0] data_out; wire ? ? ? my_wr, my_rd; wire ? ? ? CS_reg1, CS_reg2, CS_reg3; // the register selection wire [7:0] reg1, reg2, reg3; ? ? ? ? ?// the register to be read and written assign data_in = data_bus; assign data_bus = ((!CS_) && (!OE_))? data_out : 8'bZZZZZZZZ; decode decode_u1 ?(.CS_(CS_), ? ? ? ? ? ? ? ? ? .OE_(OE_), ? ? ? ? ? ? ? ? ? .WR_(WR_), ? ? ? ? ? ? ? ? ? .Addr(Addr), ? ? ? ? ? ? ? ? ? .my_wr(my_wr), ? ? ? ? ? ? ? ? ? .my_rd(my_rd), ? ? ? ? ? ? ? ? ? .CS_reg1(CS_reg1), ? ? ? ? ? ? ? ? ? .CS_reg2(CS_reg2), ? ? ? ? ? ? ? ? ? .CS_reg3(CS_reg3) ? ? ? ? ? ? ? ? ? ); write_reg write_reg_u1 ( .clk(clk_cpu), ? ? ? ? ? ? ? ? ? ? ? ? .rst(rst), ? ? ? ? ? ? ? ? ? ? ? ? .data_in(data_in), ? ? ? ? ? ? ? ? ? ? ? ? .my_wr(my_wr), ? ? ? ? ? ? ? ? ? ? ? ? .CS_reg1(CS_reg1), ? ? ? ? ? ? ? ? ? ? ? ? .CS_reg2(CS_reg2), ? ? ? ? ? ? ? ? ? ? ? ? .CS_reg3(CS_reg3), ? ? ? ? ? ? ? ? ? ? ? ? .reg1(reg1), ? ? ? ? ? ? ? ? ? ? ? ? .reg2(reg2), ? ? ? ? ? ? ? ? ? ? ? ? .reg3(reg3) ? ? ? ? ? ? ? ? ? ? ? ? ); read_reg read_reg_u1 ?( .clk(clk_cpu), ? ? ? ? ? ? ? ? ? ? ? ? .rst(rst), ? ? ? ? ? ? ? ? ? ? ? ? .data_out(data_out), ? ? ? ? ? ? ? ? ? ? ? ? .my_rd(my_rd), ? ? ? ? ? ? ? ? ? ? ? ? .CS_reg1(CS_reg1), ? ? ? ? ? ? ? ? ? ? ? ? .CS_reg2(CS_reg2), ? ? ? ? ? ? ? ? ? ? ? ? .CS_reg3(CS_reg3), ? ? ? ? ? ? ? ? ? ? ? ? .reg1(reg1), ? ? ? ? ? ? ? ? ? ? ? ? .reg2(reg2), ? ? ? ? ? ? ? ? ? ? ? ? .reg3(reg3) ? ? ? ? ? ? ? ? ? ? ? ? ); ? ? ? ? ? ? ? ? ? ? endmodule

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35

  • 36

  • 37

  • 38

  • 39

  • 40

  • 41

  • 42

  • 43

  • 44

  • 45

  • 46

  • 47

  • 48

  • 49

  • 50

  • 51

  • 52

  • 53


使用OE/WR邊沿讀寫(xiě)

使用OE或WR的沿讀寫(xiě)寄存器的描述看起來(lái)比前面介紹的使用CPU時(shí)鐘同步讀寫(xiě)寄存器的描述簡(jiǎn)單,但是讀者必須明確這種方式正常工作有兩個(gè)前提條件:

  • OE的上升沿可以有效地采樣數(shù)據(jù)總線,即OE的上升沿采樣數(shù)據(jù)總線時(shí)Setup和Hold都能保證滿足;

  • WR和CS信號(hào)都比OE信號(hào)寬,即OE上升沿讀寫(xiě)寄存器時(shí),CS和WR信號(hào)始終保持有效。
    只有這兩個(gè)條件同時(shí)滿足的前提下,才能保證使用OE的沿讀寫(xiě)PLD寄存器電路是可靠的。

/******************************************/ module decode (CS_, WR_, Addr, my_wr, my_rd, CS_reg1, CS_reg2, CS_reg3); input ? ? ? ?CS_, WR_; input ?[7:0] Addr; output ? ? ? my_wr, my_rd; output ? ? ? CS_reg1, CS_reg2, CS_reg3; reg ? ? ? ? ?CS_reg1, CS_reg2, CS_reg3; assign my_wr = (!WR_) && (!CS_); assign my_rd = (WR_) ?&& (!CS_); always @ (Addr or CS_) ?if (!CS_) ? ? begin ? ? ? case (Addr) ? ? ? ? ?8'b 11110000: CS_reg1 <= 1'b1; ? ? ? ? ?8'b 00001111: CS_reg2 <= 1'b1; ? ? ? ? ?8'b 10100010: CS_reg3 <= 1'b1; ? ? ? ? ?default: ? ? begin ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? CS_reg1 <= 1'b0; ? ? ? ? ? ? ? ? ? ? ? ? ? ? CS_reg2 <= 1'b0; ? ? ? ? ? ? ? ? ? ? ? ? ? ? CS_reg3 <= 1'b0; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? end ? ? ? endcase ? ? end ? ? ? ? ? ? ? endmodule /******************************************/ module read_reg (OE_, rst, data_out, ?my_rd, CS_reg1, CS_reg2, CS_reg3, reg1, reg2, reg3); input ? ? ? ?OE_, rst, my_rd, CS_reg1, CS_reg2, CS_reg3; input ?[7:0] reg1, reg2, reg3; output [7:0] data_out; reg ? ?[7:0] data_out; ?always @ (posedge OE_ or negedge rst) ? ? ?if (!rst) ? ? ? ? data_out <= 8'b0; ? ? ?else ? ? ? ? begin ? ? ? ? ? ?if (my_rd) ? ? ? ? ? ? ? ?begin ? ? ? ? ? ? ? ? ? ? if (CS_reg1) ? ? ? ? ? ? ? ? ? ? ? ? data_out <= reg1; ? ? ? ? ? ? ? ? ? ? else if (CS_reg2) ? ? ? ? ? ? ? ? ? ? ? ? data_out <= reg2; ? ? ? ? ? ? ? ? ? ? else if (CS_reg3) ? ? ? ? ? ? ? ? ? ? ? ? data_out <= reg3; ? ? ? ? ? ? ? ?end ? ? ? ? ? ?else ? ? ? ? ? ? ? ?data_out <= 8'b0; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? end endmodule /******************************************/ module write_reg (OE_, rst, data_in, ?my_wr, CS_reg1, CS_reg2, CS_reg3, reg1, reg2, reg3); input ? ? ? ?OE_, rst, my_wr, CS_reg1, CS_reg2, CS_reg3; input ?[7:0] data_in; output [7:0] reg1, reg2, reg3; reg ? ?[7:0] reg1, reg2, reg3; ?always @ (posedge OE_ or negedge rst) ? ? ?if (!rst) ? ? ? ? begin ? ? ? ? ? ? ?reg1 <= 8'b0; ? ? ? ? ? ? ?reg2 <= 8'b0; ? ? ? ? ? ? ?reg3 <= 8'b0; ? ? ? ? ? ? ? ? end ? ? ?else ? ? ? ? begin ? ? ? ? ? ?if (my_wr) ? ? ? ? ? ? ? ?begin ? ? ? ? ? ? ? ? ? ? if (CS_reg1) ? ? ? ? ? ? ? ? ? ? ? ? reg1 <= data_in; ? ? ? ? ? ? ? ? ? ? else if (CS_reg2) ? ? ? ? ? ? ? ? ? ? ? ? reg2 <= data_in; ? ? ? ? ? ? ? ? ? ? else if (CS_reg3) ? ? ? ? ? ? ? ? ? ? ? ? reg3 <= data_in; ? ? ? ? ? ? ? ?end ? ? ? ? ? ?else ? ? ? ? ? ? ? ?begin ? ? ? ? ? ? ? ? ? ? reg1 <= reg1; ? ? ? ? ? ? ? ? ? ? reg2 <= reg2; ? ? ? ? ? ? ? ? ? ? reg3 <= reg3; ? ? ? ? ? ? ? ?end ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? end ? ? ? ? endmodule /******************************************/ module top (rst, CS_, OE_, WR_, Addr, data_bus); input ? ? ? rst; input ? ? ? ?CS_, OE_, WR_; input [7:0] Addr; inout [7:0] data_bus; wire [7:0] data_in; wire [7:0] data_out; wire ? ? ? my_wr, my_rd; wire ? ? ? CS_reg1, CS_reg2, CS_reg3; // the register selection wire [7:0] reg1, reg2, reg3; ? ? ? ? ?// the register to be read and written assign data_in = data_bus; assign data_bus = ((!CS_) && (!OE_))? data_out : 8'bZZZZZZZZ; decode decode_u1 ?(.CS_(CS_), ? ? ? ? ? ? ? ? // ?.OE_(OE_), ? ? ? ? ? ? ? ? ? .WR_(WR_), ? ? ? ? ? ? ? ? ? .Addr(Addr), ? ? ? ? ? ? ? ? ? .my_wr(my_wr), ? ? ? ? ? ? ? ? ? .my_rd(my_rd), ? ? ? ? ? ? ? ? ? .CS_reg1(CS_reg1), ? ? ? ? ? ? ? ? ? .CS_reg2(CS_reg2), ? ? ? ? ? ? ? ? ? .CS_reg3(CS_reg3) ? ? ? ? ? ? ? ? ? ); write_reg write_reg_u1 ( .OE_(OE_), ? ? ? ? ? ? ? ? ? ? ? ? .rst(rst), ? ? ? ? ? ? ? ? ? ? ? ? .data_in(data_in), ? ? ? ? ? ? ? ? ? ? ? ? ? .my_wr(my_wr), ? ? ? ? ? ? ? ? ? ? ? ? .CS_reg1(CS_reg1), ? ? ? ? ? ? ? ? ? ? ? ? .CS_reg2(CS_reg2), ? ? ? ? ? ? ? ? ? ? ? ? .CS_reg3(CS_reg3), ? ? ? ? ? ? ? ? ? ? ? ? .reg1(reg1), ? ? ? ? ? ? ? ? ? ? ? ? .reg2(reg2), ? ? ? ? ? ? ? ? ? ? ? ? .reg3(reg3) ? ? ? ? ? ? ? ? ? ? ? ? ); read_reg read_reg_u1 ?( ?.OE_(OE_), ? ? ? ? ? ? ? ? ? ? ? ? .rst(rst), ? ? ? ? ? ? ? ? ? ? ? ? .data_out(data_out), ? ? ? ? ? ? ? ? ? ? ? ? ? .my_rd(my_rd), ? ? ? ? ? ? ? ? ? ? ? ? .CS_reg1(CS_reg1), ? ? ? ? ? ? ? ? ? ? ? ? .CS_reg2(CS_reg2), ? ? ? ? ? ? ? ? ? ? ? ? .CS_reg3(CS_reg3), ? ? ? ? ? ? ? ? ? ? ? ? .reg1(reg1), ? ? ? ? ? ? ? ? ? ? ? ? .reg2(reg2), ? ? ? ? ? ? ? ? ? ? ? ? .reg3(reg3) ? ? ? ? ? ? ? ? ? ? ? ? ); ? ? ? ? ? ? ? ? ? ? endmodule /******************************************/

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35

  • 36

  • 37

  • 38

  • 39

  • 40

  • 41

  • 42

  • 43

  • 44

  • 45

  • 46

  • 47

  • 48

  • 49

  • 50

  • 51

  • 52

  • 53

  • 54

  • 55

  • 56

  • 57

  • 58

  • 59

  • 60

  • 61

  • 62

  • 63

  • 64

  • 65

  • 66

  • 67

  • 68

  • 69

  • 70

  • 71

  • 72

  • 73

  • 74

  • 75

  • 76

  • 77

  • 78

  • 79

  • 80

  • 81

  • 82

  • 83

  • 84

  • 85

  • 86

  • 87

  • 88

  • 89

  • 90

  • 91

  • 92

  • 93

  • 94

  • 95

  • 96

  • 97

  • 98

  • 99

  • 100

  • 101

  • 102

  • 103

  • 104

  • 105

  • 106

  • 107

  • 108

  • 109

  • 110

  • 111

  • 112

  • 113

  • 114

  • 115

  • 116

  • 117

  • 118

  • 119

  • 120

  • 121

  • 122

  • 123

  • 124

  • 125

  • 126

  • 127

  • 128

  • 129

  • 130

  • 131

  • 132

  • 133

  • 134

  • 135

  • 136

  • 137

  • 138

  • 139

  • 140

  • 141

  • 142

  • 143

  • 144

  • 145

  • 146


如果譯碼電路是組合邏輯,則其譯碼結(jié)果就有可能帶有毛刺,另外由于CPU總線的時(shí)序在電壓、溫度、環(huán)境變化的情況下時(shí)序可能遭到破壞,造成OE,WR,CS等信號(hào)的時(shí)序余量惡化,如果此時(shí)使用譯碼結(jié)果的電平做電平敏感的always模塊,進(jìn)行讀寫(xiě)寄存器操作(如Example-4-21\ asyn_bad目錄下的read_reg.v和write_reg.v),則會(huì)因?yàn)槊毯湾e(cuò)誤電平造成讀寫(xiě)錯(cuò)誤。所以不同將OE或WR的電平作為敏感信號(hào)來(lái)進(jìn)行讀寫(xiě)。


【轉(zhuǎn)】RTL概念與常用RTL建模的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
上思县| 彭泽县| 杭锦旗| 长丰县| 宁远县| 界首市| 北海市| 嘉义县| 虎林市| 依安县| 五峰| 新和县| 柯坪县| 普陀区| 青岛市| 金山区| 锡林浩特市| 舟山市| 邮箱| 陆丰市| 鄯善县| 兴文县| 周口市| 花莲市| 正宁县| 常山县| 谢通门县| 芦溪县| 湄潭县| 平原县| 黔西县| 铜陵市| 都兰县| 营山县| 宁强县| 阜宁县| 霍州市| 霍林郭勒市| 奉贤区| 灵石县| 镇巴县|