1 | library ieee;
|
2 | use ieee.std_logic_1164.all;
|
3 | use ieee.numeric_std.all;
|
4 |
|
5 | -- transmission 'least significant bit first'
|
6 |
|
7 | entity transmitter is
|
8 | generic(freq: integer := 100e6;
|
9 | baud: integer := 115200;
|
10 | nticks: integer := 16;
|
11 | databits: integer := 8; -- allowed values 5-8
|
12 | paritybit: integer := 0;
|
13 | -- 0 = no parity, 1 = odd, 2 = even
|
14 | stopbits: integer := 2); -- only full, 1 or 2
|
15 | port(clk: in std_logic;
|
16 | reset: in std_logic;
|
17 | tx: out std_logic;
|
18 | done: out std_logic;
|
19 | busy: out std_logic;
|
20 | data: in std_logic_vector(databits-1 downto 0);
|
21 | take_data_pulse: in std_logic);
|
22 | end entity;
|
23 |
|
24 | architecture behaviour of transmitter is
|
25 |
|
26 | constant oversample_freq: integer := baud * nticks;
|
27 | constant n: integer := freq / oversample_freq;
|
28 |
|
29 | type fsm is (idle, start_transmit,
|
30 | data_transmit, parity_transmit,
|
31 | stop_transmit, done_pulse);
|
32 | signal state_reg, state_next: fsm := idle;
|
33 |
|
34 | signal count_reg, count_next: integer range 0 to n := 0;
|
35 | signal data_reg, data_next: std_logic_vector(databits-1 downto 0);
|
36 |
|
37 | signal dbits_reg, dbits_next: integer range 0 to databits := 0;
|
38 | signal sbits_reg, sbits_next: integer range 0 to stopbits := 0;
|
39 |
|
40 | signal even_parity, odd_parity: std_logic := '0';
|
41 |
|
42 | begin
|
43 |
|
44 | update: process(clk, reset)
|
45 | begin
|
46 | if reset = '1' then
|
47 | state_reg <= idle;
|
48 | count_reg <= 0;
|
49 | data_reg <= (others => '0');
|
50 | dbits_reg <= 0;
|
51 | sbits_reg <= 0;
|
52 | elsif rising_edge(clk) then
|
53 | state_reg <= state_next;
|
54 | count_reg <= count_next;
|
55 | data_reg <= data_next;
|
56 | dbits_reg <= dbits_next;
|
57 | sbits_reg <= sbits_next;
|
58 | end if;
|
59 | end process;
|
60 |
|
61 | logic: process(state_reg, take_data_pulse,
|
62 | count_reg, dbits_reg, sbits_reg,
|
63 | data_reg, even_parity, odd_parity)
|
64 | begin
|
65 | tx <= '0';
|
66 | busy <= '1';
|
67 | done <= '0';
|
68 | state_next <= state_reg;
|
69 | data_next <= data_reg;
|
70 | sbits_next <= sbits_reg;
|
71 | dbits_next <= dbits_reg;
|
72 | count_next <= count_reg;
|
73 | case state_reg is
|
74 | when idle =>
|
75 | tx <= '1';
|
76 | busy <= '0';
|
77 | count_next <= 0;
|
78 | if take_data_pulse = '1' then
|
79 | data_next <= data;
|
80 | sbits_next <= 0;
|
81 | dbits_next <= 0;
|
82 | state_next <= start_transmit;
|
83 | end if;
|
84 | when start_transmit =>
|
85 | tx <= '0';
|
86 | count_next <= count_reg + 1;
|
87 | if count_reg = n-1 then
|
88 | count_next <= 0;
|
89 | state_next <= data_transmit;
|
90 | end if;
|
91 | when data_transmit =>
|
92 | count_next <= count_reg + 1;
|
93 | tx <= data_reg(dbits_reg);
|
94 | if count_reg = n-1 then
|
95 | count_next <= 0;
|
96 | dbits_next <= dbits_reg + 1;
|
97 | if dbits_reg = databits-1 then
|
98 | if paritybit = 0 then
|
99 | state_next <= stop_transmit;
|
100 | else
|
101 | state_next <= parity_transmit;
|
102 | end if;
|
103 | end if;
|
104 | end if;
|
105 | when parity_transmit =>
|
106 | tx <= '0';
|
107 | count_next <= count_reg + 1;
|
108 | if count_reg = n-1 then
|
109 | count_next <= 0;
|
110 | state_next <= stop_transmit;
|
111 | end if;
|
112 | if paritybit = 1 then -- should be made odd
|
113 | if even_parity = '1' then
|
114 | tx <= '1';
|
115 | else
|
116 | tx <= '0';
|
117 | end if;
|
118 | else -- should be made even
|
119 | if even_parity = '1' then
|
120 | tx <= '0';
|
121 | else
|
122 | tx <= '1';
|
123 | end if;
|
124 | end if;
|
125 | when stop_transmit =>
|
126 | tx <= '1';
|
127 | count_next <= count_reg + 1;
|
128 | if count_reg = n-1 then
|
129 | count_next <= 0;
|
130 | sbits_next <= sbits_reg + 1;
|
131 | if sbits_reg = stopbits-1 then
|
132 | state_next <= done_pulse;
|
133 | end if;
|
134 | end if;
|
135 | when done_pulse =>
|
136 | tx <= '1';
|
137 | busy <= '0';
|
138 | done <= '1';
|
139 | state_next <= idle;
|
140 | end case;
|
141 | end process;
|
142 |
|
143 | parity: process(data_reg)
|
144 | variable even: std_logic;
|
145 | begin
|
146 | even := '1';
|
147 | for i in data_reg'range loop
|
148 | if data_reg(i) = '1' then
|
149 | even := not even;
|
150 | end if;
|
151 | end loop;
|
152 | even_parity <= even;
|
153 | odd_parity <= not even;
|
154 | end process;
|
155 |
|
156 | end architecture;
|