?? fpga_7279.vhd
字號(hào):
--FPGA控制7279的程序
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_ARITH.all;
use IEEE.std_logic_UNSIGNED.all;
entity FPGA_7279 is
port (
--以下是引腳信號(hào)
CLK :IN STD_LOGIC; --系統(tǒng)時(shí)鐘
RST_N :IN STD_LOGIC; --系統(tǒng)復(fù)位
CLK_S :IN STD_LOGIC; --7279時(shí)序的狀態(tài)機(jī)時(shí)鐘,周期為20us
--外部控制接口與本模塊之間的信號(hào)
WR_N :IN STD_LOGIC; --外部寫信號(hào)
RD_N :IN STD_LOGIC; --外部讀信號(hào)
KEY_EN :OUT STD_LOGIC; --存在有效鍵值, 高電平為存在有效鍵值, 外部接口讀走數(shù)據(jù)后變低
ADDR :IN STD_LOGIC_VECTOR(2 downto 0); --地址信號(hào)
D_BUS :IN STD_LOGIC_VECTOR(7 downto 0); --指令,數(shù)據(jù)輸入及鍵盤值輸出
--與7279之間的信號(hào)
KEY7279 :IN STD_LOGIC; --7279的鍵盤信號(hào),有鍵按下時(shí)為低電平,平時(shí)為高電平
CLK7279 :OUT STD_LOGIC; --7279的時(shí)鐘信號(hào)
CS7279 :OUT STD_LOGIC; --7279的片選信號(hào)
DAT7279 :INOUT STD_LOGIC; --7279數(shù)據(jù)信號(hào)
OUT7279 :OUT STD_LOGIC_VECTOR(7 downto 0) --7279鍵盤鍵值輸出信號(hào),測(cè)試時(shí)用
);
end FPGA_7279;
ARCHITECTURE behav OF FPGA_7279 IS
CONSTANT RST_7279 : std_logic_vector (7 downto 0) := x"A4"; --復(fù)位(清除)指令
CONSTANT TST_7279 : std_logic_vector (7 downto 0) := x"BF"; --測(cè)試指令
CONSTANT SL_7279 : std_logic_vector (7 downto 0) := x"A1"; --左移指令
CONSTANT SR_7279 : std_logic_vector (7 downto 0) := x"A0"; --右移指令
CONSTANT RL_7279 : std_logic_vector (7 downto 0) := x"A3"; --循環(huán)左移指令
CONSTANT RR_7279 : std_logic_vector (7 downto 0) := x"A2"; --循環(huán)右移指令
CONSTANT RDKY_7279 : std_logic_vector (7 downto 0) := x"15"; --讀鍵盤數(shù)據(jù)指令
CONSTANT DC0_7279 : std_logic_vector (7 downto 0) := x"80"; --下載數(shù)據(jù)且按方式0譯碼, 1 0 0 0 0 a2 a1 a0 ,后3位用來指定數(shù)碼管
CONSTANT DC1_7279 : std_logic_vector (7 downto 0) := x"C8"; --下載數(shù)據(jù)且按方式1譯碼, 1 1 0 0 1 a2 a1 a0
CONSTANT NDC_7279 : std_logic_vector (7 downto 0) := x"90"; --下載數(shù)據(jù)不譯碼, 1 0 0 1 0 a2 a1 a0
CONSTANT FL_7279 : std_logic_vector (7 downto 0) := x"88"; --閃爍控制
CONSTANT HD_7279 : std_logic_vector (7 downto 0) := x"98"; --消隱控制
CONSTANT SGDSP_7279 : std_logic_vector (7 downto 0) := x"E0"; --段點(diǎn)亮指令
CONSTANT SGCLR_7279 : std_logic_vector (7 downto 0) := x"C0"; --段關(guān)閉指令
SIGNAL cmd_7279 : STD_LOGIC_VECTOR (7 downto 0); --保存讀進(jìn)來的操作命令
SIGNAL key_7279 : STD_LOGIC_VECTOR (7 downto 0); --保存從7279讀出來的按鍵值
SIGNAL key_7279_tmp : STD_LOGIC_VECTOR (7 downto 0); --從7279讀鍵值,加一級(jí)緩存,鍵有效方才放入鍵值寄存器
SIGNAL cmd_tmp : STD_LOGIC_VECTOR (7 downto 0); --保存操作命令到移位緩存
SIGNAL cmd_tmp1 : STD_LOGIC_VECTOR (7 downto 0); --進(jìn)入START狀態(tài)后,操作命令緩存,因?yàn)?字節(jié)指令中讀鍵盤操作有所特殊,需要判斷
SIGNAL data_tmp : STD_LOGIC_VECTOR (7 downto 0); --進(jìn)入START狀態(tài)后,操作數(shù)據(jù)緩存
SIGNAL data_tmp1 : STD_LOGIC_VECTOR (7 downto 0); --保存操作數(shù)據(jù)到移位緩存
SIGNAL scmd_cnt : INTEGER RANGE 0 to 7; --命令字移位計(jì)數(shù)器
SIGNAL sdata_cnt : INTEGER RANGE 0 to 7; --數(shù)據(jù)字移位計(jì)數(shù)器,與鍵盤值讀取計(jì)數(shù)器復(fù)用
SIGNAL delay_cnt : INTEGER RANGE 0 to 3;
SIGNAL seg_cnt : INTEGER RANGE 0 to 7; --數(shù)碼管計(jì)數(shù)器,從右到左一共8個(gè)數(shù)碼管
SIGNAL f_edge_cnt : INTEGER RANGE 0 to 10; --檢測(cè)到KEY7279后,延時(shí)計(jì)數(shù)器
SIGNAL key_flag : STD_LOGIC; --按鍵標(biāo)志,計(jì)數(shù)器溢出標(biāo)志
SIGNAL cmd_start : STD_LOGIC; --單字節(jié)指令判斷開始標(biāo)志
SIGNAL data_start : STD_LOGIC; --雙字節(jié)指令,由數(shù)據(jù)來判斷開始標(biāo)志
SIGNAL cmd_start_tmp : STD_LOGIC; --緩存單字節(jié)指令判斷開始標(biāo)志
SIGNAL data_start_tmp : STD_LOGIC; --緩存由數(shù)據(jù)來判斷開始標(biāo)志
TYPE SEG_Register IS ARRAY ( 0 To 7) of STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL seg_r :SEG_Register;
SIGNAL data_7279 :SEG_Register;
SIGNAL decode_bus :STD_LOGIC_VECTOR (7 downto 0); --從D_BUS讀進(jìn)數(shù)據(jù)來后,解碼
TYPE STATE_TYPE is (IDLE, START, START_DELAY, SHIFT_CMD_LOW,
SHIFT_CMD_HIGH, NEXT_DELAY, SHIFT_DATA_LOW, SHIFT_DATA_HIGH,
SHIFT_KEY_LOW, SHIFT_KEY_HIGH, SHIFT_KEY_HIGH1, FINISH );
signal state : STATE_TYPE;
TYPE STATE_TYPE1 IS (IDLE, START_WR, STOP);
SIGNAL state1: STATE_TYPE1;
BEGIN
OUT7279 <= key_7279;
--直接對(duì)7279控制的狀態(tài)機(jī)
process(CLK_S,RST_N)
begin
if (RST_N = '0') then
state <= IDLE;
key_7279 <= x"00";
CS7279 <= '1';
CLK7279 <= '0';
DAT7279 <= 'Z';
state <= IDLE;
elsif falling_edge(CLK_S) then
case state is
when IDLE =>
if (KEY7279 = '0') then
cmd_tmp <= RDKY_7279;--為了測(cè)試讀鍵盤操作
DAT7279 <= 'Z';
state <= START;
else
if (seg_cnt = 7) then
seg_cnt <= 0;
else
seg_cnt <= seg_cnt + 1;
end if;
cmd_tmp <= NDC_7279(7 downto 3) & CONV_STD_LOGIC_VECTOR(seg_cnt,3);
data_tmp <= data_7279(seg_cnt);
state <= START;
end if;
when START =>
delay_cnt <= 3;
CS7279 <= '0'; --7279片選置低,開始4次延時(shí),即80us
CLK7279 <= '0'; --設(shè)置時(shí)鐘為低
state <= START_DELAY;
--開始發(fā)送命令字-------------------------------------------------
when START_DELAY =>
if (delay_cnt > 1) then
delay_cnt <= delay_cnt - 1;
else
scmd_cnt <= 7; --80us延時(shí)結(jié)束,開始送命令字
state <= SHIFT_CMD_LOW;
end if;
when SHIFT_CMD_LOW => --1位數(shù)據(jù)送到數(shù)據(jù)線上
DAT7279 <= cmd_tmp1(scmd_cnt); --用命令字的二級(jí)緩存做
CLK7279 <= '1'; --時(shí)鐘信號(hào)由低變高
state <= SHIFT_CMD_HIGH;
when SHIFT_CMD_HIGH =>
CLK7279 <= '0'; --一外時(shí)鐘后,時(shí)鐘信號(hào)由高變低
if (scmd_cnt > 0) then
scmd_cnt <= scmd_cnt - 1;
state <= SHIFT_CMD_LOW;
--當(dāng)為雙字節(jié)操作時(shí),交替間斷的延時(shí)
elsif (data_start_tmp = '1') or (cmd_tmp1 = RDKY_7279) then
delay_cnt <= 3;
state <= NEXT_DELAY;
else
state <= FINISH;
end if;
--開始發(fā)送8位數(shù)據(jù)------------------------------------------------
when NEXT_DELAY =>
if (delay_cnt >1) then
delay_cnt <= delay_cnt - 1;
elsif (cmd_tmp = RDKY_7279) then --當(dāng)為鍵盤接收指令時(shí)
sdata_cnt <= 7;
state <= SHIFT_KEY_LOW; --進(jìn)行讀取按鍵
else
sdata_cnt <= 7;
state <= SHIFT_DATA_LOW; --80us延時(shí)結(jié)束,進(jìn)入數(shù)據(jù)傳輸
end if;
when SHIFT_DATA_LOW => --1位數(shù)據(jù)送到數(shù)據(jù)線上
DAT7279 <= data_tmp1(sdata_cnt);
CLK7279 <= '1'; --時(shí)鐘信號(hào)由低變高
state <= SHIFT_DATA_HIGH;
when SHIFT_DATA_HIGH =>
CLK7279 <= '0'; --時(shí)鐘信號(hào)由高變低
if (sdata_cnt > 0) then
sdata_cnt <= sdata_cnt - 1;
state <= SHIFT_DATA_LOW;
else
state <= FINISH;
end if;
--讀取按鍵值-----------------------------------------------------
when SHIFT_KEY_LOW =>
CLK7279 <= '1'; --時(shí)鐘信號(hào)由低變高,DAT7279變?yōu)檩斎霠顟B(tài)
DAT7279 <= 'Z';
state <= SHIFT_KEY_HIGH;
when SHIFT_KEY_HIGH => --保證一個(gè)時(shí)鐘周期的建立時(shí)間
--key_7279(sdata_cnt) <= DAT7279;
key_7279_tmp(sdata_cnt) <= DAT7279;
state <= SHIFT_KEY_HIGH1;
when SHIFT_KEY_HIGH1 =>
CLK7279 <= '0'; --低電平后為一個(gè)時(shí)鐘周期的保持時(shí)間
if (sdata_cnt > 0) then
sdata_cnt <= sdata_cnt - 1;
state <= SHIFT_KEY_LOW;
else
if (KEY7279 = '0') then --當(dāng)讀取完后,KEY7279仍為0才能確定讀取的為有效值
key_7279 <= key_7279_tmp;
end if;
state <= FINISH;
end if;
--結(jié)束操作-------------------------------------------------------
when FINISH =>
CS7279 <= '1'; --7279片選置高,結(jié)束操作
state <= IDLE;
when others =>
NULL;
end case;
end if;
end process;
process(CLK_S,RST_N)
begin
if (RST_N = '0') then
cmd_start <= '0';
data_start <= '0';
elsif falling_edge(CLK_S) then
case state is
when IDLE =>
if (KEY7279 = '0') then
cmd_start <= '1'; --為了測(cè)試
data_start <= '0'; --為了測(cè)試
else
cmd_start <= '0'; --為了測(cè)試
data_start <= '1'; --為了測(cè)試
end if;
when START => --IDLE =>
cmd_tmp1 <= cmd_tmp; --為防止丟失雙字節(jié)指令,所以多加一級(jí)緩存
data_tmp1 <= data_tmp;
cmd_start_tmp <= cmd_start;
data_start_tmp <= data_start;
when others =>
NULL;
end case;
end if;
end process;
--讀鍵值標(biāo)志位
KEY_EN <= not key_flag; --高電平,鍵值有效,(一般用高電平表示有效,用沿的話一般用下降沿表示有效)
process(KEY7279,CLK,RST_N)
begin
if (RST_N = '0') then
key_flag <= '1';
elsif (RD_N = '0') then
key_flag <= '1'; --讀鍵值寄存器key_7279時(shí),清key_flag鍵值標(biāo)志
elsif rising_edge(KEY7279) then --7279上升沿時(shí),即按鍵已釋放
key_flag <= '0'; --key_flag下降沿,通知外部,可以讀鍵值了
end if;
end process;
--解碼模塊,從數(shù)據(jù)到顯示碼
decode_bus <= "00000000" when (D_BUS = "11111111") else --D_BUS為x"FF"時(shí),清除顯示
D_BUS(7) & "1111110" when (D_BUS(3 downto 0) = "0000") else --0,D_BUS(7)小數(shù)點(diǎn)位
D_BUS(7) & "0110000" when (D_BUS(3 downto 0) = "0001") else --1
D_BUS(7) & "1101101" when (D_BUS(3 downto 0) = "0010") else --2
D_BUS(7) & "1111001" when (D_BUS(3 downto 0) = "0011") else --3
D_BUS(7) & "0110011" when (D_BUS(3 downto 0) = "0100") else --4
D_BUS(7) & "1011011" when (D_BUS(3 downto 0) = "0101") else --5
D_BUS(7) & "1011111" when (D_BUS(3 downto 0) = "0110") else --6
D_BUS(7) & "1110000" when (D_BUS(3 downto 0) = "0111") else --7
D_BUS(7) & "1111111" when (D_BUS(3 downto 0) = "1000") else --8
D_BUS(7) & "1111011" when (D_BUS(3 downto 0) = "1001") else --9
D_BUS(7) & "1110111" when (D_BUS(3 downto 0) = "1010") else --a
D_BUS(7) & "0011111" when (D_BUS(3 downto 0) = "1011") else --b
D_BUS(7) & "1001110" when (D_BUS(3 downto 0) = "1100") else --c
D_BUS(7) & "0111101" when (D_BUS(3 downto 0) = "1101") else --d
D_BUS(7) & "1001111" when (D_BUS(3 downto 0) = "1110") else --e
D_BUS(7) & "1000111" when (D_BUS(3 downto 0) = "1111") else --f
"00000000";
--外部控制接口的寫操作
process(CLK,RST_N)
begin
if(RST_N = '0') then
for i in 0 to 7 loop
data_7279(i) <= x"00";
--data_7279(i) <= CONV_STD_LOGIC_VECTOR(i,8); --測(cè)試用
end loop;
elsif falling_edge(CLK) then
case state1 is
when IDLE =>
if (WR_N = '0') then --只有在WR_N與state狀態(tài)為IDLE時(shí),才允許接收命令
state1 <= START_WR;
end if;
when START_WR =>
if (WR_N = '0') then
--data_7279(CONV_INTEGER(ADDR)) <= D_BUS; --DC0_7279或DC1_7279
data_7279(CONV_INTEGER(ADDR)) <= decode_bus; --NDC_7279
else
state1 <= STOP;
end if;
when STOP =>
state1 <= IDLE;
when others =>
NULL;
end case;
end if;
end process;
END behav;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -