📄 s8250.vhd
字号:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY s8250 IS
PORT(clk, rclk, reset, sin, rd, wr, cs, a2, a1, a0, dsr: IN STD_ULOGIC;
baudout, sout, dtr, rts: OUT STD_ULOGIC;
d: INOUT STD_ULOGIC_VECTOR(7 DOWNTO 0));
END s8250;
ARCHITECTURE rtl OF s8250 IS
SIGNAL scir: STD_ULOGIC_VECTOR(7 DOWNTO 0);
SIGNAL scit: STD_ULOGIC_VECTOR(7 DOWNTO 0);
SIGNAL sh_r: STD_ULOGIC_VECTOR(3 DOWNTO 0);
SIGNAL sl_r: STD_ULOGIC_VECTOR(3 DOWNTO 0);
SIGNAL sh_t: STD_ULOGIC_VECTOR(3 DOWNTO 0);
SIGNAL sl_t: STD_ULOGIC_VECTOR(3 DOWNTO 0);
SIGNAL shrecreg: STD_ULOGIC_VECTOR(7 DOWNTO 0); --接收移位寄存器
SIGNAL shsendreg: STD_ULOGIC_VECTOR(7 DOWNTO 0); --发送移位寄存器
SIGNAL recreg: STD_ULOGIC_VECTOR(7 DOWNTO 0); --接收数据寄存器
SIGNAL soutF, sinF: STD_ULOGIC;
SIGNAL shsendregEMPTY: STD_ULOGIC:='1';
SIGNAL shrecregFULL: STD_ULOGIC:='0';
SIGNAL ad: STD_ULOGIC_VECTOR(2 DOWNTO 0);
SIGNAL internal_bus_out: STD_ULOGIC_VECTOR(7 DOWNTO 0); --内总线
SIGNAL internal_bus_in: STD_ULOGIC_VECTOR(7 DOWNTO 0); --内总线
SIGNAL ccreg: STD_ULOGIC_VECTOR(7 DOWNTO 0); --通信控制寄存器
SIGNAL divl: STD_ULOGIC_VECTOR(7 DOWNTO 0); --除数寄存器低8位
SIGNAL divh: STD_ULOGIC_VECTOR(7 DOWNTO 0); --除数寄存器高8位
SIGNAL sendreg: STD_ULOGIC_VECTOR(7 DOWNTO 0); --发送数据寄存器
SIGNAL sendregF: STD_ULOGIC;
SIGNAL csreg: STD_ULOGIC_VECTOR(7 DOWNTO 0); --通信状态寄存器
SIGNAL divF: STD_ULOGIC;
SIGNAL sendover: STD_ULOGIC:='1'; --发送结束标志
SIGNAL dlength: STD_ULOGIC_VECTOR(3 DOWNTO 0);
SIGNAL dtrF: STD_ULOGIC;
BEGIN
dtr<=dtrF;
rts<=dtrF;
dlength <= "11"&ccreg(1)&ccreg(0); --通信控制寄存器低四位,用于控制数据位长度
sh_r <= scir(7 DOWNTO 4);
sl_r <= scir(3 DOWNTO 0);
sh_t <= scit(7 DOWNTO 4);
sl_t <= scit(3 DOWNTO 0);
--p1:对接收移位寄存器空满标志进行操作,将
--并将接收移位寄存器中的值放入接收数据寄存器中
PROCESS(rclk, rd, cs)
VARIABLE shrecreg_v:STD_ULOGIC_VECTOR(7 DOWNTO 0);
BEGIN
IF(rd='0' AND cs='0' AND ccreg(7)='0' AND a2='0' AND a1='0' AND a0='0') THEN
shrecregFULL<='0'; --接收移位寄存器空
ELSIF(rclk'EVENT AND rclk='1') THEN
IF((sinF='1') AND (sh_r=dlength) AND(sl_r="1111")) THEN
shrecregFULL<='1'; --接收移位寄存器满
shrecreg_v:=shrecreg;
CASE dlength IS --根据数据位数不同对接受到的数据进行处理
WHEN "1100" => FOR i IN 0 TO 4 LOOP --数据位数为5位
shrecreg_v(i):=shrecreg_v(i+3);
END LOOP;
shrecreg_v:=shrecreg_v AND "00011111";
WHEN "1101" => FOR i IN 0 TO 5 LOOP --数据位数为6位
shrecreg_v(i):=shrecreg_v(i+2);
END LOOP;
shrecreg_v:=shrecreg_v AND "00111111";
WHEN "1110" => FOR i IN 0 TO 6 LOOP --数据位数为7位
shrecreg_v(i):=shrecreg_v(i+1);
END LOOP;
shrecreg_v:=shrecreg_v AND "01111111";
WHEN "1111" => shrecreg_v:=shrecreg_v; --数据位数为8位
WHEN OTHERS => shrecreg_v:=shrecreg_v;
END CASE;
recreg<=shrecreg_v; --将接收移位寄存器中的值放入接收数据寄存器中
END IF;
END IF;
END PROCESS;
--p2 写进程
PROCESS(cs,wr,reset)
BEGIN
IF(wr'EVENT AND wr='0') THEN
ad <= a2 & a1 & a0;
internal_bus_out <= d; --将数据值写入内总线
END IF;
IF(reset = '0') THEN
ccreg <= "00000000";
ELSIF(wr'EVENT AND wr='1') THEN
IF(ad="011" AND cs='0') THEN
ccreg <= internal_bus_out; --写入通信控制寄存器
ELSIF(ccreg(7) = '1' AND ad = "000" AND cs = '0') THEN
divl <= internal_bus_out; --写入除数寄存器低8位
ELSIF(ccreg(7) = '1' AND ad = "001" AND cs = '0') THEN
divh <= internal_bus_out; --写入除数寄存器高8位
divF <= '1'; --表示除数值已写入
ELSIF(ccreg(7) = '0' AND ad = "000" AND cs = '0') THEN
sendreg <= internal_bus_out; --写入发送数据寄存器
END IF;
END IF;
END PROCESS;
--p3
PROCESS(rclk)
BEGIN
IF(rclk'EVENT AND rclk='1') THEN
IF(sin='0') THEN
sinF<='1'; --表示数据开始接收
ELSIF((sinF='1') AND (sh_r=dlength) AND(sl_r="1111")) THEN
sinF<='0'; --表示数据接收完毕
END IF;
END IF;
END PROCESS;
--p4 对发送过程的各标志操作
PROCESS(clk)
BEGIN
IF(reset='0' OR dsr='0') THEN
dtrF<='1';
END IF;
IF(sendover= '1' AND sendregF = '0') THEN
soutF<='0'; --表示开始发送数据
shsendregEMPTY<='0'; --表示发送移位寄存器满
dtrF<='0';
ELSIF(clk'EVENT AND clk='1') THEN
IF(((soutF='0') AND (sh_t=dlength) AND (sl_t="1111")) OR reset='0') THEN
soutF<='1'; --表示数据位发送完毕
shsendregEMPTY<='1'; --表示发送移位寄存器空
END IF;
END IF;
END PROCESS;
--p5 读进程
PROCESS(rd, cs)
BEGIN
IF(rd='0') THEN
IF(cs='0') THEN
IF(ccreg(7) = '0' AND a2='0' AND a1='0' AND a0='0') THEN
internal_bus_in<=recreg; --读接收数据寄存器
ELSIF(ccreg(7) = '1' AND a2='0' AND a1='0' AND a0='0') THEN
internal_bus_in<=divl; --读除数寄存器低8位
ELSIF(ccreg(7) = '1' AND a2='0' AND a1='0' AND a0='1') THEN
internal_bus_in<=divh; --读除数寄存器高8位
ELSIF(a2='0' AND a1='1' AND a0='1') THEN
internal_bus_in<=ccreg; --读通信控制寄存器
ELSIF(a2='1' AND a1='0' AND a0='1') THEN
internal_bus_in<=csreg; --读通信状态寄存器
END IF;
END IF;
ELSE
internal_bus_in<="ZZZZZZZZ";
END IF;
d<=internal_bus_in;
END PROCESS;
--p6 接收控制进程
PROCESS(rclk, reset)
VARIABLE scir_v:INTEGER RANGE 0 TO 255;
VARIABLE scir_s:STD_LOGIC_VECTOR(7 DOWNTO 0);
VARIABLE dlength_v:INTEGER RANGE 0 TO 255;
BEGIN
CASE dlength IS
WHEN "1100" => dlength_v:=208; --11001111+1 数据位数为5位
WHEN "1101" => dlength_v:=224; --11011111+1 数据位数为6位
WHEN "1110" => dlength_v:=240; --11101111+1 数据位数为7位
WHEN "1111" => dlength_v:=0; --11111111+1 数据位数为8位
WHEN OTHERS => dlength_v:=0;
END CASE;
IF(reset='0') THEN
scir_v:=0; --"00000000";
ELSIF(rclk'EVENT AND rclk='1') THEN
IF((scir_v<=111) AND (sin='0')) THEN --sci_v="01101111" 启动位到,开始接受
scir_v:=112; --scir_v="01110000";
ELSIF((scir_v<=111) AND (sin='1')) THEN
scir_v:=0;
ELSE
scir_v:=scir_v + 1;
IF(scir_v = dlength_v) THEN --当接收到所设定的数据长度时
scir_v := 0;
END IF;
END IF;
END IF;
scir_s:=CONV_STD_LOGIC_VECTOR(scir_v,8);
scir<=TO_STDULOGICVECTOR(scir_s);
END PROCESS;
--p7 产生停止位和BOUDOUT信号
PROCESS(clk)
VARIABLE counter:INTEGER RANGE 0 TO 32767; --15 bits
VARIABLE halfdiv_int:INTEGER RANGE 0 TO 32767;
VARIABLE halfdiv:STD_LOGIC_VECTOR(15 DOWNTO 0);
VARIABLE baudoutF:STD_ULOGIC;
VARIABLE stop_counter:INTEGER RANGE 0 TO 64;
VARIABLE stopF:STD_ULOGIC;
BEGIN
IF(clk'EVENT AND clk='1') THEN
IF(divF = '1') THEN --当除数寄存器已被写入
halfdiv := TO_STDLOGICVECTOR(divh&divl);
FOR i IN 0 TO 14 LOOP --将除数除以2
halfdiv(i):=halfdiv(i+1);
END LOOP;
halfdiv(15) := '0';
halfdiv_int:= CONV_INTEGER(halfdiv);
counter := counter+1; --计算来了多少个clk脉冲
IF(counter = halfdiv_int) THEN --当所来脉冲等于除数的一半时
counter := 0;
stop_counter := stop_counter+1;
IF(baudoutF = '1') THEN
baudoutF := '0';
ELSE
baudoutF := '1';
END IF;
END IF;
END IF;
IF((soutF='0') AND (sh_t=dlength) AND (sl_t="1111")) THEN --当数据位发送完毕时,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -