【嵌入式开发】FPGA/CPLD控制串口(VHDL版)
作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/
采用自顶向下设计:
top_rs232_port.vhd
library ieee;
use ieee.std_logic_1164.all;
entity rs232_port is
port ( serialinput : in std_logic;
clock : in std_logic;
reset : in std_logic;
readinput : in std_logic;
sendoutput : in std_logic;
serial_in : in std_logic_vector(7 downto 0);
serialoutput : out std_logic;
getinput : out std_logic;
outputsent : out std_logic;
serial_out : out std_logic_vector(7 downto 0));
end rs232_port;
architecture behavioral of rs232_port is
signal fastclk : std_logic;
signal slowclk : std_logic;
component rs232_in
port(data_out : out std_logic_vector(7 downto 0);
reset : in std_logic;
clock : in std_logic;
getdata : in std_logic;
ready : out std_logic;
serialinput: in std_logic);
end component;
component rs232_out
port(data_in : in std_logic_vector(7 downto 0);
reset : in std_logic;
clock : in std_logic;
load : in std_logic;
ready : out std_logic;
serialoutput : out std_logic);
end component;
component clkdiv
Generic (Divisor1: positive :=1311; -- clock for sending
Divisor2: positive :=82 ); -- clock for receiving
PORT(fast_clock : IN STD_LOGIC;
reset : IN STD_LOGIC;
slow_clock1: out STD_LOGIC;
slow_clock2: out STD_LOGIC);
END component;
begin
serin: rs232_in
port map(data_out => serial_out,
reset => reset,
clock => fastclk,
getdata => readinput,
ready => getinput,
serialinput=> serialinput);
serout: rs232_out
port map(data_in => serial_in,
reset => reset,
clock => slowclk,
load => sendoutput,
ready => outputsent,
serialoutput=> serialoutput);
clocks: clkdiv
port map(fast_clock => clock,
reset => reset,
slow_clock1 => slowclk,
slow_clock2 => fastclk);
end behavioral;
rs232_input.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity rs232_in is
port(data_out: out std_logic_vector(7 downto 0);
reset : in std_logic;
clock : in std_logic;
getdata : in std_logic;
ready : out std_logic;
serialinput : in std_logic);
end rs232_in;
architecture behavioural of rs232_in is
signal indata : std_logic_vector(7 downto 0);
constant countmax : natural := 153;
begin
process (clock)
variable count:natural range 0 to 170;
variable startbit : integer range 0 to 2 ;
begin
if (clock'event and clock='1') then
if ( reset = '1' or getdata = '1')then
indata <= (others => '0');
ready <= '0';
count := 0;
data_out <= (others => '0');
startbit := 0 ;
elsif (serialinput = '0' and startbit = 0) then
startbit := 1;
elsif (serialinput = '1' and count >= countmax) then
startbit := 0;
data_out <= indata;
count:= 0;
ready <= '1';
indata <= (others => '0');
end if;
if (startbit = 1) then
count:= (count +1);
case count is
when 24 =>
indata(0) <= serialinput;
when 40 =>
indata(1) <= serialinput;
when 56 =>
indata(2) <= serialinput;
when 72 =>
indata(3) <= serialinput;
when 88 =>
indata(4) <= serialinput;
when 104 =>
indata(5) <= serialinput;
when 120 =>
indata(6) <= serialinput;
when 136 =>
indata(7) <= serialinput;
when others =>
count:= count;
end case;
end if;
end if;
end process ;
end behavioural;
rs232_output.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity rs232_out is
port(data_in : in std_logic_vector(7 downto 0);
reset : in std_logic;
clock : in std_logic;
load : in std_logic;
ready : out std_logic;
serialoutput : out std_logic);
end rs232_out;
architecture behavioural of rs232_out is
signal frame : std_logic_vector(10 downto 0);
signal internaldata : std_logic_vector(7 downto 0);
signal ready_s : std_logic;
begin
frame(0) <= '1';
frame(1) <= '0';
frame(9 downto 2) <= internaldata;
frame(10)<= '1';
ready <= ready_s;
process (clock)
variable count:natural range 0 to 10;
begin
if (clock'event and clock ='1') then
if (reset = '1') then
internaldata <= (others => '0');
ready_s <= '1';
count := 0;
serialoutput <= frame(0);
elsif load = '1' then
ready_s <= '0';
internaldata <= data_in;
serialoutput <= frame(0);
count:= 0;
elsif ready_s = '1' then
serialoutput <= frame(0);
elsif count = 10 then
ready_s <= '1';
serialoutput <= frame(count);
count:= 0;
else
count:= (count +1);
serialoutput <= frame(count);
end if;
end if;
end process ;
end behavioural;
clockkdiv.vhd
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY clkdiv IS
Generic (Divisor1: positive :=1311; -- clock for sending
Divisor2: positive :=82 ); -- clock for receiving
PORT(fast_clock : IN STD_LOGIC;
reset : IN STD_LOGIC;
slow_clock1: out STD_LOGIC;
slow_clock2: out STD_LOGIC);
END clkdiv;
ARCHITECTURE behaviour OF clkdiv IS
signal slow_clock1_s : std_logic;
signal slow_clock2_s : std_logic;
BEGIN
slow_clock1 <= slow_clock1_s;
slow_clock2 <= slow_clock2_s;
process (fast_clock)
variable c1:natural range 0 to Divisor1;
variable c2:natural range 0 to Divisor2;
BEGIN
if( fast_clock'EVENT and fast_clock = '1') then
if (reset = '1') then
c1:= 0;
c2:= 0;
slow_clock1_s <='0' ;
slow_clock2_s <= '0';
else
c1 := (c1 + 1);
c2 := (c2 + 1);
IF (c1=Divisor1) THEN
slow_clock1_s <= not slow_clock1_s;
c1 := 0;
elsif (c2 = Divisor2) then
slow_clock2_s <= not slow_clock2_s;
c2:= 0;
END IF;
end if;
end if;
END PROCESS ;
END behaviour;