d10a0b7329d6a207c8bdf65169f25002e7603a2f
[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     state_idle_c,
48     state_send_c,
49     state_wait_c);
50   signal state_s : state_t;
51   
52   subtype frame_t is std_logic_vector(data_width - 1 + 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 <= '0' when state_s = state_idle_c
62     else '1';
63   
64   frame_s(frame_t'high) <= '1';
65   frame_s(frame_t'high - 1) <= '0';
66   frame_s(frame_t'high - 2 downto frame_t'high - 2 - (data_width - 1)) <= txd;
67   frame_s(frame_t'low + 1) <= get_parity(txd, parity_type) when parity_enabled = '1'
68                          else frame_s(frame_t'low);
69   frame_s(frame_t'low) <= '1';
70   
71   done_s <= index_s(frame_t'low + 0) when parity_enabled = '1'
72        else index_s(frame_t'low + 1);
73
74   output : process(clk)
75     variable output_v : std_logic;
76   begin
77     output_v := '0';
78     for i in frame_t'high downto frame_t'low loop
79       output_v := output_v or (frame_s(i) and index_s(i));
80     end loop;
81     tx <= output_v;
82   
83     if rising_edge(clk) then
84       case state_s is
85         when state_idle_c =>
86           index_s(frame_t'high) <= '1';
87           index_s(frame_t'high - 1 downto frame_t'low) <= (others => '0');
88         when state_send_c =>
89           index_s <= '0' & index_s(frame_t'high downto frame_t'low + 1);
90         when others =>
91           null;
92       end case;
93     end if;
94   end process;
95   
96   sequence : process(clk, rst)
97   begin
98     if rst = '1' then
99       state_s <= state_idle_c;
100     elsif rising_edge(clk) then
101       case state_s is
102         when state_idle_c =>
103           if txn = '1' then
104             state_s <= state_send_c;
105           end if;
106         when state_send_c =>
107           state_s <= state_wait_c;
108         when state_wait_c =>
109           if timer_s = '1' then
110             if done_s = '1' then
111               state_s <= state_idle_c;
112             else
113               state_s <= state_send_c;
114             end if;
115           end if;
116       end case;
117     end if;
118   end process;
119   
120   sending_s <= '1' when state_s = state_wait_c
121           else '0';
122   trigger : rs232_counter_e port map(
123     clock  => clk,
124     reset  => rst,
125     enable => sending_s,
126     
127     done   => timer_s);
128 end rtl;