📄 uart_core.vhd
字号:
-- 库声明
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use WORK.UART_PACKAGE.all;
entity uart_core is
generic (
-- 数据位个数
DATA_BIT : integer := 8;
-- 总数据个数
TOTAL_BIT : integer := 10;
-- 奇偶校验规则
PARITY_RULE : PARITY := NONE );
port (
-- 时钟和复位信号
clk : in std_logic;
reset_n : in std_logic;
-- 和信号监测器的接口信号
new_data : in std_logic;
reset_dt : out std_logic;
-- 复位、使能子模块的信号
reset_parts : out std_logic;
ce_parts : out std_logic;
-- 和移位寄存器的接口信号
send_si : out std_logic;
sel_si : out std_logic;
regs : in std_logic_vector(TOTAL_BIT-1 downto 0);
-- 计数器时钟选择信号和计数器计数到达上阈的指示信号
sel_clk : out std_logic;
overflow : in std_logic;
-- 和奇偶校验器的接口信号
sel_pv : out std_logic;
parity : in std_logic;
-- 输出选择信号
sel_out : out std_logic;
-- 提供给CPU的接口信号
send : in std_logic;
send_bus : in std_logic_vector(DATA_BIT-1 downto 0);
send_over : out std_logic;
recv : out std_logic;
recv_bus : out std_logic_vector(DATA_BIT-1 downto 0);
error : out std_logic );
end uart_core;
architecture uart_core of uart_core is
-- 内部信号
signal state : UART_STATE := UART_IDLE;
signal send_buf : std_logic_vector(TOTAL_BIT-1 downto 0);
signal si_count : integer range 0 to 15 := 0;
begin
-- 主过程
main: process(clk, reset_n)
begin
if reset_n = '0' then
-- 信号监测器复位信号
reset_dt <= '1';
-- 其他模块的复位和使能信号
reset_parts <= '0';
ce_parts <= '0';
-- 移位寄存器输入
sel_si <= '0';
-- 波特率发生器和计数器的时钟选择信号
sel_clk <= '0';
-- 奇偶校验器的输入
sel_pv <= '0';
-- 选择TxD输出
sel_out <= '0';
-- 与CPU之间的接口信号
send_over <= '0';
recv <= '0';
error <= '0';
recv_bus <= (others => '0');
-- 状态机
state <= UART_IDLE;
-- 串行加载的计数
si_count <= 0;
elsif rising_edge(clk) then
case state is
-- 空闲状态
when UART_IDLE =>
-- 当信号监测器监测到数据时,new_data变为'1'
if new_data = '1' then
-- 复位子模块
reset_parts <= '0';
-- 子模块使能无效
ce_parts <= '0';
-- 选择移位寄存器串行输入为RxD
sel_si <= '1';
-- 选择移位寄存器的时钟为波特率始终
-- 选择计数器的时钟为波特率发生器的指示信号
sel_clk <= '0';
-- 使得输出保持为'1'
sel_out <= '0';
-- 设置奇偶校验的数据源为数据发送总线
sel_pv <= '1';
-- 改变状态为接收
state <= UART_RECV;
-- 当send信号变为'1',表示CPU要求发送数据
elsif send = '1' then
-- 复位子模块
reset_parts <= '0';
-- 子模块使能无效
ce_parts <= '0';
-- 选择移位寄存器串行输入为串行加载序列
sel_si <= '0';
-- 选择移位寄存器的时钟为波特率始终
-- 选择计数器的时钟为波特率发生器的指示信号
sel_clk <= '0';
-- 使得输出保持为'1'
sel_out <= '0';
-- 设置奇偶校验的数据源为数据发送总线
sel_pv <= '0';
-- 初始化串行加载序列的索引变量
si_count <= TOTAL_BIT-1;
-- 改变状态为加载
state <= UART_LOAD;
else
-- 停止对信号监测器的复位
reset_dt <= '1';
end if;
-------- 数据加载和发送状态--------
-- 加载状态
when UART_LOAD =>
-- 如果overflow信号为'1',表示数据加载完成
if overflow = '1' then
-- 复位子模块
reset_parts <= '0';
-- 子模块使能信号无效
ce_parts <= '0';
-- 选择移位寄存器串行输入为串行加载序列
sel_si <= '0';
-- 选择移位寄存器的时钟为波特率始终
-- 选择计数器的时钟为波特率发生器的指示信号
sel_clk <= '0';
-- 使得输出保持为'1'
sel_out <= '0';
-- 设置奇偶校验的数据源为数据发送总线
sel_pv <= '0';
-- 改变状态为发送
state <= UART_SEND;
else
-- 选择移位寄存器的时钟为系统时钟
-- 选择计数器的时钟为系统时钟
sel_clk <= '1';
-- 通过增加si_count,生成串行加载序列
if not(si_count = TOTAL_BIT-1) then
si_count <= si_count+1;
else
si_count <= 0;
end if;
-- 子模块复位信号无效
reset_parts <= '1';
-- 子模块使能信号有效
ce_parts <= '1';
end if;
-- 发送状态
when UART_SEND =>
-- 选择输出为TxD
sel_out <= '1';
-- 如果overflow为'1',表示发送完成
if overflow = '1' then
-- 输出发送完成的指示信号
send_over <= '1';
-- 改变状态为发送完成
state <= UART_END_SEND;
else
-- 子模块复位信号无效
reset_parts <= '1';
-- 子模块使能信号有效
ce_parts <= '1';
end if;
-- 发送完成状态
when UART_END_SEND =>
-- 子模块使能信号无效
ce_parts <= '0';
-- 复位信号监测器
reset_dt <= '0';
-- 恢复发送完成指示信号
send_over <= '0';
-- 改变状态为空闲
state <= UART_IDLE;
-------- 数据接收状态--------
-- 接收状态
when UART_RECV =>
-- 如果overflow变为"1",表示接收完成
if overflow = '1' then
-- 输出接收指示信号
recv <= '1';
-- 总线数据输出
recv_bus <= regs(DATA_BIT downto 1);
-- 改变状态为接收完成
state <= UART_END_RECV;
else
-- 子模块复位信号无效
reset_parts <= '1';
-- 子模块使能信号有效
ce_parts <= '1';
end if;
-- 接收完成状态
when UART_END_RECV =>
-- 进行奇偶校验
if not(regs(0) = parity) then
error <= '1';
end if;
-- 子模块使能信号无效
ce_parts <= '0';
-- 复位信号监测器
reset_dt <= '0';
-- 恢复接收完成指示信号
recv <= '0';
-- 改变状态为空闲
state <= UART_IDLE;
-- 如果产生未知状态,输出错误信息
when others =>
error <= '1';
-- 恢复到空闲状态
state <= UART_IDLE;
end case;
end if;
end process;
-- 生成串行加载序列
send_buffer: process(send_bus, parity)
begin
-- 存储起始位
send_buf(0) <= '0';
-- 存储数据位
send_buf(DATA_BIT downto 1) <= send_bus(DATA_BIT-1 downto 0);
-- 存储奇偶校验位和停止位
if PARITY_RULE = ODD or PARITY_RULE = EVEN then
send_buf(DATA_BIT+1) <= parity;
send_buf(TOTAL_BIT-1 downto DATA_BIT+2) <= (others => '1');
else
send_buf(TOTAL_BIT-1 downto DATA_BIT+1) <= (others => '1');
end if;
end process;
-- 串行输入选择
si_switch: process(reset_n, si_count)
begin
-- 复位
if reset_n = '0' then
send_si <= '1';
else
-- 将send_buf里面的数据送到send_si端口上
send_si <= send_buf(si_count);
end if;
end process;
end uart_core;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -