Victor Lee (WHUT)
设计汉字显示的控制器,读取EEPROM(ATMEL AT28C64B)中存储的汉字显示的数据,并在16*16的点阵上面显示出来,可以一个个字的显示和移动的显示。EEPROM工作速度在6.6M左右,所以我选取2.5M的时钟,关键在于设置地址读取信号,当地址线低5位从00000计数到11111刚好读出一个汉字,因此高7位就是汉字的位置。因为每次要读出16位的data,因此在低0位的时候读取的数据送到LED的低8位,在1位的时候读取的数据送到高8位,同时,将扫描信号和地址线的4~1位相同,这样,扫描一次就可以读取16位数据。于2005年5月25日设计完成,同时还要注意CPLD上面的引脚有些没有标的就不要用,程序设计如下:
------------------------------------------------------------
----------------------------------------------
--2005.05.25 ver0.1(done perfect)
--name:word show on the 16*16 led
--note:read data from the EEPROM 2864
--author:Victor Lee (WHUT)
----------------------------------------------
LIBRARY IEEE;
USE IEEE.Std_Logic_1164.ALL;
USE IEEE.Std_Logic_Arith.ALL;
USE IEEE.Std_Logic_Unsigned.ALL;
ENTITY e2prom IS
PORT(clk:IN STD_LOGIC; --FOR SYSTEM CLOCK 10Mhz
enc:IN STD_LOGIC;--FOR CPLD DATA OUT ENABLE
rst:IN STD_LOGIC;--FOR CPLD RESET
oer:OUT STD_LOGIC;--FOR EEPROM READ ENABLE,'0' are valid
cer:OUT STD_LOGIC;-FOR EEPROM CHIP SELECT ENABLE,'0' are valid
wer:OUT STD_LOGIC;--FOR EEPROM WRITE ENABLE,'0' are valid
led:OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
addr:OUT STD_LOGIC_VECTOR(11 DOWNTO 0);
--ADDRESS LOWER 4 DOWNTO 1 IS THE SCAN SIGNAL
--ADDRESS FOR THE EEPROM TO GET THE DATA
datar:IN STD_LOGIC_VECTOR(7 DOWNTO 0)); --DATAOUT FROM EEPROM
END e2prom;
ARCHITECTURE be OF e2prom IS
SIGNAL q:STD_LOGIC_VECTOR(18 DOWNTO 0);
SIGNAL d:STD_LOGIC_VECTOR(15 DOWNTO 0);--FOR SAVE DATA
SIGNAL ocr:STD_LOGIC;
SIGNAL sclk:STD_LOGIC;
SIGNAL counterh:STD_LOGIC_VECTOR(11 DOWNTO 5);
SIGNAL counterl:STD_LOGIC_VECTOR(4 DOWNTO 0);--ADDR
BEGIN
Free_Counter:BLOCK
BEGIN
PROCESS(clk)
BEGIN
IF clk'event AND clk='1' THEN
q<=q+1;
END IF;
END PROCESS;
sclk<=q(5);--for addr lower counter
cer<=ocr;
led<=d;
addr<=counterh&counterl;
END BLOCK Free_Counter;
Addressl:BLOCK --for a word read out
BEGIN
PROCESS(sclk,rst)
BEGIN
IF rst='1' THEN
counterl<="00000";
ELSIF sclk'event AND sclk='1' THEN
IF counterl="11111" THEN
counterl<="00000";
ELSE
counterl<=counterl+1;
END IF;
END IF;
END PROCESS;
END BLOCK Addressl;
Addressh:BLOCK--for word sel
BEGIN
PROCESS(q(18),rst,d(0))
BEGIN
IF rst='1' OR d(0)='1' THEN
counterh<="0000000";
ELSIF q(18)'event AND q(18)='1' THEN
IF enc='1' THEN
counterh<=counterh+1;
ELSE
counterh<=counterh;
END IF;
END IF;
END PROCESS;
END BLOCK Addressh;
Control_EEPROM:BLOCK
BEGIN
wer<='1';
PROCESS(clk,rst,sclk)
BEGIN
IF rst='1' THEN
oer<='1';
ocr<='1';
ELSE
oer<=not sclk;
ocr<=not sclk;
END IF;
END PROCESS;
END BLOCK Control_EEPROM;
Data:BLOCK
BEGIN
PROCESS(rst,clk)
BEGIN
IF rst='1' THEN
d<="0000000000000000";
ELSIF clk'event AND clk='1' THEN
IF counterl(0)='1' THEN
d(7 DOWNTO 0)<=datar;
d(15 DOWNTO 8)<="00000000";
ELSIF counterl(0)='0' THEN
d(15 DOWNTO 8)<=datar;
d(7 DOWNTO 0)<="00000000";
END IF;
END IF;
END PROCESS;
END BLOCK Data;
END be;
-----------------------------------------
现在需要完成的时动态显示,即滚动显示。
可以考虑在数据读出的时候,扫描信号不与数据信号对应,根据设置的频率进行改变。
滚动显示于2005.05.27日设计完毕,略微有些不足,在时序上面还需要多下功夫。可能是时序问题导致在显示“这是”和“谢谢”的时候会出现data为全FF的情况,使得无法通过判断d(0)是否是1来决定是否显示结束。而在以前静态显示的时候是可以的。多分析了一下时序,出现问题的地方少多了
addrl .00000.00001.00010.00011.00100.00101.00110.00111.
sclk ___---___---___---___---___---___---___---___---
ocr _---___---___---___---___---___---___---___---___---___
data .data1.data2.data3.data4.data5
scan xxx__-------------__________-------------__________
所以当时钟设置好以后,以ocr的上沿读取数据就是准确的
全部例程及相关解释如下:
----------------------------------------------
--2005.05.25 ver0.1(done perfect)
--name:word show on the 16*16 led
--note:read data from the EEPROM 2864
--author:Victor Lee (WHUT)
----------------------------------------------
LIBRARY IEEE;
USE IEEE.Std_Logic_1164.ALL;
USE IEEE.Std_Logic_Arith.ALL;
USE IEEE.Std_Logic_Unsigned.ALL;
ENTITY e2prom IS
GENERIC(word:integer:=37);--FOR word count
PORT( clk:IN STD_LOGIC;--FOR SYSTEM CLOCK 10Mhz
enc:IN STD_LOGIC;--FOR CPLD DATA OUT ENABLE
rst:IN STD_LOGIC;--FOR CPLD RESET
oer:OUT STD_LOGIC;--FOR EEPROM READ ENABLE,'0' are valid
cer:OUT STD_LOGIC;--FOR EEPROM CHIP SELECT ENABLE,'0' are valid
wer:OUT STD_LOGIC;--FOR EEPROM WRITE ENABLE,'0' are valid
led:OUT STD_LOGIC_VECTOR(15 DOWNTO 0);--TO SAVE THE PIN,JUST SHOW A HALF AT A TIME
addr:OUT STD_LOGIC_VECTOR(11 DOWNTO 0);
--ADDRESS FOR THE EEPROM TO GET THE DATA
enscroll:IN STD_LOGIC;
scan:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--for row scan
datar:IN STD_LOGIC_VECTOR(7 DOWNTO 0)); --DATAOUT FROM EEPROM
END e2prom;
ARCHITECTURE be OF e2prom IS
SIGNAL q:STD_LOGIC_VECTOR(16 DOWNTO 0);--for free counter
SIGNAL qh:STD_LOGIC_VECTOR(26 DOWNTO 16);--for scroll scan
SIGNAL d:STD_LOGIC_VECTOR(15 DOWNTO 0);--FOR line DATA
SIGNAL ocr:STD_LOGIC;for EEPROM 2864
SIGNAL sclk:STD_LOGIC;
SIGNAL scans:STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL counterh:STD_LOGIC_VECTOR(11 DOWNTO 5);
SIGNAL counterl:STD_LOGIC_VECTOR(4 DOWNTO 0);--ADDR
SIGNAL addrl:STD_LOGIC_VECTOR(4 DOWNTO 0);--for a word show, read out 32 bit complately
SIGNAL scroll:STD_LOGIC_VECTOR(3 DOWNTO 0);--FOR WORD SCROLL
SIGNAL addrh:STD_LOGIC_VECTOR(11 DOWNTO 5);--for word select
BEGIN
Free_Counter:BLOCK
BEGIN
PROCESS(clk,rst,d)
BEGIN
IF rst='1' THEN-- OR d(0)='1' THEN
q(16 DOWNTO 0)<="00000000000000000";
ELSIF clk'event AND clk='1' THEN
q<=q+1;
END IF;
END PROCESS;
sclk<=q(5);--for addr lower counter
cer<=ocr;
led<=d;
addr<=addrh&addrl;
END BLOCK Free_Counter;
Free_Counter_h:BLOCK
BEGIN
PROCESS(q,rst,d)
BEGIN
IF rst='1' THEN--d(7 DOWNTO 0)="1111111" THEN-- OR d(0)='1' THEN
qh(26 DOWNTO 16)<="00000000000";
ELSIF counterh=word+1 THEN
qh(26 DOWNTO 20)<="0000000";
ELSIF q(16)'event AND q(16)='1' THEN
IF enc='1' THEN
qh<=qh+1;
END IF;
END IF;
scroll<=qh(19 DOWNTO 16);
counterh<=qh(26 DOWNTO 20);
END PROCESS;
END BLOCK Free_Counter_h;
Addressl:BLOCK --for a word read out
BEGIN
PROCESS(sclk,rst)
BEGIN
IF rst='1' THEN
counterl<="00000";
ELSIF sclk'event AND sclk='1' THEN
counterl<=counterl+1;
END IF;
END PROCESS;
END BLOCK Addressl;
PROCESS(clk)
BEGIN
IF clk'event AND clk='1' THEN
IF enscroll='1' THEN
addrl<=(counterl(4 DOWNTO 1)+scroll)&counterl(0);--key step 1:for scan scroll
ELSE
addrl<=counterl;
END IF;
END IF;
END PROCESS;
Flag:PROCESS(clk) --key step 2:for word scroll
BEGIN
IF clk'event AND clk='1' THEN
IF scroll="0000" THEN
IF scans(4 DOWNTO 1)="1111" THEN
IF counterh=word THEN
addrh<="0000000";
ELSE
addrh<=counterh+1;--下个汉字的地址
END IF;
ELSE
addrh<=counterh;--上个汉字的地址
END IF;
ELSIF scans(4 DOWNTO 1)<(("1111"-scroll)+1) THEN
addrh<=counterh;
ELSE
IF counterh=word THEN
addrh<="0000000";
ELSE
addrh<=counterh+1;--下个汉字的地址
END IF;
END IF;
END IF;
END PROCESS Flag;
Control_EEPROM:BLOCK
--SIGNAL qs:STD_LOGIC_VECTOR(4 DOWNTO 0);
BEGIN
wer<='1';
PROCESS(q,rst,sclk)
BEGIN
IF rst='1' THEN
oer<='1';
ocr<='1';
ELSIF q(1)'event AND q(1)='1' THEN
oer<=NOT sclk;--ocr;
ocr<=NOT sclk;
END IF;
END PROCESS;
END BLOCK Control_EEPROM;
scan_critical:BLOCK
BEGIN
PROCESS(q(4))
BEGIN
IF q(4)'event AND q(4)='0' THEN
scans<=counterl;
END IF;
END PROCESS;
END BLOCK scan_critical;
Data:BLOCK
BEGIN
PROCESS(rst,ocr,scans)
BEGIN
IF rst='1' THEN
d<="0000000000000000";
ELSIF ocr'event AND ocr='1' THEN
scan<=scans(4 DOWNTO 1);
IF scans(0)='1' THEN
d(7 DOWNTO 0)<=datar;
d(15 DOWNTO 8)<="00000000";
ELSIF scans(0)='0' THEN
d(15 DOWNTO 8)<=datar;
d(7 DOWNTO 0)<="00000000";
END IF;
END IF;
END PROCESS;
END BLOCK Data;
END be;