我做过MC6850串口通信模块(简化版),可完成与PC机通信功能,设置参数固定。里面是核心VHDL代码。完整代码稍后发给你。
本代码不包括CPU接口部分,它是专为68K异步总线设计的,不通用。
以下代码可以完成串并,并串,串口协议等功能。我个人认为在CPLD上实现完整8250芯片功
能没有必要(还不如直接买8250便宜呢),你可以固定参数(波特率9600、校验位1、停止
位0……),这样可简化设计节省投资。特别注意串口协议的类状态机,3中取2的实现。在
一本CPLD设计的书上(名字忘了)有此程序介绍,我的程序对它做了一些小改动。在
MAX7128上实现。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY mc6850 IS
PORT(cs,e,rw,rs,rx,clk,reset,c4m:IN STD_LOGIC;
d:INOUT STD_LOGIC_VECTOR(7 DOWNTO 0);
tx:OUT STD_LOGIC);
END mc6850;
ARCHITECTURE rtl OF mc6850 IS
SIGNAL scit,scir:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL sh_t,sl_t,sh_r,sl_r:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL rst,cs0,cs1,rd0,rd1,rd2,rxd:STD_LOGIC;
SIGNAL trd:STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL cr,sr,td,rd:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL dout:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL tdempty,rdfull:STD_LOGIC; --'1' means valid
SIGNAL csi,te:STD_LOGIC;
--SIGNAL dshift:STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL tt:STD_LOGIC;
BEGIN
--tx parallel/serial
PROCESS(sh_t)
BEGIN
CASE sh_t IS
WHEN "0110"=> tx<='0';
WHEN "0111"=> tx<=td(0);
WHEN "1000"=> tx<=td(1);
WHEN "1001"=> tx<=td(2);
WHEN "1010"=> tx<=td(3);
WHEN "1011"=> tx<=td(4);
WHEN "1100"=> tx<=td(5);
WHEN "1101"=> tx<=td(6);
WHEN "1110"=> tx<=td(7);
WHEN "1111"=> tx<='1';
WHEN OTHERS=> tx<='1';
END CASE;
END PROCESS;
--rx serial/parallel
PROCESS(rst,reset,clk)
BEGIN
IF(rst='0' OR reset='0') THEN
dout<="00000000";
ELSIF(clk'EVENT AND clk='1') THEN
IF(sh_r>="0111" AND sh_r<="1111" AND
sl_r="1001") THEN
dout(7)<=rxd;
FOR i IN 0 TO 6 LOOP
dout(i)<=dout(i+1);
END LOOP;
END IF;
END IF;
END PROCESS;
--select 2 from 3
PROCESS(clk)
BEGIN
IF(clk'EVENT AND clk='1') THEN
IF(sl_r="0110") THEN
rd0<=rx;
ELSIF(sl_r="0111") THEN
rd1<=rx;
ELSIF(sl_r="1000") THEN
rd2<=rx;
END IF;
END IF;
END PROCESS;
trd<=rd2&rd1&rd0;
PROCESS
BEGIN
IF(trd="011" OR trd="101" OR trd="110" OR trd="111") THEN
rxd<='1';
ELSE
rxd<='0';
END IF;
END PROCESS;
--------------------------------------------------------------------
--------------------------------------------------------------------
--rx tx counter
sh_r<=scir(7 DOWNTO 4);
sl_r<=scir(3 DOWNTO 0);
sh_t<=scit(7 DOWNTO 4);
sl_t<=scit(3 DOWNTO 0);
--rx counter
PROCESS(rst,reset,clk)
BEGIN
IF(rst='0' OR reset='0') THEN
scir<="00000000";
ELSIF(clk'EVENT AND clk='1') THEN
IF(scir<="01101111" AND rx='0') THEN
scir<="01110000"; --6F 70
ELSIF(scir<="01101111" AND rx='1') THEN
scir<="00000000";
ELSE
IF(scir="11111111" OR
(scir="01111001" AND rxd='1')) THEN
scir<="00000000";
ELSE
scir<=scir+'1';
END IF;
END IF;
END IF;
END PROCESS;
--tx counter
PROCESS(rst,reset,clk)
BEGIN
IF(rst='0' OR reset='0') THEN
scit<="00010011";
ELSIF(clk'EVENT AND clk='0') THEN
IF(scit<="01011111") THEN
IF(tdempty='0' AND rw='1') THEN
scit<="01100000";
ELSE
scit<="00010011";
END IF;
ELSE
IF(scit="11111111") THEN
scit<="00000000";
ELSE
scit<=scit+'1';
END IF;
END IF;
END IF;
END PROCESS;
--tdempty rdfull flag
--tdempty
PROCESS(clk,rw,cs1,rst,reset)
BEGIN
IF(rst='0' OR reset='0') THEN
tdempty<='1';
ELSIF(rw='0' AND cs1='0') THEN
tdempty<='0';
ELSIF(clk'EVENT AND clk='0') THEN
IF(scit="11111111") THEN
tdempty<='1';
END IF;
END IF;
END PROCESS;
--rdfull
PROCESS(clk,rw,cs1,rst,reset)
BEGIN
IF((rw='1' AND cs1='0') OR (rst='0' OR reset='0')) THEN
rdfull<='0';
ELSIF(clk'EVENT AND clk='0') THEN
IF(scir="11111111") THEN
rd<=dout;
rdfull<='1';
END IF;
END IF;
END PROCESS;
--chip selsct signal
PROCESS
BEGIN
IF(csi='0') THEN
IF(rs='0') THEN
cs0<='0';cs1<='1';
ELSE
cs0<='1';cs1<='0';
END IF;
ELSE
cs0<='1';cs1<='1';
END IF;
END PROCESS;
--rst generater
PROCESS(cr)
BEGIN
IF(cr="00000011") THEN
rst<='0';
ELSE
rst<='1';
END IF;
END PROCESS;
--csi generate
PROCESS(c4m)
BEGIN
IF(c4m'EVENT AND c4m='1') THEN
IF(cs='0') THEN
csi<='0';
ELSE
csi<='1';
END IF;
END IF;
END PROCESS;
--cpu interface
--sr
sr<="000000"&tdempty&rdfull;
--read
--PROCESS(c40m)
--BEGIN
-- IF(c40m'EVENT AND c40m='1') THEN
-- dshift(2)<=e;
-- FOR i IN 0 TO 1 LOOP
-- dshift(i)<=dshift(i+1);
-- END LOOP;
-- END IF;
--END PROCESS;
--te<=dshift(0);
PROCESS(c4m)
BEGIN
IF(c4m'EVENT AND c4m='1') THEN
--te<=e;
tt<=e;
te<=tt;
END IF;
END PROCESS;
PROCESS
BEGIN
IF(rw='1') THEN
--IF(cs0='0' AND (te='1' OR e='1')) THEN
IF(cs0='0' AND te='1') THEN
d<=sr;
--ELSIF(cs1='0' AND (te='1' OR e='1')) THEN
ELSIF(cs1='0' AND te='1') THEN
d<=rd;
ELSE
d<="ZZZZZZZZ";
END IF;
ELSE
d<="ZZZZZZZZ";
END IF;
END PROCESS;
--write
--td<="01111001";
PROCESS(cs)
BEGIN
IF(cs'EVENT AND cs='1') THEN
IF(rw='0' AND cs1='0') THEN
td<=d;
ELSIF(rw='0' AND cs0='0') THEN
cr<="000000"&d(1)&d(0);
END IF;
END IF;
END PROCESS;
END rtl;
发表时间:2002年9月2日13:20:00