Aktuální adresář: FITkit /
trunk /
fpga /
ctrls /
serial /
serial_tx.vhd
1 -- serial_tx.vhd : Transmitter
2 -- Copyright (C) 2007 Brno University of Technology,
3 -- Faculty of Information Technology
4 -- Author(s): Zdenek Vasicek (xvasic11 AT stud.fit.vutbr.cz)
5 --
6 -- LICENSE TERMS
7 --
8 -- Redistribution and use in source and binary forms, with or without
9 -- modification, are permitted provided that the following conditions
10 -- are met:
11 -- 1. Redistributions of source code must retain the above copyright
12 -- notice, this list of conditions and the following disclaimer.
13 -- 2. Redistributions in binary form must reproduce the above copyright
14 -- notice, this list of conditions and the following disclaimer in
15 -- the documentation and/or other materials provided with the
16 -- distribution.
17 -- 3. All advertising materials mentioning features or use of this software
18 -- or firmware must display the following acknowledgement:
19 --
20 -- This product includes software developed by the University of
21 -- Technology, Faculty of Information Technology, Brno and its
22 -- contributors.
23 --
24 -- 4. Neither the name of the Company nor the names of its contributors
25 -- may be used to endorse or promote products derived from this
26 -- software without specific prior written permission.
27 --
28 -- This software or firmware is provided ``as is'', and any express or implied
29 -- warranties, including, but not limited to, the implied warranties of
30 -- merchantability and fitness for a particular purpose are disclaimed.
31 -- In no event shall the company or contributors be liable for any
32 -- direct, indirect, incidental, special, exemplary, or consequential
33 -- damages (including, but not limited to, procurement of substitute
34 -- goods or services; loss of use, data, or profits; or business
35 -- interruption) however caused and on any theory of liability, whether
36 -- in contract, strict liability, or tort (including negligence or
37 -- otherwise) arising in any way out of the use of this software, even
38 -- if advised of the possibility of such damage.
39 --
40 -- $Id$
41 --
42 --
43
44 library IEEE;
45 use IEEE.STD_LOGIC_1164.ALL;
46 use IEEE.STD_LOGIC_ARITH.ALL;
47 use IEEE.STD_LOGIC_UNSIGNED.ALL;
48 use work.serial_cfg.all;
49
50 entity serial_transmitter is
51 generic (
52 SPEED : serial_speed := s460800Bd;
53 DATAWIDTH : serial_databit := 8;
54 STOPBITS : serial_stopbit := 1;
55 PARITY : serial_parity := sParityEven
56 );
57 port (
58 -- Common interface
59 CLK : in std_logic;
60 RESET : in std_logic;
61
62 DATA_IN : in std_logic_vector(DATAWIDTH-1 downto 0);
63 WRITE_EN : in std_logic;
64
65 BUSY : out std_logic;
66
67 -- Serial interface
68 TXD : out std_logic
69 );
70 end serial_transmitter;
71
72
73 architecture behavioral of serial_transmitter is
74
75 type FSMstate is (SIdle, SWaitTx, SStartbit, SDataBits, SParityBit, SStopBit1, SStopBit2, SStopBit3);
76 signal pstate : FSMstate; -- actual state
77 signal nstate : FSMstate; -- next state
78
79 signal tx_en : std_logic;
80 signal data_shreg : std_logic_vector(DATAWIDTH-1 downto 0);
81 signal data_shen : std_logic;
82 signal bitcnt_reg : std_logic_vector(3 downto 0);
83 signal bitcnt_en : std_logic;
84 signal bitcnt_rst : std_logic;
85 signal bit_cmp : std_logic;
86 signal outmx_sel : std_logic_vector(1 downto 0);
87 signal parity_reg : std_logic;
88 signal txbusy_reg : std_logic;
89 signal txbusy_rst : std_logic;
90
91 component serial_gen
92 generic (
93 SPEED : serial_speed;
94 FREQMULT : positive
95 );
96 port(
97 CLK : in std_logic;
98 RESET : in std_logic;
99 EN : in std_logic;
100
101 OUTPUT : out std_logic
102 );
103 end component;
104
105 begin
106 -- ===========================================================================================================
107 -- Transmitter
108 -- ===========================================================================================================
109 TXD <= '1' when outmx_sel="00" else --idle, stop bit
110 '0' when outmx_sel="01" else --start bit
111 data_shreg(0) when outmx_sel="10" else --data bit
112 parity_reg; --parity bit
113
114 BUSY <= txbusy_reg;
115
116 --Baudrate generator
117 txclk_gen: serial_gen
118 generic map (
119 SPEED => SPEED,
120 FREQMULT => 1
121 )
122 port map (
123 CLK => CLK,
124 RESET => RESET,
125 EN => '1',
126 OUTPUT => tx_en
127 );
128
129 -- Busy register
130 process (RESET, CLK)
131 begin
132 if (RESET = '1') then
133 txbusy_reg <= '0';
134 elsif (CLK'event) and (CLK = '1') then
135 if (txbusy_rst='1') then
136 txbusy_reg <= '0';
137 elsif (WRITE_EN='1') and (txbusy_reg='0') then
138 txbusy_reg <= '1';
139 end if;
140 end if;
141 end process;
142
143 -- Data shift register
144 process (RESET, CLK)
145 begin
146 if (CLK'event) and (CLK = '1') then
147 if (WRITE_EN='1') and (txbusy_reg='0') then -- parallel load
148 data_shreg <= DATA_IN;
149
150 if (PARITY = sParityEven) then
151 parity_reg <= '0'; --even parity (suda parita)
152 else
153 parity_reg <= '1'; --odd parity (licha parita)
154 end if;
155
156 elsif (data_shen='1') and (tx_en='1') then -- shift enable
157 data_shreg <= '0' & data_shreg(DATAWIDTH-1 downto 1);
158 parity_reg <= parity_reg xor data_shreg(0);
159 end if;
160 end if;
161 end process;
162
163 --Bit counter
164 process (RESET, CLK)
165 begin
166 if (CLK'event) and (CLK = '1') then
167 if (bitcnt_rst='1') then
168 bitcnt_reg <= (others => '0');
169 elsif (bitcnt_en='1') and (tx_en='1') then
170 bitcnt_reg <= bitcnt_reg + 1;
171 end if;
172 end if;
173 end process;
174
175 --bit comparator
176 bit_cmp <= '1' when (conv_integer(bitcnt_reg) = DATAWIDTH-1) else '0';
177
178 --Present State registr
179 pstatereg: process(RESET, CLK)
180 begin
181 if (RESET='1') then
182 pstate <= SIdle;
183 elsif (CLK'event) and (CLK='1') then
184 pstate <= nstate;
185 end if;
186 end process;
187
188 --Next State logic, Output logic
189 nstate_logic: process(pstate, txbusy_reg, tx_en, bit_cmp)
190 begin
191 data_shen <= '0';
192 outmx_sel <= "00";
193 bitcnt_en <= '0';
194 bitcnt_rst <= '0';
195 txbusy_rst <= '0';
196
197 nstate <= SIdle;
198 case pstate is
199 when SIdle =>
200 if (txbusy_reg='1') then
201 nstate <= SWaitTx;
202 end if;
203
204 --Synchronization with baudrate generator
205 when SWaitTx =>
206 nstate <= SWaitTx;
207
208 if (tx_en='1') then
209 nstate <= SStartBit;
210
211 bitcnt_rst <= '1';
212 end if;
213
214 --Start bit
215 when SStartBit =>
216 nstate <= SStartbit;
217
218 outmx_sel <= "01";
219 if (tx_en='1') then
220 nstate <= SDataBits;
221 end if;
222
223 -- Data bits
224 when SDataBits =>
225 nstate <= SDataBits;
226
227 data_shen <= '1';
228 bitcnt_en <= '1';
229 outmx_sel <= "10";
230 if (tx_en='1') and (bit_cmp='1') then
231 if (PARITY = sParityNone) then
232 if (STOPBITS=2) then -- two stop bits
233 nstate <= SStopBit1;
234 else -- one stop bit
235 nstate <= SStopBit2;
236 end if;
237 else
238 nstate <= SParityBit;
239 end if;
240 end if;
241
242 -- Parity bit
243 when SParityBit =>
244 nstate <= SParityBit;
245
246 outmx_sel <= "11";
247 if (tx_en='1') then
248 if (STOPBITS=2) then -- two stop bits
249 nstate <= SStopBit1;
250 else -- one stop bit
251 nstate <= SStopBit2;
252 end if;
253 end if;
254
255 -- Stop bit
256 when SStopBit1 =>
257 nstate <= SStopBit1;
258
259 outmx_sel <= "00";
260 if (tx_en='1') then
261 nstate <= SStopBit2;
262 end if;
263
264 -- Stop bit - busy reset
265 when SStopBit2 =>
266 nstate <= SStopBit3;
267
268 outmx_sel <= "00";
269 txbusy_rst <= '1';
270
271 -- Stop bit
272 when SStopBit3 =>
273 nstate <= SStopBit3;
274
275 outmx_sel <= "00";
276 if (tx_en='1') then
277 if (txbusy_reg='1') then
278 nstate <= SStartBit;
279
280 bitcnt_rst <= '1';
281 else
282 nstate <= SIdle;
283 end if;
284 end if;
285
286 when others => null;
287 end case;
288 end process;
289
290 end behavioral;
291
292