uart_tx: WIP, todo: testbench
[hwmod.git] / src / uart_tx.vhd
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4 --use work.gen_pkg.all;
5
6 --package int_types is
7 --      type STATE_UART_TX is (IDLE, STARTBITS, PAYLOAD, PARITY, STOP, DONE);
8 --      type PARITY_TYPE is (ODD, EVEN, NONE);
9 --end package int_types;
10
11 entity uart_tx is
12         generic (
13                 CLK_FREQ : integer := 33000000;
14                 BAUDRATE : integer := 115200
15         );
16         port(
17                 sys_clk : in std_logic;
18                 sys_res_n : in std_logic;
19                 txd : out std_logic;
20                 tx_data : in std_logic_vector(7 downto 0);
21                 tx_new : in std_logic;
22                 tx_done : out std_logic
23         );
24 end entity uart_tx;
25
26 architecture beh of uart_tx is
27         constant BAUD : integer := CLK_FREQ/BAUDRATE;
28
29         type STATE_UART_TX is (IDLE, SENDBITS, DONE);
30         signal state_int, state_next : STATE_UART_TX;
31
32         signal txd_next, txd_int : std_logic;
33         signal tx_done_next, tx_done_int : std_logic;
34         signal tx_to_send : std_logic_vector(0 to 10);
35         signal bitcnt_int, bitcnt_next : integer range 0 to 10;
36         signal baudcnt_int, baudcnt_next : integer range 0 to BAUD;
37 begin
38         txd <= txd_int;
39         tx_done <= tx_done_int;
40
41         process (sys_clk, sys_res_n)
42         begin
43                 if sys_res_n = '0' then
44                         state_int <= IDLE;
45                         txd_int <= '1';
46                         tx_done_int <= '0';
47                         bitcnt_int <= 0;
48                         baudcnt_int <= 0;
49                         tx_to_send <= (others => '0');
50                 elsif rising_edge(sys_clk) then
51                         state_int <= state_next;
52                         txd_int <= txd_next;
53                         tx_done_int <= tx_done_next;
54                         bitcnt_int <= bitcnt_next;
55                         baudcnt_int <= baudcnt_next;
56                         -- HIGHBIT (1) | STARTBIT (1) | DATA (8) | STOPBIT (1)
57                         -- TODO: passt das wegen der endianess?
58                         tx_to_send <= '1' & '0' & tx_data & '1';
59                 end if;
60         end process;
61
62         process(tx_new, tx_to_send, state_int, bitcnt_int, baudcnt_int)
63         begin
64                 state_next <= state_int;
65                 tx_done_next <= tx_done_int;
66                 txd_next <= txd_int;
67                 bitcnt_next <= bitcnt_int;
68                 baudcnt_next <= baudcnt_int;
69
70                 case state_int is
71                         when IDLE =>
72                                 tx_done_next <= '0';
73                                 txd_next <= '1';
74                                 bitcnt_next <= 0;
75                                 -- das highbyte sofort anlegen
76                                 baudcnt_next <= BAUD;
77                                 if tx_new = '1' then
78                                         state_next <= SENDBITS;
79                                 end if;
80                         when SENDBITS =>
81                                 if bitcnt_int <= 10 then
82                                         if baudcnt_int < BAUD then
83                                                 baudcnt_next <= baudcnt_int + 1;
84                                         else
85                                                 txd_next <= tx_to_send(bitcnt_int);
86                                                 bitcnt_next <= bitcnt_int + 1;
87                                                 baudcnt_next <= 0;
88                                         end if;
89                                 else
90                                         -- fuer das stopbit auch noch warten
91                                         if baudcnt_int < BAUD then
92                                                 baudcnt_next <= baudcnt_int + 1;
93                                         else
94                                                 state_next <= DONE;
95                                         end if;
96                                 end if;
97                         when DONE =>
98                                 tx_done_next <= '1';
99                                 if tx_new = '0' then
100                                         state_next <= IDLE;
101                                 end if;
102                 end case;
103         end process;
104 end architecture beh;