mr.king的笔记 https://bbs.21ic.com/?85833 [收藏] [复制] [RSS]

日志

非常简单的串口状态机

已有 1051 次阅读2010-11-26 06:39 |系统分类:EDA/PLD| FPGA, 串口

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity SERIAL is
    Port (  clk,exreset,rx :in STD_LOGIC;        
       datain:in STD_LOGIC_vector(15 downto 0);
       sendfinish,rxtest1  :buffer STD_LOGIC;
       rxbuf:buffer std_logic_vector(7 downto 0);
       tx,receivesuccess,stopbiterr,clkrxouttest,rxtest: out  STD_LOGIC);
end SERIAL;


architecture Behavioral of SERIAL is


 TYPE sreg IS (ready,startbitpending,startbitsure,receive);


 signal sendprocess,serialtxclk,serialrxclk,success:STD_LOGIC;
 signal clktxcount,overcount :integer range 0 to 511;
 signal txbitcount,pendingcount:integer range 0 to 31;
 signal shiftcount:integer range 0 to 15;
 signal txshift:STD_LOGIC_vector(15 downto 0);
 signal rxbitcount,clkrxcount,t2,t3,t4,t5:integer range 0 to 127;
 signal bittemp:integer range 0 to 3;
 signal rxshift:std_logic_vector(7 downto 0);
 signal currentstate,nextstate:sreg;
begin
 serialtxclkout:process(exreset,clk)
 begin
  if exreset='0' then
   clktxcount<=0;
   serialtxclk<='1';
  elsif rising_edge(clk) then
   if clktxcount=433 then
   --if clktxcount=3 then
    clktxcount<=0;
    serialtxclk<='1';
   else
    clktxcount<=clktxcount+1;
    if clktxcount=216 then
    --if clktxcount=1 then
     serialtxclk<='0';
    end if;
   end if;   
  end if;
 end process serialtxclkout;


 serialrxclkout:process(exreset,clk)
 begin
  if exreset='0' then
   clkrxcount<=0;
   clkrxouttest<='1';
   serialrxclk<='1';
  elsif rising_edge(clk) then
   if clkrxcount=61 then
    clkrxcount<=0;
    clkrxouttest<='1';
    serialrxclk<='1';
   else
    clkrxcount<=clkrxcount+1;
    if clkrxcount=30 then
     serialrxclk<='0';
     clkrxouttest<='0';
    end if;
   end if;   
  end if;
 end process serialrxclkout;
 
 rxin:process(exreset,serialrxclk)
 begin
  if exreset='0' then
   overcount<=0;
   currentstate<=ready;
   nextstate<=ready;
   pendingcount<=0;
   rxbitcount<=0;
   success<='0';
  elsif rising_edge(serialrxclk) then
   if sendfinish='0' then
    success<='0';
   end if; 
   if overcount>70 then
    currentstate<=ready;
    nextstate<=ready;
    pendingcount<=0;
    rxbitcount<=0;
    nextstate<=ready;
   end if;
   --rxtest1<=not rxtest1;
   overcount<=overcount+1;
   rxtest<=rx;
   case currentstate is
    when ready=>
     if rx='0' then
      rxbitcount<=0;
      nextstate<=startbitpending;
      pendingcount<=0;
      overcount<=0;
      rxtest1<='0';
      t2<=8;
      t3<=9;
      t4<=10;
      t5<=11;
     end if;
   
     when startbitpending=>
     rxbitcount<=rxbitcount+1;
     if rx='0' then
      pendingcount<=pendingcount+1;
      if pendingcount>3 then
       nextstate<=startbitsure;
       bittemp<=0;
       shiftcount<=0;
       receivesuccess<='0';
       stopbiterr<='0';
      else
       rxtest1<='1';
      end if;
      
     else
      pendingcount<=0;
      nextstate<=ready;
     end if;  
    when startbitsure=>
     rxbitcount<=rxbitcount+1;
     nextstate<=receive;
     rxtest1<='0';
     
    when receive=>
     --rxtest1<=not rxtest1;
     rxbitcount<=rxbitcount+1;
     if rxbitcount=t2 then
      rxtest1<=not rxtest1;
      if rx='1' then
       bittemp<=bittemp+1;
      end if;
      t2<=t2+7;      
     end if;
     if rxbitcount=t3 then
      rxtest1<=not rxtest1;
      if rx='1' then
       bittemp<=bittemp+1;
      end if;
      t3<=t3+7;      
     end if;
     if rxbitcount=t4 then
      rxtest1<=not rxtest1;
      if rx='1' then
       bittemp<=bittemp+1;
      end if;
      t4<=t4+7;      
     end if;
     if rxbitcount=t5 then
      rxtest1<=not rxtest1;
      rxshift(6 downto 0)<=rxshift(7 downto 1);
      if bittemp>1 then
       rxshift(7)<='1';
      else
       rxshift(7)<='0';
      end if;
      bittemp<=0;
      if shiftcount=8 then         --对
       if bittemp>1 then
        receivesuccess<='1';
        success<='1';
        rxbuf<=rxshift(7 downto 0);
       else
        stopbiterr<='1';
       end if;  
       nextstate<=ready; 
      else 
       nextstate<=receive;
       shiftcount<=shiftcount+1;
       t5<=t5+7;      
      end if; 
     end if;
    
    when others=> 
     nextstate<=ready;
   end case;
  end if;
 
 currentstate<=nextstate;
 
 end process rxin;
 
 txout:process(success,serialtxclk,exreset)
 begin
  if exreset='0' then
   sendfinish<='1';
   tx<='1';
   txbitcount<=0;
   sendprocess<='0';
  else 
   --if (send='0') or (sendprocess='1') then
   --if (rx='0') or (sendprocess='1') then
   if (success='1') or (sendprocess='1') then
    if rising_edge(serialtxclk) then
      case txbitcount is
       when 0=>
        --txshift<=datain;
        txshift<=rxbuf & rxbuf;
        tx<='0';
        sendfinish<='0';
        sendprocess<='1';
        txbitcount<=txbitcount+1;
       when 10=>
        tx<='0';
        txbitcount<=txbitcount+1;
       when 9=>
        tx<='1';
        txbitcount<=txbitcount+1;
       when 19=>
        sendfinish<='1';
        sendprocess<='0';
        txbitcount<=0;
        tx<='1';
       when others=>
        tx<=txshift(0);
        txshift(14 downto 0)<=txshift(15 downto 1);
        txbitcount<=txbitcount+1;
      end case;
     end if; 
    end if;
   end if;
 end process txout;


end Behavioral;


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)