?? 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 + -