4a83543f7ac13e80afe94f94a322a6b8302f7e3a
[bos2k9.git] / fhw_rs232 / rs232_send.vhd
1 -----------------------------------------------------------------------
2 -- Copyright (c) 2009 Malte S. Stretz <http://msquadrat.de> 
3 --
4 -- TODO
5 -- 
6 -----------------------------------------------------------------------
7 -- This entity is part of the following library:
8 -- pragma library fhw_rs232
9 library fhw_rs232;
10 use fhw_rs232.rs232_globals_p.all;
11
12 library ieee;
13 use ieee.std_logic_1164.all;
14 use ieee.numeric_std.all;
15
16 entity rs232_send is
17   generic(
18     clock_divider  : positive;
19     data_width     : positive := 8;
20     parity_enabled : std_logic := '0';
21     parity_type    : std_logic := '0');
22   port(
23     clk : in  std_logic;
24     rst : in  std_logic;
25     
26     tx  : out std_logic;
27     txd : in  std_logic_vector(data_width - 1 downto 0);
28     txn : in  std_logic;
29     txb : out std_logic);
30  end rs232_send;
31  
32 -----------------------------------------------------------------------
33
34 architecture rtl of rs232_send is
35   component rs232_counter_e is
36     generic(
37       count : positive := clock_divider);
38     port(
39       clock  : in  std_logic;
40       reset  : in  std_logic;
41       enable : in  std_logic;
42       
43       done : out std_logic);
44   end component;
45
46   type state_t is (
47     idle_state_c,
48     send_state_c,
49     wait_state_c);
50   signal state_s : state_t;
51   
52   subtype frame_t is std_logic_vector((2 + data_width + 2) - 1 downto 0);
53   signal frame_s : frame_t;
54   signal index_s : frame_t;
55   
56   signal sending_s : std_logic;
57   signal timer_s   : std_logic;
58   
59   signal done_s  : std_logic;
60 begin
61   txb <= txn when state_s = idle_state_c
62     else '1';
63   
64   frame_s(frame_t'high - 0) <= '1'; -- Stop
65   frame_s(frame_t'high - 1) <= get_parity(txd, parity_type) when parity_enabled = '1'
66                           else frame_s(frame_t'high);
67   frame_s(frame_t'high - 2 downto frame_t'low + 2) <= txd;
68   frame_s(frame_t'low + 1) <= '0'; -- Start
69   frame_s(frame_t'low + 0) <= '1'; -- Idle
70   
71   done_s <= index_s(frame_t'high);
72
73   output : process(frame_s, index_s)
74     variable output_v : std_logic;
75   begin
76     output_v := '0';
77     for i in frame_t'range loop
78       output_v := output_v or (frame_s(i) and index_s(i));
79     end loop;
80     tx <= output_v;
81   end process;
82   
83   shifter : process(clk, rst)
84   begin
85     if rst = '1' then
86       index_s(frame_t'low) <= '1';
87       index_s(frame_t'high downto frame_t'low + 1) <= (others => '0');
88     elsif rising_edge(clk) then
89       if state_s = send_state_c then
90         index_s <= index_s(frame_t'high - 1 downto frame_t'low) & index_s(frame_t'high);
91       end if;
92     end if;
93   end process;
94   
95   sequence : process(clk, rst)
96   begin
97     if rst = '1' then
98       state_s <= idle_state_c;
99     elsif rising_edge(clk) then
100       case state_s is
101         when idle_state_c =>
102           if txn = '1' then
103             state_s <= send_state_c;
104           end if;
105         when send_state_c =>
106           state_s <= wait_state_c;
107         when wait_state_c =>
108           if timer_s = '1' then
109             if done_s = '1' then
110               state_s <= idle_state_c;
111             else
112               state_s <= send_state_c;
113             end if;
114           end if;
115       end case;
116     end if;
117   end process;
118   
119   sending_s <= '1' when state_s = wait_state_c
120           else '0';
121   trigger : rs232_counter_e port map(
122     clock  => clk,
123     reset  => rst,
124     enable => sending_s,
125     
126     done   => timer_s);
127 end rtl;