Add the missing timer.
[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_interval : time;
19     clock_divider  : positive; -- TODO: calculate this based on clock_interval
20     data_width     : positive := 8;
21     parity_enabled : std_logic := '0';
22     parity_type    : std_logic := '0');
23   port(
24     clk : in  std_logic;
25     rst : in  std_logic;
26     
27     tx  : out std_logic;
28     txd : in  std_logic_vector(data_width - 1 downto 0);
29     txn : in  std_logic;
30     txb : out std_logic);
31  end rs232_send;
32  
33 -----------------------------------------------------------------------
34
35 architecture rtl of rs232_send is
36   component rs232_counter_e is
37     generic(
38       count : positive := clock_divider);
39     port(
40       clock  : in  std_logic;
41       reset  : in  std_logic;
42       enable : in  std_logic;
43       
44       done : out std_logic);
45   end component;
46
47   type state_t is (
48     state_idle_c,
49     state_send_c,
50     state_wait_c);
51   signal state_s : state_t;
52   
53   subtype frame_t is std_logic_vector(data_width - 1 + 2 + 1 downto 0);
54   signal frame_s : frame_t;
55   signal index_s : frame_t;
56   
57   signal sending_s : std_logic;
58   signal timer_s   : std_logic;
59   
60   signal done_s  : std_logic;
61 begin
62   txb <= '0' when state_s = state_idle_c
63     else '1';
64   
65   frame_s(frame_t'high) <= '1';
66   frame_s(frame_t'high - 1) <= '0';
67   frame_s(frame_t'high - 2 downto frame_t'high - 2 - (data_width - 1)) <= txd;
68   frame_s(frame_t'low + 1) <= get_parity(txd, parity_type) when parity_enabled = '1'
69                          else frame_s(frame_t'low);
70   frame_s(frame_t'low) <= '1';
71   
72   done_s <= index_s(frame_t'low + 0) when parity_enabled = '1'
73        else index_s(frame_t'low + 1);
74
75   output : process(clk)
76     variable output_v : std_logic;
77   begin
78     output_v := '0';
79     for i in frame_t'high downto frame_t'low loop
80       output_v := output_v or (frame_s(i) and index_s(i));
81     end loop;
82     tx <= output_v;
83   
84     if rising_edge(clk) then
85       case state_s is
86         when state_idle_c =>
87           index_s(frame_t'high) <= '1';
88           index_s(frame_t'high - 1 downto frame_t'low) <= (others => '0');
89         when state_send_c =>
90           index_s <= '0' & index_s(frame_t'high downto frame_t'low + 1);
91         when others =>
92           null;
93       end case;
94     end if;
95   end process;
96   
97   sequence : process(clk, rst)
98   begin
99     if rst = '1' then
100       state_s <= state_idle_c;
101     elsif rising_edge(clk) then
102       case state_s is
103         when state_idle_c =>
104           if txn = '1' then
105             state_s <= state_send_c;
106           end if;
107         when state_send_c =>
108           state_s <= state_wait_c;
109         when state_wait_c =>
110           if timer_s = '1' then
111             if done_s = '1' then
112               state_s <= state_idle_c;
113             else
114               state_s <= state_send_c;
115             end if;
116           end if;
117       end case;
118     end if;
119   end process;
120   
121   sending_s <= '1' when state_s = state_wait_c
122           else '0';
123   trigger : rs232_counter_e port map(
124     clock  => clk,
125     reset  => rst,
126     enable => sending_s,
127     
128     done   => timer_s);
129 end rtl;