原创 UART的FPGA设计源码

2010-6-3 16:49 1755 1 1 分类: FPGA/CPLD

顶层文件


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use work.uart_1.all;
entity UART is
generic( data_bit:integer:=8;
 total_bit:integer:=10;
 parity_rule:parity:=even;
full_plus_count:bd_count:=bd9600_fpc;
rise_plus_count:bd_count:=bd9600_hpc);


 port (clk:in std_logic;
       reset_n:in std_logic;
       send: in std_logic;
       rxd:in std_logic;
       txd:out std_logic;
       error1:out std_logic;
       send_over:out std_logic;
      recv:out std_logic;
recv_buf:out std_logic_vector(7 downto 0);
send_bus:in std_logic_vector(7 downto 0));
end UART;
architecture rtl of UART is


component  parity_verifier
generic(data_length:integer:=8;
        parity_rule:parity:=even);
 port(
      source:in std_logic_vector(data_length-1 downto 0);
      parity:out std_logic
      );
end component;


component baudrate_generator
generic(full_plus_count:bd_count:=bd9600_fpc;
        rise_plus_count:bd_count:=bd9600_hpc);
 port(clk:in std_logic;
      reset_n:in std_logic;
      ce:in std_logic;
      bdout:out std_logic;
      indicator:out std_logic
      );
end component;


component detector is
port(clk,reset_n,rxd:in std_logic;
     new_data:out std_logic);
end component;


component swith_bus
generic (bus_width:integer:=8);
port(din1,din2:in std_logic_vector(bus_width-1 downto 0);
     sel:in std_logic;
     dout:out std_logic_vector(bus_width-1 downto 0));
end component;


component swith is
port(din1,din2:in std_logic;
     sel:in std_logic;
     dout:out std_logic);
end component;


component shift_register is
generic(total_bit:integer:=10);
port( clk:in std_logic;
      reset_n:in std_logic;
      din:in std_logic;
      regs:out std_logic_vector(total_bit-1 downto 0);
      dout:out std_logic);
end component;


component UART1 IS
 GENERIC(DATA_BIT:INTEGER :=8;
         TOTAL_BIT:INTEGER:=10;
          PARITY_RULE:PARITY:=even);
 PORT( clk,reset_n:in std_logic;
       new_data:in std_logic;----信号监测与复位信号
       reset_dt:out std_logic;
       reset_part:out std_logic;
       ce_part: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;
       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);
       error1:out std_logic);
end component;


component counter is
generic (max_count :integer:=10);
port(clk,reset_n:in std_logic;
   ce:in std_logic;
   overflow:out std_logic);
end component;


constant vcc_constant:std_logic:='1';
signal bg_clk:std_logic;
signal bg_out:std_logic;
signal ce_part:std_logic;
signal counter_clk:std_logic;


signal clk_inv:std_logic;
signal indicator:std_logic;
signal new_data:std_logic;
signal overflow:std_logic;


signal parity:std_logic;
signal reset_dt:std_logic;
signal reset_part:std_logic;
signal sel_clk:std_logic;


signal sel_pv:std_logic;
signal sel_out:std_logic;
signal sel_si:std_logic;
signal send_si:std_logic;


signal sr_in:std_logic;
signal sr_out:std_logic;
signal vcc:std_logic;
signal pv_source:std_logic_vector(data_bit-1 downto 0);


signal recv_parity_source:std_logic_vector(data_bit-1 downto 0);
signal regs:std_logic_vector(total_bit-1 downto 0);
signal send_parity_source:std_logic_vector(data_bit-1 downto 0);


begin
u_bg:baudrate_generator
 port map(clk=>clk,
      reset_n=>reset_part,
      ce=>ce_part,
      bdout=>bg_out,
      indicator=> indicator
      );


U_core:UART1
  PORT MAP( clk=>clk,reset_n=>reset_n,
       new_data=>new_data,----信号监测与复位信号
       reset_dt=>reset_dt,
       reset_part=>reset_part,
       ce_part=>ce_part,
       send_si=>send_si,
       sel_si=>sel_si,
       regs=>regs,
       sel_clk=>sel_clk,
       overflow=>overflow,
       sel_pv=>sel_pv,
       parity=>parity,
       sel_out=>sel_out,
       send=>send,
       send_bus=>send_parity_source,
       send_over=>send_over,
       recv=>recv,
       recv_bus=>recv_parity_source,
       error1=>error1);
u_counter :counter
port map (clk=>counter_clk,
         reset_n=>reset_part,
          ce=>ce_part,
          overflow=>overflow);
 
u_counterclkswith:swith
port map(din1=>indicator,
         din2=>clk_inv,
         sel=>sel_clk,
         dout=>counter_clk);


u_detector:detector
port map(rxd=>rxd,
         clk=>clk,
         reset_n=>reset_dt,
         new_data=>new_data);


u_parityverifier:parity_verifier
port map( parity=>parity,
          source=>pv_source);


u_busswith:swith_bus
port map(din1=>send_parity_source(data_bit-1 downto 0),
        din2=>recv_parity_source(data_bit-1 downto 0),
        sel=>sel_pv,
        dout=>pv_source(data_bit-1 downto 0));


u_siswith:swith
port map(din1=>send_si,
        din2=>rxd,
        sel=>sel_si,
        dout=>sr_in);


u_sr:shift_register
port map(clk=>bg_clk,
         din=>sr_in,
         dout=>sr_out,
         regs=>regs(total_bit-1 downto 0),
         reset_n=>reset_part);


u_srclkswith:swith
port map(din1=>bg_out,
         din2=>clk_inv,
         sel=>sel_clk,
         dout=>bg_clk);
u_txdswith:swith
port map(din1=>vcc,
         din2=>sr_out,
         sel=>sel_out,
         dout=>txd);
end rtl;


波特率


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;


package uart_1 is
type dt_state is(dt_unlock,dt_lock);
type bd_count is range 65535 downto 0;
constant bd9600_fpc:bd_count:=5208;
constant bd9600_hpc:bd_count:=2604;
constant bdtest_fpc:bd_count:=10;
constant bdtest_hpc:bd_count:=5;
type parity is(none,odd,even);
function multixor(din:in std_logic_vector) return std_logic;
end uart_1;
package body uart_1 is
function multixor(din:in std_logic_vector)return std_logic is
variable check:std_logic;
begin
  check:=din(din'low);
  for i in 1 to (din'high)loop
  check:=check xor din(i);
 end loop;
return check;
end multixor;
end uart_1;               


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use work.uart_1.all;
entity baudrate_generator is
generic(full_plus_count:bd_count:=bd9600_fpc;
        rise_plus_count:bd_count:=bd9600_hpc);
 port(clk:in std_logic;
      reset_n:in std_logic;
      ce:in std_logic;
      bdout:out std_logic;
      indicator:out std_logic
      );
end baudrate_generator;
 architecture rtl of baudrate_generator is


begin
process(clk,reset_n,ce)
variable clk_count:bd_count:=0;
 begin
 if reset_n='0' then clk_count:=0;
 bdout<='0';indicator<='0';
elsif rising_edge(clk) then
   if ce='1' then 
      if clk_count<full_plus_count-1 then
           clk_count:=clk_count+1;
      else clk_count:=0;
      end if;
    end if;
    if   (clk_count>rise_plus_count-1 and clk_count<=full_plus_count-1) then
             bdout<='1'; else bdout<='0';
     end if;
      if clk_count=full_plus_count-1 then  indicator<='1';
          elsif clk_count=0 then indicator<='0';
       end if;
end if;
end process;
end rtl;


计数器


library ieee;
use ieee.std_logic_1164.all;
entity counter is
generic (max_count :integer:=10);
port(clk,reset_n:in std_logic;
   ce:in std_logic;
   overflow:out std_logic);
end counter;
architecture rtl of counter is
 begin
process(clk,ce,reset_n)
variable count:integer range 0 to 10;
begin
if reset_n='0' then
 count:=0;overflow<='0';
elsif rising_edge(clk)then
   if ce='1' then
  if count="max"_count-1 then overflow<='1';count:=0;
 else count:=count+1;overflow<='0';
end if;
 end if;
end if;
end process;
end rtl;
信号监测


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
 entity detector is
port(clk,reset_n,rxd:in std_logic;
     new_data:out std_logic);
end detector;


architecture rtl of detector is
type dt_state is(dt_unlock,dt_lock);
signal state:dt_state;
begin
process(clk,reset_n,rxd)
begin
if reset_n='0' then
 state<=dt_unlock;
new_data<='0';
 elsif rising_edge(clk) then
if rxd='0' and state<=dt_unlock then
 new_data<='1';
 state<=dt_lock;
else new_data<='0';
end if;
end if;
end process;
end rtl;


奇偶校验


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use work.uart_1.all;
entity parity_verifier is
generic(data_length:integer:=8;
        parity_rule:parity:=even);
 port(
      source:in std_logic_vector(data_length-1 downto 0);
      parity:out std_logic
      );
end parity_verifier;


architecture rtl of parity_verifier is
 begin
 with parity_rule select
 parity<=multixor(source) when odd,
         (not multixor(source)) when even,
         '1' when others;
end rtl;


移位寄存器


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use work.uart_1.all;
entity shift_register is
generic(total_bit:integer:=10);
port( clk:in std_logic;
      reset_n:in std_logic;
      din:in std_logic;
      regs:out std_logic_vector(total_bit-1 downto 0);
      dout:out std_logic);
end shift_register;


architecture rtl of shift_register is
signal shift_regs:std_logic_vector(total_bit-1 downto 0);
begin


regs<=shift_regs;


process(clk,reset_n,din)
begin
if reset_n='1' then dout<='1';
  elsif rising_edge(clk) then dout<=shift_regs(total_bit-1);
    shift_regs(total_bit-1 downto 1)<=shift_regs(total_bit-2 downto 0);
    shift_regs(0)<=din;
end if;
end process;
end rtl;


总线选择


library ieee;
use ieee.std_logic_1164.all;
entity swith_bus is
generic (bus_width:integer:=8);
port(din1,din2:in std_logic_vector(bus_width-1 downto 0);
     sel:in std_logic;
     dout:out std_logic_vector(bus_width-1 downto 0));
end swith_bus;


architecture rtl of swith_bus is
begin
with sel select
dout<=din1 when '0',
      din2 when others;
end rtl ;


二选一


library ieee;
use ieee.std_logic_1164.all;
entity swith is
port(din1,din2:in std_logic;
     sel:in std_logic;
     dout:out std_logic);
end swith;


architecture rtl of swith is
begin
with sel select
dout<=din1 when '0',
      din2 when others;
end rtl ;


uart内核控制器


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use work.uart_1.all;
ENTITY UART1 IS
 GENERIC(DATA_BIT:INTEGER :=8;
         TOTAL_BIT:INTEGER:=10;
          PARITY_RULE:PARITY:=NONE);
 PORT( clk,reset_n:in std_logic;
       new_data:in std_logic;----信号监测与复位信号
       reset_dt:out std_logic;
       reset_part:out std_logic;
       ce_part: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;
       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);
       error1:out std_logic);
end UART1;


ARCHITECTURE rtl of UART1 is
 type uart_state is(uart_idle,uart_recv,uart_send,uart_load,uart_end_send,uart_end_recv);
 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
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_swith:process(reset_n,si_count,send_buf)
begin
if reset_n='0' then
   send_si<='1';
else send_si<=send_buf(si_count);
end if;
end process;


main:process(clk,reset_n)
begin
if reset_n='0' then
reset_dt<='1';--信号监测复位
reset_part<='0';
ce_part<='0';
sel_si<='0';
sel_clk<='0';
sel_pv<='0';
sel_out<='0';
send_over<='0';
recv<='0';
error1<='0';


state<=uart_idle;
si_count<=0;
elsif rising_edge(clk) then


case state is
when uart_idle=>
if new_data='1' then
reset_part<='0';
ce_part<='0';
sel_si<='1';
sel_clk<='0';
sel_out<='1';
sel_pv<='1';
state<=uart_recv;


elsif send='1' then
reset_part<='0';
ce_part<='0';
sel_si<='0';
sel_clk<='0';
sel_out<='0';
sel_pv<='0';
si_count<=TOTAL_BIT-1;
STATE<=uart_load;
else
reset_dt<='1';
end if;
 when uart_load =>
if overflow='1' then
reset_part<='0';
ce_part<='0';
sel_si<='0';
sel_clk<='0';
sel_out<='0';
sel_pv<='0';
state<=uart_send;
else
sel_clk<='1';if not(si_count=TOTAL_BIT-1) THEN
  si_count<=si_count+1;
else si_count<=0;
end if;
reset_part<='1';ce_part<='1';
end if;


when uart_send =>
if overflow='1' then
send_over<='1';
state<=uart_end_send;
else
reset_part<='1';
ce_part<='1';
 end if;
 when uart_end_send=>
ce_part<='0';
reset_dt<='0';
send_over<='0';
state<=uart_idle;


when uart_recv=>
if overflow='1' then
recv<='1';
state<=uart_end_recv;
else
reset_part<='1';
ce_part<='1';
end if;


when uart_end_recv=>
 if not(regs(0)=parity) then
error1<='1';
end if;
ce_part<='0';
reset_dt<='0';
recv<='0';
state<=uart_idle;
when others=>error1<='1';
state<=uart_idle;
end case;
end if;
end process;
end rtl;

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
1
关闭 站长推荐上一条 /3 下一条