⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rxcver.vhd

📁 VHDL的例子
💻 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 + -