介紹了數字系統設計中經常用到的計數器,分頻器,選擇器,譯碼器,編碼器,寄存器,存儲器,輸入電路,顯示電路等基本單元電路的VHDL程序設計。
學習要求:在教師講授這些基本單元電路的設計思想的基礎上,通過上機調試熟練掌握這些基本單元電路的設計。
關鍵詞:計數器(Counter),分頻器(Divder),選擇器(Multiplexer),譯碼器(Decoder),編碼器(Encoder),寄存器(Register),存儲器(Memory),輸入電路(Input Circuit),顯示電路(Display Circuit)
6.1 計數器的設計
6.1.1 同步計數器的設計
6.1.2 異步計數器的設計
6.2 分頻器的設計
6.3 選擇器的設計
6.4 譯碼器的設計
6.5 編碼器的設計
6.5.1 一般編碼器的設計
6.5.2 優先級編碼器的設計
6.6 寄存器的設計
6.6.1 數碼寄存器的設計
6.6.2 移位寄存器的設計
6.6.3 并行加載移位寄存器的設計
6.7 存儲器的設計
6.7.1 只讀存儲器ROM的設計
6.7.2 讀寫存儲器SRAM的設計
6.8 輸入電路的設計
6.8.1 鍵盤掃描電路的設計
6.8.2 鍵盤接口電路的設計
6.9 顯示電路的設計
6.9.1 數碼管靜態顯示電路的設計
6.9.2 數碼管動態顯示電路的設計
6.9.2 液晶顯示控制電路的設計
6.1 計數器的設計
計數器是在數字系統中使用最多的時序電路,它不僅能用于對時鐘脈沖計數,還可以用于分頻,定時,產生節拍脈沖和脈沖序列以及進行數字運算等。計數器是一個典型的時序電路,分析計數器就能更好地了解時序電路的特性。計數器分同步計數器和異步計數器兩種。
6.1.1 同步計數器的設計
所謂同步計數器,就是在時鐘脈沖(計數脈沖)的控制下,構成計數器的各觸發器狀態同時發生變化的那一類計數器。
1) 六十進制計數器
眾所周知,用一個4位二進制計數器可構成1位十進制計數器,而2位十進制計數器連接起來可以構成一個六十進制的計數器。六十進制計數器常用于時鐘計數。一個六十進制計數器的外部端口示意圖如圖6.1所示。在該六十進制計數器的電路中,BCDLWR和BCD10WR與DATAIN配合,以實現對六十進制計數器的個位和十位值的預置操作。應注意,在對個位和十位進行預置操作時,DATAIN輸入端是公用的,因而個位和十位的預置操作必定要串行進行。利用VHDL語言描述六十進制計數器的程序如例6.1所示。
圖6.1 六十進制計數器外部端口示意圖
【例6.1】 用VHDL設計一個六十進制計數器(方法1)。
--BCD60COUNT.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY BCD60COUNT IS
PORT(CLK,BCD1WR,BCD10WR,CIN:STD_LOGIC;
COUT STD_LOGIC;
DATAIN:IN STD_LOGIC_VECTOR (3 DOWNTO 0);
BCD1:OUT STD_LOGIC_VECTOR (3 DOWNTO 0);
BCDI0:OUT STD_LOGIC_VECTOR (2 DOWNTO 0));
END BCD60COUNT;
ARCHITECTURE RTL OF BCD60COUNT IS
SIGNAL BCD1N:STD_LOGIC_VECTOR (3 DOWNTO 0);
SIGNAL BCD10N:STD_LOGIC_VECTOR (2 DOWNTO 0);
BEGIN
BCD1<=BCD1N;
BCDI0<=BCD10N;
PROCESS (CLK,BCD1WR) –-個位數處理進程
BEGIN
IF (BCD1WR='1') THEN
BCD1N<=DATAIN;
ELSIF (CLK'EVENT AND CLK='1') THEN
IF (CIN='1') THEN
IF (BCD1N=9) THEN
BCD1N<="0000";
ELSE
BCD1N<=BCD1N+1;
END IF;
END IF;
END IF;
END PROCESS;
PROCESS (CLK,BCD10WR) –-十位數處理進程
BEGIN
IF (BCD10WR='1') THEN
BCD10N<=DATAIN (2 DOWNTO 0);
ELSIF (CLK'EVENT AND CLK='1') THEN
IF (CIN='1' AND BCD1N=9) THEN
IF (BCD10N=5) THEN
BCD10N<="000";
ELSE
BCD10N<=BCD10N+1;
END IF;
END IF;
END IF;
END PROCESS;
PROCESS (BCD10N,BCD1N,CIN) –-進位位處理進程
BEGIN
IF (CIN='1' AND BCD1N=9 AND BCD10N=5) THEN
CO<='1';
ELSE
CO<='0';
END IF;
END PROCESS;
END RTL;
【例6.2】 用VHDL設計一個六十進制計數器(方法2)。
--COUNTER60.vhd
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY COUNTER60 IS
PORT(CP: IN STD_LOGIC; --時鐘脈沖
BIN: OUT STD_LOGIC_VECTOR (5 DOWNTO 0); --二進制
S: IN STD_LOGIC; --輸出啟動信號
CLR: IN STD_LOGIC; --清除信號
EC: IN STD_LOGIC; --使能計數信號
CY60: OUT STD_LOGIC );--計數60進位信號
END COUNTER60;
ARCHITECTURE RTL OF COUNTER60 IS
SIGNAL Q : STD_LOGIC_VECTOR (5 DOWNTO 0) ;
SIGNAL RST, DLY : STD_LOGIC;
BEGIN
PROCESS (CP,RST) -- 計數60
BEGIN
IF RST = '1' THEN
Q <= "000000"; -- 復位計數器
ELSIF CP'EVENT AND CP = '1' THEN
DLY <= Q(5);
IF EC = '1' THEN
Q <= Q+1; -- 計數值加1
END IF;
END IF;
END PROCESS;
CY60 <= NOT Q(5) AND DLY; -- 進位信號微分
RST <= '1' WHEN Q=60 OR CLR='1' ELSE -- 復位信號設定
'0';
BIN <= Q WHEN S = '1' ELSE -- 計數輸出
"000000";
END RTL ;
2) 可逆計數器
在時序應用電路中,計數器的應用十分普遍,如加法計數器,減法計數器,可逆計數器等。所謂可逆計數器,就是根據計數控制信號的不同,在時鐘脈沖作用下,計數器可以進行加1或者減1操作的一種計數器。可逆計數器有一個特殊的控制端,這就是UPDN端。當UPDN=‘1’時,計數器進行加1操作,當UPDN=‘0’時,計數器就進行減1操作。表6.1是一個3位可逆計數器的真值表,它的VHDL語言描述如例6.3所示。
表6.1 可逆計數器真值表
輸入端 輸出端
DIR CP Q2 Q1 Q0
X X 0 0 0
1 計數器加1操作
0 計數器減1操作
【例6.3】 用VHDL設計一個3位二進制的可逆計數器。
--COUNT3.vhd
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY COUNT3 IS
PORT (CP,DIR:IN STD_LOGIC;
Q: OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END;
ARCHITECTURE RTL OF COUNT3 IS
SIGNAL QN:STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
PROCESS(CP)
BEGIN
IF CP'EVENT AND CP='1' THEN
IF DIR='0' THEN
QN<=QN +1;
ELSE
QN<=QN-1;
END IF ;
END IF;
END PROCESS;
Q<=QN;
END RTL;
編寫可逆計數器VHDL程序時,在語法上,就是把加法和減法計數器合并,使用一個控制信號決定計數器作加法或減法的動作。在本例中,利用“控制信號DIR”可以讓計數器的計數動作加1或減1。
6.1.2 異步計數器的設計
異步計數器又稱行波計數器,它將低/高位計數器的輸出做為高/低位計數器的時鐘信號,這一級一級串行連接起來就構成了一個異步計數器。異步計數器與同步計數器不同之處就在于時鐘脈沖的提供方式,但是,由于異步計數器采用行波計數,從而使計數延遲增加,在要求延遲小的領域受到了很大限制。盡管如此,由于它的電路簡單,仍有廣泛的應用。
圖6.2是用VHDL語言描述的一個由8個觸發器構成的異步計數器.它的程序如例6.4所示,采用元件例化方式生成。與上述同步計數器不同之處主要表現在對各級時鐘脈沖的描述上,這一點請讀者在閱讀程序時多加注意。
圖6.2 8位異步計數器原理圖
【例6.4】 用VHDL設計一個由8個觸發器構成的8位二進制異步計數器。
--RPLCONT.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY DFFR IS
PORT(CLK,CLR,D:IN STD_LOGIC;
Q,QB:OUT STD_LOGIC);
END ENTITY DFFR;
ARCHITECTURE ART1 OF DFFR IS
SIGNAL Q_IN:STD_LOGIC;
BEGIN
QB<=NOT Q_IN;
Q<=Q_IN;
PROCESS(CLK,CLR) IS
BEGIN
IF (CLR='1') THEN
Q_IN<='0';
ELSIF (CLK'EVENT AND CLK='1') THEN
Q_IN<=D;
END IF ;
END PROCESS;
END ARCHITECTURE ART1;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY RPLCONT IS
PORT(CLK,CLR:IN STD_LOGIC;
COUNT:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY RPLCONT;
ARCHITECTURE ART2 OF RPLCONT IS
SIGNAL COUNT_IN_BAR:STD_LOGIC_VECTOR(8 DOWNTO 0);
COMPONENT DFFR IS
PORT(CLK,CLR,D:IN STD_LOGIC;
Q,QB:OUT STD_LOGIC);
END COMPONENT;
BEGIN
COUNT_IN_BAR(0)<=CLK;
GEN1:FOR I IN 0 TO 7 GENERATE
U:DFFR PORT MAP (CLK=>COUNT_IN_BAR(I),CLR=>CLR,
D=>COUNT_IN_BAR(I+1),Q=>COUNT(I),QB=>COUNT_IN_BAR(I+1));
END GENERATE;
END ARCHITECTURE ART2;
6.2 分頻器的設計
一般來說,可以把加法計數器看成一種分頻電路,而且是除2的N的次方的分頻電路。
但是也常常會有除M(M不是2的N次方)的分頻電路需求.
下面就介紹一個除6的加法分頻電路。先建立一個計數器,而這個計數器的大小必須是3位(計數默認范圍是0~2^3-1=7),不過將把這樣的計數值為6的瞬間,立即復位改變為0,其VHDL程序如例6.5所示
【例6.5】 用VHDL設計一個除6的加法分頻電路。
--COUNT6.vhd
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY COUNT6 is
PORT(CP: IN STD_LOGIC;
Result: OUT STD_LOGIC);
END COUNT6;
ARCHITECTURE a OF COUNT6 IS
SIGNAL RST: STD_LOGIC;
SIGNAL QN: STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
PROCESS (CP,RST) -- *** COUNTER
BEGIN
IF RST = '1' THEN
QN <= "000"; --Reset Counter
ELSIF CP'event AND CP='1' THEN
QN <= QN + 1; --COUNTER + 1
END IF;
END PROCESS;
RST <= '1' WHEN QN = 6 ELSE -- RESET COUNTER
'0';
Result <= QN(2); -- Result Output
END a;
以后遇到需要分頻是N 的同步計數器,需將上述QN=6改成QN=N,而且計數器X bits數需調整為符合條件2X>=N才可以。
6.3 選擇器的設計
多路選擇器可以從多組數據來源中選取一組送入目的地。它的應用范圍相當廣泛,從組合邏輯的執行,到數據路徑的選擇,經常可以看到它的蹤影。另外在像時鐘,計數定時器等的輸出顯示電路中都可以看到利用多路選擇器制作掃描電路來分別驅動輸出裝置(通常為七段數碼顯示管,點矩陣或液晶面板),以降低功率的消耗。有時也希望把兩組沒有必要同時觀察的數據,共享一組顯示電路,以降低成本。
多路選擇器的結構是2N個輸入線,會有N個地址選擇線及一個輸出線配合。現以一個四選一的多路選擇器為例,其四選一電路的真值表如表6.2所示,其外部端口示意圖如圖6.3所示。
表6.2 四選一電路真值表
選擇輸入 數據輸入 數據輸出
b a Input(0) Input(1) Input(2) Input(3) y
0 0 0 X X X 0
0 0 1 X X X 1
0 1 X 0 X X 0
0 1 X 1 X X 1
1 0 X X 0 X 0
1 0 X X 1 X 1
1 1 X X X 0 0
1 1 X X X 1 1
圖6.3 四選一電路外部端口示意圖
描述四選一多路選擇器的方法有多種,例如在一個進程中使用if-then-else語句;在一個進程中使用case語句;使用with select構造或使用結構VHDL。現用if-then-else語句對它進行描述,就可以得到如例6.6所示的程序。
【例6.6】設計一個四選一的多路選擇器的VHDL程序(使用if-then-else語句)。
--MUX4.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY MUX4 IS
PORT(DATA0,DATA1,DATA2,DATA3:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
A,B:IN STD_LOGIC;
Y:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END ENTITY MUX4;
ARCHITECTURE ART OF MUX4 IS
SIGNAL SEL:STD_LOGIC_VECTOR(1 DOWNTO 0);
BEGIN
SEL<=B&A;
PROCESS(SEL)
BEGIN
IF (SEL="00") THEN
Y<=DATA0;
ELSIF(SEL="01") THEN
Y<=DATA1;
ELSIF(SEL="10") THEN
Y<=DATA2;
ELSE
Y<=DATA3;
END IF;
END PROCESS;
ARCHITECTURE ART;
例6.6中的四選一選擇器是用IF語句描述的,程序中的ELSE項作為余下的條件,將選擇INPUT(3)從Y端輸出,這種描述比較安全。當然,不用ELSE項也可以,這時必須列出SEL的所有可能出現的情況,加以一一確認。在進程中使用CASE語句會更清晰易讀。例6.7是用CASE語句描述的四選一選擇器。
【例6.7】設計一個四選一的多路選擇器的VHDL程序(使用case語句)。
--MUX4.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY MUX4 IS
PORT(DATA0,DATA1,DATA2,DATA3:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
A,B:IN STD_LOGIC;
Y:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END ENTITY MUX4;
ARCHITECTURE ART OF MUX4 IS
SIGNAL SEL:STD_LOGIC_VECTOR(1 DOWNTO 0);
BEGIN
SEL<=B&A;
PROCESS(SEL)
BEGIN
CASE SEL IS
WHEN "00"=>Y<=DATA0;
WHEN "01"=>Y<=DATA1;
WHEN "10"=>Y<=DATA2;
WHEN "11"=>Y<=DATA3;
WHEN OTHERS =>Y<=NULL;
END CASE;
END PROCESS;
END ARCHITECTURE ART;
【例6.8】設計一個四選一的多路選擇器的VHDL程序(使用WHEN-ELSE并行條件賦值語句)。
--MUX4.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY MUX4 IS
PORT(DATA0,DATA1,DATA2,DATA3:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
A,B:IN STD_LOGIC;
Y:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END ENTITY MUX4;
ARCHITECTURE ART OF MUX4 IS
SIGNAL SEL : STD_LOGIC_VECTOR(1 DOWNTO 0);
BEGIN
SEL<=B&A;
Y<= DATA0 WHEN SEL="00" ELSE
DATA1 WHEN SEL="01" ELSE
DATA2 WHEN SEL="10" ELSE
DATA3 WHEN SEL="11" ELSE
'0' ;
END ARCHITECTURE ART ;
6.4 譯碼器的設計
譯碼器是把輸入的數碼解出其對應的數碼,如果有N個二進制選擇線,則最多可以譯碼轉換成2N個數據。譯碼器也經常被應用在地址總線或用作電路的控制線。像只讀存儲器(ROM)中便利用譯碼器來進行地址選址的工作。
3-8譯碼器是最常用的種小規模集成電路。3-8譯碼器外部端口示意圖如圖6.9所示,它有3個二進制輸入端a, b,c和8個譯碼輸出端y0~y7。對輸入a,b,c的值進行譯碼,就可以確定輸出端y0~y7的哪一個輸出端變為有效(低電平),從而達到譯碼的目的。另外為方便譯碼器的控制或便于將來擴充用,在設計時常常會增加一個EN使能輸入腳。3-8譯碼器的真值表如表6.3所示。有了真值表,就可以直接用查表法來設計。
在VHDL 中,“WITH…SELECT”,“CASE…WHEN”及“WHEN…ELSE”這類指令都是執行查表或對應動作的能手。
圖6.4 3-8譯碼器外部端口示意圖
表6.3 3-8譯碼器的真值表
使能 二進制輸入端 譯碼輸出端
en c b a y0 y1 y2 y3 y4 y5 y6 y7
0 x x x 1 1 1 1 1 1 1 1
1 0 0 0 0 1 1 1 1 1 1 1
1 0 0 1 1 0 1 1 1 1 1 1
1 0 1 0 1 1 0 1 1 1 1 1
1 0 1 1 1 1 1 0 1 1 1 1
1 1 0 0 1 1 1 1 0 1 1 1
1 1 0 1 1 1 1 1 1 0 1 1
1 1 1 0 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1 1 0
【例6.9】 用VHDL設計一個3-8譯碼器(用“CASE…WHEN”語句)。
--DECODER38.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY DECODER38 IS
PORT (A,B,C, EN : IN STD_LOGIC;
Y : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END DECODER38 ;
ARCHITECTURE RTL OF DECODER38 IS
SIGNAL INDATA :STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
INDATA<=C&B&A;
PROCESS (INDATA,EN)
BEGIN
IF (EN='1')THEN
CASE INDATA IS
WHEN "000" =>Y<="11111110";
WHEN "001" =>Y<="11111101";
WHEN "010" =>Y<="11111011";
WHEN "011" =>Y<="11110111";
WHEN "100" =>Y<="11101111";
WHEN "101" =>Y<="11011111";
WHEN "110" =>Y<="10111111";
WHEN "111" =>Y<="01111111";
WHEN OTHERS=>Y<=NULL;
END CASE;
ELSE
Y<="11111111";
END IF;
END PROCESS;
END RTL;
【例6.10】 用VHDL設計一個3-8譯碼器(用“WITH…SELECT”語句)。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.All;
ENTITY DECODER38 IS
PORT (A,B,C, EN : IN STD_LOGIC;
Y : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END DECODER38;
ARCHITECTURE RTL OF DECODER38 IS
SIGNAL INDATA :STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
INDATA<=EN&C&B&A; --將EN,A,B,C合并成序列的一種寫法
WITH INDATA SELECT
Y<="11111110" WHEN "1000",
"11111101" WHEN "1001",
"11111011" WHEN "1010",
"11110111" WHEN "1011",
"11101111" WHEN "1100",
"11011111" WHEN "1101",
"10111111" WHEN "1110",
"01111111" WHEN "1111",
"11111111" WHEN OTHERS;
END RTL;
在本節中用到的兩種描述語句,“WITH…SELECT”是并行同時性語句,“CASE…WHEN”是與其功能相同的順序性語句,讀者在使用時一定要確定需要的是順序性語句還是并行性語句,否則程序在編譯時會發生錯誤。
6.5 編碼器的設計
編碼器是將2^N個分離的信息代碼以N個二進制碼來表示。它的功能和譯碼器正好相反。編碼器常常運用于影音壓縮或通信方面,以達到精簡傳輸量的目的。可以將編碼器看成壓縮電路,譯碼起看成解壓縮電路。傳送數據前先用編碼器壓縮數據后在傳送出去,在接收端則由譯碼器將數據解壓縮,還原其原來的數據。這樣,在傳送過程中,就可以以N個數碼來代替2^N個數碼的數據量,來提升傳輸效率。
6.5.1 一般編碼器的設計
如果沒有特別說明,各編碼輸入端無優先
區別。圖6.5是8-3編碼器的外部端口圖,
有了外部端口圖,就能夠做ENTITY的定義,
再根據編碼器的真值表如表6.4所示.,再使用
查表法就可以輕松描述結構體了。
圖6.5 8-3編碼器外部端口圖
表6.4 8-3編碼器的真值表
輸入 二進制編碼輸出
A7 A6 A5 A4 A3 A2 A1 A0 Y2 Y1 Y0
1 1 1 1 1 1 1 0 1 1 1
1 1 1 1 1 1 0 1 1 1 0
1 1 1 1 1 0 1 1 1 0 1
1 1 1 1 0 1 1 1 1 0 0
1 1 1 0 1 1 1 1 0 1 1
1 1 0 1 1 1 1 1 0 1 0
1 0 1 1 1 1 1 1 0 0 1
0 1 1 1 1 1 1 1 0 0 0
【例6.11】用VHDL設計一個8-3編碼器。
--CH_8_3.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY CH_8_3 IS
PORT (A :IN STD_LOGIC_VECTOR(7 DOWNTO 0);
Y :OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END CH_8_3;
ARCHITECTURE RTL OF CH_8_3 IS
BEGIN
WITH A SELECT
Y<="000" WHEN "11111110",
"001" WHEN "11111101",
"010" WHEN "11111011",
"011" WHEN "11110111",
"100" WHEN "11101111",
"101" WHEN "11011111",
"110" WHEN "10111111",
"111" WHEN "01111111",
"000" WHEN OTHERS;
END RTL;
6.5.2 優先級編碼器的設計
優先級編碼器長用于中斷的優先級控制,例如,74LS148是一個8輸入,3位二進制碼輸出的優先級編碼器。當其某一個輸入有效時,就可以輸出一個對應的3位二進制編碼。另外,當同時有幾個輸入有效時, 將輸優先級最高的那個輸入所對應的二進制編碼。
該優先級編碼器的真值表如表6. 5所示。表中的“X”項表示任意項,它可以是“0”,也可以是“1”。INPUT(0)的優先級最高,INPUT(7)的優先級最低。
表6.5 優先級編碼器真值表
輸入 二進制編碼輸出
Input(7) Input(6) Input(5) Input(4) Input(3) Input(2) Input(1) Input(0) Y2 Y1 Y0
X X X X X X X 0 1 1 1
X X X X X X 0 1 1 1 0
X X X X X 0 1 1 1 0 1
X X X X 0 1 1 1 1 0 0
X X X 0 1 1 1 1 0 1 1
X X 0 1 1 1 1 1 0 1 0
X 0 1 1 1 1 1 1 0 0 1
X 1 1 1 1 1 1 1 0 0 0
【例6.12】 用VHDL設計一個8-3優先級編碼器。
-- CH8_3.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY CH8_3 IS
PORT (INPUT :IN STD_LOGIC_VECTOR(7 DOWNTO 0);
Y: OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END CH8_3;
ARCHITECTURE RTL OF CH8_3 IS
BEGIN
PROCESS(INPUT)
BEGIN
IF (INPUT(0)='0') THEN
Y<="111";
ELSIF (INPUT(1)='0' THEN
Y<="110";
ELSIF (INPUT(2)='0' THEN
Y<="101";
ELSIF (INPUT(3)='0' THEN
Y<="100";
ELSIF (INPUT(4)='0' THEN
Y<="011";
ELSIF (INPUT(5)='0' THEN
Y<="010";
ELSIF (INPUT(6)='0' THEN
Y<="001";
ELSIF
Y<="000";
END IF;
END PROCESS;
END RTL;
6.6 寄存器的設計
寄存(鎖存)器是一種重要的數字電路部件,常用來暫時存放指令、參與運算的數據或運算結果等。它是數字測量和數字控制中常用的部件,是計算機的主要部件之一。寄存器的主要組成部分是具有記憶功能的雙穩態觸發器。一個觸發器可以儲存一位二進制代碼,要儲存N位二進制代碼,就在有N個觸發器。寄存器從功能上說,通常可分為數碼寄存器和移位寄存器兩種。
6.6.1 數碼寄存器的設計
數碼寄存器用于寄存一組二進制代碼,廣泛用于各類數字系統。下面給出—個8位寄存器的VHDL描述。
【例6.13】 用VHDL設計一個8位的數碼寄存器。
--REG.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY REG IS
PORT(D:IN STD_LOGIC_VECTOR(7 TO 0);
CLK:IN STD_LOGIC;
Q:OUT STD_LOGIC_VECTOR(7 TO 0));
END ENTITY REG;
ARCHITECTURE ART OF REG IS
BEGIN
PROCESS(CLK) IS
BEGIN
IF(CLK'EVENT AND CLK='1')THEN
Q<=D;
END IF;
END PROCESS;
END ARCHITECTURE ART;
6.6.2 移位寄存器的設計
移位寄存器除了具有存儲代碼的功能以外,還具有移位功能。所謂移位功能,是指寄存器里存儲的代碼能在移位脈沖的作用下依次左移或右移。因此,移位寄存器不但可以用來寄存代碼,還可用來實現數據的串并轉換、數值的運算以及數據處理等。下面給出一個8位的移位寄存器,其具有左移一位或右移一位、并行輸入和同步復位的功能。
【例6.14】用VHDL設計一個8位的移位寄存器,其具有左移一位或右移一位、并行輸入和同步復位的功能.
--SHIFT_REG.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY SHIFT_REG IS
PORT(DATA:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
CLK:IN STD_LOGIC;
SHIFT_LEFT,SHIFT_RIGHT:IN STD_LOGIC;
RESET:IN STD_LOGIC;
MODE:IN STD_LOGIC_VECTOR(1 DOWNTO 0);
QOUT:BUFFER STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY SHIFT_REG;
ARCHITECTURE ART OF SHIFT_REG IS
BEGIN
PROCESS IS
BEGIN
WAIT UNTIL(RISING_EDGE(CLK));
IF(RESET='1')THEN
QOUT<="00000000";
ELSE --同步復位功能的實現
CASE MODE IS
WHEN "01"=>QOUT<=SHIFT_RIGHT&QOUT(7 DOWNTO 1);--右移一位
WHEN "10"=>QOUT<=QOUT(6 DOWNTO 0)&SHIFT_LEFT; --左移一位
WHEN "11"=>QOUT<=DATA; --并行輸入
WHEN OTHERS=>NULL;
END CASE;
END IF;
END PROCESS;
END ARCHITECTURE ART;
6.6.3 并行加載移位寄存器的設計
在TTL手冊中的74LS166是一個帶清零端的8位并行加載的移位寄存器,其引腳圖及邏輯圖如圖6.6所示。
圖6.6 74LS166的引腳圖及邏輯圖
圖中各引腳名稱和功能如下:
A,B,C,D,E,F,G,H:8位并行數據輸入端;
SER:串行數據輸入端;
QH:串行數據輸出端;
CLK: 時鐘信號輸入端;
CLKINH:時鐘信號禁止(FE)端;
SH/LD:移位加載控制(SL)端;
CLR:清零端。
當清零輸入端CLR為‘0’時,8個觸發器的輸出均為‘0’,從而使輸出Q為‘0’。CLKINH是時鐘禁止端,當它為‘1’時將禁止時鐘,即不管時鐘信號如何變化,移位寄存器的狀態不發生改變。另外,時鐘信號只在上升沿時才有效,且CLKINH 為‘0’。當控制端SH/LD =‘1’時是移位狀態,在時鐘脈沖上升沿的控制下右移,當SH/LD =‘0’時是加載狀態,在時鐘脈沖上升沿的作用下,數據輸入端A~H的信號就是裝載到移位寄存器的QA~QH。根據上述描述,就可以用VHDL語言編寫出描述74166功能的程序。
【例6.15】用VHDL設計的帶清零端的8位并行加載的移位寄存器74LS166。
-- SREG8PARLWCLR.VHD
LIBRARY IEEE;
USE IEEE. STD _ LOGIC _ 1164. ALL;
ENTITY SREG8PARLWCLR IS
PORT(CLR, SL, FE, CLK, SER: IN STD_ LOGIC;
A, B, C, D, E, F,G, H: IN STD_ LOGIC;
Q: OUT STD_ LOGIC);
END SREG8PARLWCLR;
ARCHITECTURE BEHAV OF SREG8PARLWCLR IS
SIGNAL TMPREG8:STD _ LOGIC _ VECTOR (7 DOWNTO O);
BEGIN
PROCESS (CLK, SL, FE, CLR)
IF (CLR= ‘0’) THEN
TMPREG8< = “00000000”;
Q< = TMPREG8 (7);
ELSIF (CLK’EVENT) AND (CLK= ‘1’) AND (FE = ‘0’)THEN
IF (SL= ‘0’) THEN
TMPREG8 (0)< =A;
TMPREG8 (1)< =B;
TMPREG8 (2)< =C;
TMPREG8 (3)< =D;
TMPREG8 (4)< =E;
TMPREG8 (5)< =F;
TMPREG8 (6)< =G;
TMPREG8 (7)< =H;
Q< = TMPREG8 (7);
ELSIF (SL =‘1’)THEN
FOR I IN TMPREG8’HIGH DOWNTO TMPREG8’LOW+ 1 LOOP
TMPREG8 (I)< = TMPREG8(I- 1);
END LOOP;
TMPREG8 (TMPREG8’LOW) < = SE;
Q< = TMPREG8 (7);
END IF;
END IF;
END PROCESS;
END BEHAV;
6.7 存儲器的設計
半導體存儲器的種類很多,從功能上可以分為只讀存儲器(READ_ONLY MEMORY,簡稱ROM)和隨機存儲器(RANDOM ACCESS MEMORY,簡稱RAM)兩大類。
6.7.1 只讀存儲器ROM的設計
只讀存儲器在正常工作時從中讀取數據,不能快速地修改或重新寫入數,適用于存儲固定數據的場合。下面是一個容量為256×4的ROM存儲的例子,該ROM有8位地址線ADR(0)~ADR(7),4位數據輸出線DOUT(0)~DOUT(3)及使能EN,如圖6. 7所示。
圖6. 7 ROM
【例6.16】 用VHDL設計一個一個容量為256×4的ROM存儲的例子,該ROM有8位地址線ADR(0)~ADR(7),4位數據輸出線DOUT(0)~DOUT(3)及使能EN。
-- ROM.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE STD.TEXTIO.ALL;
ENTITY ROM IS
PORT(EN:IN STD_LOGIC;
ADR:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
DOUT: OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END ENTITY ROM;
ARCHITECTURE ART OF ROM IS
SUBTYPE WORD IS STD_LOGIC_VECTOR(3 DOWNTO 0);
TYPE MEMORY IS ARRAY(0 TO 255) OF WORD;
SIGNAL ADR_IN:INTEGER RANGE 0 TO 255;
VARIABLE ROM:MEMORY;
VARIABLE START_UP:BOOLEAN:=TRUE;
VARIABLE L:LINE;
VARIABLE J:INTEGER;
FILE ROMIN:TEXT IS IN “ROMIN”;
BEGIN
PROCESS(EN,ADR) IS
BEGIN
IF START_UP THEN --初始化開始
FOR J IN ROM’RANGE LOOP
READLINE(ROMIN,1);
READ(1,ROM(J));
END LOOP;
START_UP:=FALSE; --初始化結束
END IF;
ADR_IN<=CONV_INTEGER(ADR); --將向量轉化成整數
IF(EN=‘1’)THEN
DOUT<=ROM(ADR_IN);
ELSE
DOUT<=“ZZZZ”;
END IF;
END PROCESS;
END ARCHITECTURE ART;
6.7.2 讀寫存儲器SRAM的設計
RAM和ROM的主要區別在于RAM描述上有讀和寫兩種操作,而且在讀寫上對時間有較嚴格的要求。下面我們給出一個8×8位的雙口SRAM的VHDL描述實例,如圖6.8所示。
圖6. 8 雙口SRAM
【例6.17】 用VHDL設計一個8×8位的雙口SRAM。
--DPRAM.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY DPRAM IS
GENERIC(WIDTH:INTEGER :=8;
DEPTH:INTEGER :=8;
ADDER:INTEGER :=3);
PORT(DATAIN:IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
DATAOUT:OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
CLOCK:IN STD_LOGIC;
WE,RE:IN STD_LOGIC;
WADD:IN STD_LOGIC_VECTOR(ADDER-1 DOWNTO 0);
RADD:IN STD_LOGIC_VECTOR(ADDER-1 DOWNTO 0));
END ENTITY DPRAM;
ARCHITECTURE ART OF DPRAM IS
TYPE MEM IS ARRAY(DEPTH-1 TO 0) OF
STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
SIGNAL RAMTMP:MEM;
BEGIN
--寫進程
PROCESS(CLOCK) IS
BEGIN
IF (CLOCK'EVENT AND CLOCK='1') THEN
IF(WE='1')THEN
RAMTMP(CONV_INTEGER(WADD))<=DATAIN;
END IF;
END IF;
END PROCESS;
--讀進程
PROCESS(CLOCK) IS
BEGIN
IF(CLOCK'EVENT AND CLOCK='1')THEN
IF (RE='1') THEN
DATAOUT<=RAMTMP(CONV_INTEGER(RADD));
END IF;
END IF;
END PROCESS;
END ARCHITECTURE ART;
6.8 輸入電路的設計
6.8.1 鍵盤掃描電路的設計
計算機控制系統中,數據和控制信號的輸入主要使用鍵盤。下面給出—個鍵盤掃描電路VHDL描述。
【例6.18】 用VHDL設計一個鍵盤掃描電路。
-- KSCAN.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY KSCAN IS
PORT(CLK: IN STD_LOGIC;
KIN1,KIN2 : IN STD_LOGIC;
LEDA,LEDB,LEDC: OUT STD_LOGIC;
LEDD : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END KSCAN;
ARCHITECTURE HAV OF KSCAN IS
SIGNAL SEG : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL SEL : STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL KNUM : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL COUNT: STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL COUNT0: STD_LOGIC;
BEGIN
LEDD<=SEG;
PROCESS(CLK)
BEGIN
IF CLK’EVENT AND CLK=‘1’ THEN
COUNT<=COUNT+1;
END IF;
END PROCESS;
COUNT0<=COUNT(0);
PROCESS(COUNT0,COUNT,KIN1,KIN2)
BEGIN
IF COUNT0’EVENT AND COUNT0=‘1’THEN
IF (KIN2=‘0’) AND COUNT(1)=‘0’THEN
KNUM<=‘1’ & COUNT(4 DOWNTO 2);
ELSIF (KIN1=‘0’) AND COUNT(1)=‘0’THEN
KNUM<=‘0’ & COUNT (4 DOWNTO 2);
END IF;
END IF;
END PROCESS;
SEL<=COUNT (4 DOWNTO 2);
PROCESS(KNUM)
BEGIN
CASE KNUM IS
WHEN “0000” => SEG<=“00111111”;
WHEN “0001” => SEG<=“00000110”;
WHEN “0010” => SEG<=“01011011”;
WHEN “0011” => SEG<=“01001111”;
WHEN “0100” => SEG<=“01100110”;
WHEN “0101” => SEG<=“01101101”;
WHEN “0110” => SEG<=“01111101”;
WHEN “0111” => SEG<=“00000111”;
WHEN “1000” => SEG<=“01111111”;
WHEN “1001” => SEG<=“01101111”;
WHEN “1010” => SEG<=“01110111”;
WHEN “1011” => SEG<=“01111100”;
WHEN “1100” => SEG<=“00111001”;
WHEN “1101” => SEG<=“01011110”;
WHEN “1110” => SEG<=“01111001”;
WHEN “1111” => SEG<=“01110001”;
WHEN OTHERS => SEG<=“00000000”;
END CASE ;
END PROCESS;
LEDA<=SEL(0);
LEDB<=SEL(1);
LEDC<=SEL(2);
END HAV;
6.8.2 鍵盤接口電路的設計
PS/2鍵盤接口通常使用專用芯片實現。由于PS/2鍵盤或鼠標串行輸出信號速度較高,普通單片機無法接收,現利用VHDL在目標器件FPGA/CPLD上實現一個鍵碼接收部分。PS/2接口的鍵盤每按下一個鍵,該鍵的掃描碼即以十六進制形式顯示在數碼管上。以下為接收PS/2鍵盤信號的VHDL邏輯描述。
【例6.20】 用VHDL設計一個接收PS/2鍵盤信號的接口電路。
-- KB2PCL.VHD
LIBRARY IEEE;
USE IEEE.STD_LOG1C_1164.ALL;
ENTITY KB2PCL IS
PORT (SYSCLK:IN STD_LOGIC;RESET:IN STD_LOGIC;
KBCLK: IN STD_LOGIC;KBDATA:IN STD_LOGIC;
PDATA: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
PARITY:OUT STD_LOGIC;DTOE:BUFFER STD_LOGIC);
END KB2PC1;
ARCHITECTURE ONE OF KB2PC1 IS
SIGNAL COSTATE:STD_LOGIC_VECTOR(1 DOWNTO 0);
SIGNAL SPDATA:STD_LOGIC_VECTOR(8 DOWNTO 0);
SIGNAL START,SWTO02,RECVEN:STD_LOGIC;
SIGNAL CNT8:INTEGER RANGE 0 TO 15;
BEGIN
SLRL:PROCESS(RESET, KBCLK,KBDATA,STAFF,COSTATE )
BEGIN
IF RESET = ‘1’ THEN
START <= ‘0’;
ELSIF KBCLK’EVENT AND KBCLK = ‘0’ THEN
IF COSTATE = “00” AND KBDATA = ‘0’ THEN
STAFF <= ‘1’;
END IF;
END IF;
END PROCESS;
STR2:PROCESS(RESET, KBCLK,KBDATA,STAFF,COSTATE)
BEGIN
IF RESET =‘1’ THEN
SWTO02 <=‘0’;
ELSIF KBCLK’EVENT AND KBCLK =‘1’ THEN
IF COSTATE = “00” AND START = ‘1’ AND KBDATA = ‘0’ THEN
SWTO02 <=‘1’;
END IF;
END IF;
END PROCESS;
CHSTATE:PROCESS(RESET,SYSCLK,COSTATE,SWTO02)
BEGIN
IF RESET =‘1’ THEN
COSTATE <=“00”;
ELSIF SYSCLK’EVENT AND SYSCLK =‘1’ THEN
IF SWTO02 = ‘1’ THEN
COSTATE <= “01”;
ELSIF CNT8 = 9 THEN
COSTATE <= “10”;
END IF;
END IF;
END PROCESS;
RECV:PROCESS(RESET,KBCLK,KBDATA,COSTATE )
BEGIN
IF RESET=‘1’ THEN
CNT8 <= 0;SPDATA <= “000000000”;
ELSIF KBCLK’EVENT AND KBCLK = ‘0’ THEN
IF COSTATE= “01” THEN
IF CNT8/=9 THEN
SPDATA(7 DOWNTO 0 )<= SPDATA(8 DOWNTO 1);
SPDATA(8)<= KBDATA;
CNT8 <= CNT8 + 1;
END IF;
END IF;
END IF;
END PROCESS;
RECVEND:PROCESS(RESET,KBCLK,RECVEN,COSTATE )
BEGIN
IF RESET =‘1’ THEN
DTOE <= ‘0’;
ELSIF KBCLK’EVENT AND KBCLK =‘1’ THEN
IF CNT8 = 9 AND COSTATE = “01” THEN
DTOE <=‘1’;END IF;
END IF;
END PROCESS;
PARITY <= SPDATA(8);PDATA <= SPDATA(7 DOWNTO 0);
END ONE;
6.9 顯示電路的設計
常用的顯示器件有發光二極管,數碼管,液晶顯示器等,其中最常用的為數碼管。數碼管顯示數據的方式有靜態顯示和動態顯示之分。所謂靜態顯示,就是將被顯示的數據的BCD碼,通過各自的4-7/8顯示譯碼器譯碼后,分別接到顯示譯碼器的顯示驅動段a-g(p),而公共端COM則根據數碼管的類型(共陰/共陽)分別接GND/VCC。動態顯示,就是將被顯示的數據的BCD碼,按照一定的變化頻率,在不同的時刻周期性地分別送到一個數據總線上,再通過一個公共的4-7/8顯示譯碼器譯碼后,接到多個顯示譯碼器的公共顯示驅動段a-g(p)上,同時,在不同的時刻周期性地選通對應的數碼管的公共端COM。
6.9.1 數碼管靜態顯示電路的設計
七段數碼顯示器由7根顯示碼管組成,對每一根碼管,用一位二進制表示。若該數碼管的為共陰數碼管,則該位為1時,表示此碼管發光,如為0,表示此碼管不發光,對7根碼管編號。共陽數碼管則正好相反。下面用一個7位二進制數表示一個七段顯示器的編碼,其VHDL程序段描述如下:
CASE CNT4B IS
WHEN 0=> DOUT <= “0111111”;
WHEN 1=> DOUT <= “0000110”;
WHEN 2=> DOUT <= “1011011”;
WHEN 3=> DOUT <= “1001111”;
WHEN 4=> DOUT <= “1100110”;
WHEN 5=> DOUT <= “1101101”;
WHEN 6=> DOUT <= “1111101”;
WHEN 7=> DOUT <= “0000111”;
WHEN 8=> DOUT <= “1111111”;
WHEN 9=> DOUT <= “1101111”;
WHEN OTHERS=> DOUT <= “0000000”;
END CASE;
下面給出一個4位二進制加法計數器靜態顯示的VHDL程序。
【例6.21】 用VHDL設計一個4位二進制加法計數器,并將計數結果用7段LED顯示數碼管進行靜態顯示。
--CNTDISPLAY.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY CNTDISPLAY IS
PORT (CLK:IN STD_LOGIC;
DOUT:OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END DECLED;
ARCHITECTURE BEHAV OF CNTDISPLAY IS
SIGNAL CNT4B:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(CLK)
BEGIN
IF CLK’EVENT AND CLK =‘1’ THEN
CNT4B <= CNT4B +1;
END IF;
END PROCESS;
PROCESS(CNT4B)
BEGIN
CASE CNT4B IS
WHEN “0000”=> DOUT <= “0111111”;
WHEN “0001”=> DOUT <= “0000110”;
WHEN “0010”=> DOUT <= “1011011”;
WHEN “0011”=> DOUT <= “1001111”;
WHEN “0100”=> DOUT <= “1100110”;
WHEN “0101”=> DOUT <= “1101101”;
WHEN “0110”=> DOUT <= “1111101”;
WHEN “0111”=> DOUT <= “0000111”;
WHEN “1000”=> DOUT <= “1111111”;
WHEN “1001”=> DOUT <= “1101111”;
WHEN “1010”=> DOUT <= “1110111”;
WHEN “1011”=> DOUT <= “1111100”;
WHEN “1100”=> DOUT <= “0111001”;
WHEN “1101”=> DOUT <= “1011110”;
WHEN “1110”=> DOUT <= “1111001”;
WHEN “1111”=> DOUT <= “1110001”;
WHEN OTHERS=> DOUT <= “0000000”;
END CASE;
END PROCESS;
END BEHAV;
6.9.2 數碼管動態顯示電路的設計
下面我們就通過一個例子來說明數據動態掃描的工作原理和VHDL程序的設計方法。
【例6.22】用VHDL設計一個8位二進制并行半加器,要求將被加數、加數和加法運算和用動態掃描的方式在共陰數碼管上同時顯示出,該數據動態掃描顯示電路的外圍器件接線圖如圖6.9所示。
圖6.9?數據動態掃描顯示電路外圍器件接線圖
--DISPLAY.VHD
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
--實體說明
ENTITY DISPLAY IS
PORT(CLK:IN STD_LOGIC; --動態掃描顯示時鐘,24HZ以上
AIN: IN STD_LOGIC_VECTOR(7 DOWNTO 0); --8位被加數
BIN: IN STD_LOGIC_VECTOR(7 DOWNTO 0); --8位加數
SUM0,SUM1,SUM2:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--仿真觀測輸出
COM:OUT STD_LOGIC_VECTOR(6 DOWNTO 0);--數碼管COM端的選擇輸出端
SEG: OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --數碼管8段顯示驅動輸出端
END ENTITY DISPLAY;
ARCHITECTURE ART OF DISPLAY IS
SIGNAL AA, BB,SINT: STD_LOGIC_VECTOR(8 DOWNTO 0);
SIGNAL CNT:STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL BCD:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
--進行運算前的準備及加法運算
AA<='0'&AIN;
BB<='0'&BIN;
SINT<=AA+BB;
SUM0<=SINT(3 DOWNTO 0); --運算結果的仿真觀測輸出
SUM1<=SINT(7 DOWNTO 4); --運算結果的仿真觀測輸出
SUM2<="000"&SINT(8); --運算結果的仿真觀測輸出
--產生動態掃描顯示的控制信號
PROCESS(CLK)
BEGIN
IF CLK'EVENT AND CLK='1' THEN
IF CNT="111" THEN
CNT<="000";
ELSE
CNT<=CNT+'1';
END IF ;
END IF;
END PROCESS;
PROCESS(CNT)
BEGIN
--顯示數據的選擇,對應顯示數碼管公共端的選通,低電平有效
CASE CNT IS
WHEN "000" =>BCD<=AIN(3 DOWNTO 0);COM<="1111110";
WHEN "001" =>BCD<=AIN(7 DOWNTO 4);COM<="1111101";
WHEN "010" =>BCD<=BIN(3 DOWNTO 0);COM<="1111011";
WHEN "011" =>BCD<=BIN(7 DOWNTO 4);COM<="1110111";
WHEN "100" =>BCD<=SINT(3 DOWNTO 0);COM<="1101111";
WHEN "101" =>BCD<=SINT(7 DOWNTO 4);COM<="1011111";
WHEN "110" =>BCD<="000"&SINT(8);COM<="0111111";
WHEN OTHERS=>BCD<="0000";COM<="1111111";
END CASE;
--將BCD碼轉換成數碼管的8段驅動信息,高電平有效
CASE BCD IS
WHEN "0000" => SEG<="00111111";
WHEN "0001" => SEG<="00000110";
WHEN "0010" => SEG<="01011011";
WHEN "0011" => SEG<="01001111";
WHEN "0100" => SEG<="01100110";
WHEN "0101" => SEG<="01101101";
WHEN "0110" => SEG<="01111101";
WHEN "0111" => SEG<="00000111";
WHEN "1000" => SEG<="01111111";
WHEN "1001" => SEG<="01101111";
WHEN "1010" => SEG<="01110111";
WHEN "1011" => SEG<="01111100";
WHEN "1100" => SEG<="00111001";
WHEN "1101" => SEG<="01011110";
WHEN "1110" => SEG<="01111001";
WHEN "1111" => SEG<="01110001";
WHEN OTHERS => SEG<="00000000";
END CASE ;
END PROCESS;
END ARCHITECTURE ART;
6.9.2 液晶顯示控制電路的設計
液晶顯示是一種將液晶顯示器件、連接件、集成電路、PCB線路板、背光源、結構件裝配在一起的組件。下面給出—個液晶顯示控制電路的VHDL描述。
【例6.23】 用VHDL設計—個液晶顯示控制電路。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY LCD IS
PORT(DP1,DP2,DP3:IN STD_LOGIC;
RS,CS1,CS2: OUT STD_LOGIC;
LCDE:OUT STD_LOGIC;
RW:OUT STD_LOGIC);
END LCD;
ARCHITECTURE HAV OF LCD IS
BEGIN
PROCESS(DP1,DP2,DP3)
BEGIN
IF(DP1=“0” AND DP2=“0” AND DP3=“0”) THEN
LCDE<=“1”;RS<=“0”;RW<=“1”;CS1<=“1”;CS2<=“0”;
ELSIF(DP1=“0” AND DP2=“0” AND DP3=“1”)THEN
LCDE<=“1”;RS<=“0”;RW<=“0”;CS1<=“1”;CS2<=“0”;
ELSIF(DP1=“0” AND DP2=“1” AND DP3=“0”)THEN
LCDE<=“0”;RS<=“1”;RW<=“1”;CS1<=“1”;CS2<=“0”;
ELSIF(DP1=“0” AND DP2=“1” AND DP3=“1”)THEN
LCDE<=“1”;RS<=“1”;RW<=“0”;CS1<=“1”;CS2<=“0”;
ELSIF(DP1=“1” AND DP2=“0” AND DP3=“0”)THEN
LCDE<=“1”;RS<=“0”;RW<=“1”;CS1<=“0”;CS2<=“1”;
ELSIF(DP1=“1” AND DP2=“0” AND DP3=“1”)THEN
LCDE<=“1”;RS<=“0”;RW<=“0”;CS1<=“0”;CS2<=“1”;
ELSIF(DP1=“1” AND DP2=“1” AND DP3=“0”)THEN
LCDE<=“0”;RS<=“1”;RW<=“1”;CS1<=“0”;CS2<=“1”;
ELSIF(DP1=“1” AND DP2=“1” AND DP3=“1”)THEN
LCDE<=“1”;RS<=“1”;RW<=“0”;CS1<=“0”;CS2<=“1”;
ELSE
LCDE<=“0”;RS<=“1”;RW<=“1”;CS1<=“0”;CS2<=“0”;
END IF;
END PROCESS;
END HAV;
評論