📄 rxcver.vhd
字号:
LIBRARY IEEE;
USE IEEE.Std_Logic_1164.all;
USE IEEE.Std_Logic_Unsigned.all;
ENTITY Rxcver IS
PORT (
-- Global reset and clock
Reset : IN STD_LOGIC; -- 全局复位
Clk16X : IN STD_LOGIC; -- 全局时钟
-- Register
RBR : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- 接收缓冲寄存器
-- Rising edge OF RBR, LSR read strobes
RbrRDn_re : IN STD_LOGIC; -- RbrRDn_r的上升沿指示
LsrRDn_re : IN STD_LOGIC; -- LsrRDn_r的上升沿指示
-- Receiver input
SIN : IN STD_LOGIC;
-- Receiver control
Databits : IN STD_LOGIC_VECTOR(1 DOWNTO 0); -- 数据长度
ParityEnable: IN STD_LOGIC; -- 0= Parity Disabled; 1= Parity Enabled
ParityEven : IN STD_LOGIC; -- 0= Odd Parity; 1= Even Parity
ParityStick : IN STD_LOGIC; -- 0= Stick Disabled; 1= Stick Enabled
-- Receiver status
RxRDY : OUT STD_LOGIC; -- 接收数据就绪
OverrunErr : OUT STD_LOGIC; -- 接收溢出标志
ParityErr : OUT STD_LOGIC; -- 奇偶校验标志位
FrameErr : OUT STD_LOGIC; -- 接收帧错误标志位
BreakInt : OUT STD_LOGIC --接受中断标志
);
END Rxcver;
ARCHITECTURE Rxcver_arch OF Rxcver IS
SIGNAL NumDataBitReceived_r : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL RSR : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL RxPrtyErr : STD_LOGIC;
SIGNAL RxFrmErr : STD_LOGIC;
SIGNAL RxIdle_r : STD_LOGIC;
SIGNAL RbrDataRDY : STD_LOGIC;
SIGNAL CNT_r : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL Hunt_r : boolean;
SIGNAL HuntOne_r : STD_LOGIC;
SIGNAL SIN1_r : STD_LOGIC;
SIGNAL RxFrmErr1_r : STD_LOGIC;
SIGNAL RxIdle1_r : STD_LOGIC;
SIGNAL OverrunErr_r: STD_LOGIC;
SIGNAL ParityErr_r : STD_LOGIC;
SIGNAL FrameErr_r : STD_LOGIC;
SIGNAL BreakInt_r : STD_LOGIC;
SIGNAL SampledOnce : STD_LOGIC;
-- Receiver Clock Enable Signal
SIGNAL RxClkEn : STD_LOGIC;
SIGNAL RBR_r : STD_LOGIC_VECTOR(7 DOWNTO 0);
-- State Machine Definition
type state_typ IS (idle, shift, parity, stop);
SIGNAL Rx_State : state_typ;
ATTRIBUTE SYN_KEEP : integer;
ATTRIBUTE SYN_KEEP OF RxPrtyErr, NumDataBitReceived_r, RSR : SIGNAL IS 1;
ATTRIBUTE SYN_KEEP OF Hunt_r, HuntOne_r, ParityErr_r, FrameErr_r : SIGNAL IS 1;
ATTRIBUTE SYN_KEEP OF BreakInt_r, RBR_r, OverrunErr_r, RbrDataRDY : SIGNAL IS 1;
ATTRIBUTE SYN_KEEP OF RxFrmErr, RxIdle_r : SIGNAL IS 1;
ATTRIBUTE OPT : string;
ATTRIBUTE OPT OF RxPrtyErr, NumDataBitReceived_r, RSR : SIGNAL IS "KEEP";
ATTRIBUTE OPT OF Hunt_r, HuntOne_r, ParityErr_r, FrameErr_r : SIGNAL IS "KEEP";
ATTRIBUTE OPT OF BreakInt_r, RBR_r, OverrunErr_r, RbrDataRDY : SIGNAL IS "KEEP";
ATTRIBUTE OPT OF RxFrmErr, RxIdle_r : SIGNAL IS "KEEP";
begin
--------------------------------------------------------------------------------
--产生 RxClkEn信号
--------------------------------------------------------------------------------
-- RxClkEn : 串行端口数据接收时钟使能
RxCLK_Proc: PROCESS (Reset, Clk16X)
begin
IF (Reset='1') THEN
RxClkEn <= '0';
ELSIF rising_edge(Clk16X) THEN
IF (CNT_r="0110") THEN
RxClkEn <= '1';
else
RxClkEn <= '0';
END IF;
END IF;
END PROCESS RxCLK_Proc;
-- CNT_r : 4-bit计数器来产生RxClkEn的波形
CNT_Proc: PROCESS (Reset, Clk16X)
begin
IF (Reset='1') THEN
CNT_r <= (others => '0');
ELSIF rising_edge(Clk16X) THEN
IF (Rx_State /= idle) OR (Hunt_r) THEN――当系统不为IDLE或Hunt_r状态时开始计数
CNT_r <= CNT_r + 1;
ELSIF (SampledOnce='1') THEN
CNT_r <= "0010";――当发生帧错误重新同步时提前两个时钟
else
CNT_r <= (others => '0');
END IF;
END IF;
END PROCESS CNT_Proc;
--------------------------------------------------------------------------------
-- 产生Hunt_r
--------------------------------------------------------------------------------
--当开始位找到后开始Hunt_r状态
Hunt_r_Proc: PROCESS (Reset, Clk16X)
begin
IF (Reset='1') THEN
Hunt_r <= FALSE;
ELSIF rising_edge(Clk16X) THEN
IF (Rx_State=idle) and (SIN='0') and (SIN1_r='1') THEN
Hunt_r <= TRUE;――当SIN下降沿出现开始Hunt_r
ELSIF (SampledOnce='1') and (SIN='0') THEN
Hunt_r <= TRUE;
ELSIF (RxIdle_r='0') OR (SIN='1') THEN
Hunt_r <= FALSE;
END IF;
END IF;
END PROCESS Hunt_r_Proc;
-- HuntOne_r 用来产生BI标志位,表明至少有一个 '1'在 帧里的(data + parity + stop) 比特中
-- 当所有接收的BIT都为0则将Break Interrupt flag(BI)设置为1,所以当HuntOne_r为低BI设为1
HuntOne_r_Proc: PROCESS(Clk16X, Reset)
begin
IF (Reset='1') THEN
HuntOne_r <= '0';
ELSIF rising_edge(Clk16X) THEN
IF (Hunt_r) THEN
HuntOne_r <= '0';
ELSIF (RxIdle_r='0') and (CNT_r(3)='1') and (SIN='1') THEN
HuntOne_r <= '1';
END IF;
END IF;
END PROCESS HuntOne_r_Proc;
-- RbrDataRDY :表明在RBR中的数据已经就绪可以读取,当数据读取后RBR清空
RbrDataRDY_Proc: PROCESS(Clk16X, Reset)
begin
IF (Reset='1') THEN
RbrDataRDY <= '0';
ELSIF rising_edge(Clk16X) THEN
IF (RxIdle_r='1') and (RxIdle1_r='0') THEN
RbrDataRDY <= '1';――当RxIdle_r上升沿后将RbrDataRDY设置
ELSIF (RbrRDn_re='1') THEN
RbrDataRDY <= '0';――当RBR被CPU读取后将RbrDataRDY清位
END IF;
END IF;
END PROCESS RbrDataRDY_Proc;
-- SampledOnce 将被置位一个CLK16X的时钟长度当一个帧错误发生。这个帧错误不是由于BREAK或是当采样停止位后采样当SIN有低电平。
SampledOnce_Proc: PROCESS (Reset, Clk16X)
begin
IF (Reset='1') THEN
SampledOnce <= '0';
ELSIF rising_edge(Clk16X) THEN
IF (RxFrmErr='1') and (RxFrmErr1_r='0') and
(SIN='0') and (HuntOne_r='1') THEN
SampledOnce <= '1';
else
SampledOnce <= '0';
END IF;
END IF;
END PROCESS SampledOnce_Proc;
-- RxIdle_r Flag
RxIdle_Proc: PROCESS(Reset, Clk16X)
begin
IF (Reset='1') THEN
RxIdle_r <= '1';
ELSIF rising_edge(Clk16X) THEN
IF (Rx_State=idle) THEN
RxIdle_r <= '1';
ELSIF (CNT_r(3)='1') THEN
RxIdle_r <= '0';
END IF;
END IF;
END PROCESS RxIdle_Proc;
--------------------------------------------------------------------------------
--接收状态机
--------------------------------------------------------------------------------
Shift_data_Proc: PROCESS(Clk16X, Reset)
begin
IF (Reset='1') THEN
RSR <= (others=>'0');
NumDataBitReceived_r <= (others=>'0');
RxPrtyErr <= '1';
RxFrmErr <= '0';
Rx_State <= idle;
ELSIF rising_edge(Clk16X) THEN
CASE Rx_State IS
WHEN idle =>
IF (RxIdle_r='1') and (SIN='0') and (RxClkEn='1') THEN
RSR <= (others=>'0');
NumDataBitReceived_r <= (others=>'0');
-- RxPrtyErr:接收奇偶校验错误指示是一个动态的初始化为0的为偶校验,初始化为1为奇校验。对偶校验,如果有偶数个1在(data + parity)比特中, 则 RxPrtyErr为0,意味着没有奇偶校验错误,否则有错误。
RxPrtyErr <= not ParityEven;
RxFrmErr <= '0';
Rx_State <= shift;
END IF;
WHEN shift =>
IF (RxClkEn='1') THEN
RSR <= SIN & RSR(7 DOWNTO 1);
RxPrtyErr <= RxPrtyErr xor SIN; -- Update RxPrtyErr dynamically
NumDataBitReceived_r <= NumDataBitReceived_r + 1;
IF ((DataBits="00" and NumDataBitReceived_r=4) OR
(DataBits="01" and NumDataBitReceived_r=5) OR
(DataBits="10" and NumDataBitReceived_r=6) OR
(DataBits="11" and NumDataBitReceived_r=7)) THEN
IF (ParityEnable='0') THEN
Rx_State <= stop;
else
Rx_State <= parity;
END IF;
END IF;
END IF;
WHEN parity =>
IF (RxClkEn='1') THEN
IF (ParityStick='0') THEN
RxPrtyErr <= RxPrtyErr xor SIN; -- Update RxPrtyErr dynamically
else
IF (ParityEven='0') THEN
RxPrtyErr <= not SIN;
else
RxPrtyErr <= SIN;
END IF;
END IF;
Rx_State <= stop;
END IF;
WHEN stop =>
IF (RxClkEn='1') THEN
RxFrmErr <= not SIN;
Rx_State <= idle;
END IF;
WHEN others =>
IF (RxClkEn='1') THEN
Rx_State <= idle;
END IF;
END CASE;
END IF;
END PROCESS Shift_Data_Proc;
--------------------------------------------------------------------------------
--接收缓冲寄存器(RBR)
--------------------------------------------------------------------------------
RBR_Proc: PROCESS(Clk16X, Reset)
begin
IF (Reset='1') THEN
RBR_r <= (others=>'0');
ELSIF rising_edge(Clk16X) THEN
IF (RxIdle_r='1') and (RxIdle1_r='0') THEN
CASE DataBits IS
WHEN "00" => -- 5-bit data
RBR_r <= "000" & RSR(7 DOWNTO 3);
WHEN "01" => -- 6-bit data
RBR_r <= "00" & RSR(7 DOWNTO 2);
WHEN "10" => -- 7-bit data
RBR_r <= '0' & RSR(7 DOWNTO 1);
WHEN others => -- 8-bit data
RBR_r <= RSR;
END CASE;
END IF;
END IF;
END PROCESS RBR_Proc;
RBR <= RBR_r;
--------------------------------------------------------------------------------
-- 为沿检测延迟信号
--------------------------------------------------------------------------------
Delay_Signals_Proc: PROCESS(Clk16X, Reset)
begin
IF (Reset='1') THEN
SIN1_r <= '0';
RxFrmErr1_r <= '1';
RxIdle1_r <= '1';
ELSIF rising_edge(Clk16X) THEN
SIN1_r <= SIN;
RxFrmErr1_r <= RxFrmErr;
RxIdle1_r <= RxIdle_r;
END IF;
END PROCESS Delay_Signals_Proc;
--------------------------------------------------------------------------------
-- 产生Error标志位
--------------------------------------------------------------------------------
-- 在LSR的错误标志位有OverrunErr(OE), ParityErr_r(PE), FrameErr_r(FE), BreakInt_r(BI)
-- 反映了在接收整帧(Start bit + Data bits + Parity bit + Stop bit)后SIN的线性状态
-- RxIdle_r的上升沿表明整个帧接收完毕
Error_Flags_Proc: PROCESS(Clk16X, Reset)
begin
IF (Reset='1') THEN
OverrunErr_r <= '0';
ParityErr_r <= '0';
FrameErr_r <= '0';
BreakInt_r <= '0';
ELSIF rising_edge(Clk16X) THEN
IF (RxIdle_r='1') and (RxIdle1_r='0') THEN - 在RxIdle_r的上升沿更新
OverrunErr_r <= RbrDataRDY;――如果RBR的数据没有被CPU读出则设置OverrunErr_r标志
ParityErr_r <= (ParityErr_r OR RxPrtyErr) and ParityEnable;设置ParityErr_r标志位
FrameErr_r <= FrameErr_r OR RxFrmErr;――当停止位采样为低则设置FrameErr_r
BreakInt_r <= BreakInt_r OR (not HuntOne_r);
ELSIF (LsrRDn_re='1') THEN -- clear WHEN LSR IS read
ParityErr_r <= '0';
FrameErr_r <= '0';
OverrunErr_r <= '0';
BreakInt_r <= '0';
END IF;
END IF;
END PROCESS Error_Flags_Proc;
RxRDY <= RbrDataRDY;
OverrunErr <= OverrunErr_r;
ParityErr <= ParityErr_r;
FrameErr <= FrameErr_r;
BreakInt <= BreakInt_r;
END Rxcver_arch;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -