-
Notifications
You must be signed in to change notification settings - Fork 0
/
SerialTx.vhd
executable file
·145 lines (127 loc) · 3.94 KB
/
SerialTx.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
----------------------------------------------------------------------------------
-- Company: Engs 31 15X
-- Engineer: E.W. Hansen
--
-- Create Date: 12:55:02 07/19/2008
-- Design Name: Lab 5
-- Module Name: SerialTx - Behavioral
-- Project Name: RS232
-- Target Devices: Spartan 3E or Spartan 6
-- Tool versions: ISE 14.7
-- Description: Serial asynchronous transmitter for RS-232 port
--
-- Revision:
-- Revision 0.01 - File Created
-- Rev (EWH) 7.17.2014, no external baud rate generator
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity SerialTx is
Port ( Clk : in STD_LOGIC;
tx_data : in STD_LOGIC_VECTOR (7 downto 0);
tx_start : in STD_LOGIC;
tx : out STD_LOGIC; -- to RS-232 interface
tx_done_tick : out STD_LOGIC);
end SerialTx;
architecture Behavioral of SerialTx is
constant CLOCK_FREQUENCY : integer := 10000000;
constant BAUD_RATE : integer := 115200;
constant BAUD_COUNT : integer := CLOCK_FREQUENCY / BAUD_RATE;
-- baud rate counter: 12 bits can handle 4800 baud at 10 MHz clock
signal br_cnt: integer range 0 to Baud_count := 0;
signal br_tick, en: std_logic:='0';
-- Parallel-to-serial register
-- 10 bits: 1 start bit, 8 data bits, 1 stop bit, no parity
signal tx_reg: std_logic_vector(9 downto 0) := "1111111111";
signal tx_ctr: unsigned(3 downto 0); -- count the bits that have been sent
signal tx_load, tx_shift : std_logic; -- register control bits
signal tx_empty : std_logic; -- register status bit
-- Controller FSM
type state_type is (sidle, ssync, sload, sshift, sdone);
signal curr_state, next_state: state_type;
begin
BaudRateClock:
process(Clk)
begin
if rising_edge(Clk) then
if en = '1' then
if br_cnt = BAUD_COUNT-1 then
br_cnt <= 0;
br_tick <= '1'; -- emit tick every BAUD_COUNT clock cycles
else
br_cnt <= br_cnt+1;
br_tick <= '0';
end if;
else
br_cnt<=0;
end if;
end if;
end process BaudRateClock;
DataRegister:
process( Clk )
begin
if rising_edge( Clk ) then
if (tx_start = '1') then
tx_reg <= '1' & tx_data & '0'; -- load with stop & data & start
elsif br_tick = '1' then -- the register is always shifting
tx_reg <= '1' & tx_reg(9 downto 1); -- shift right, pull in 1s
end if;
end if;
end process DataRegister;
tx <= tx_reg(0); -- serial output port <= lsb
ShiftCounter:
process ( Clk )
begin
if rising_edge( Clk ) then
if (tx_load = '1') then -- load counter with 10 when register is loaded
tx_ctr <= x"A";
elsif br_tick = '1' then -- count shifts (br_ticks) down to 0
if (tx_shift = '1') then
if tx_ctr > 0 then
tx_ctr <= tx_ctr - 1;
end if;
end if;
end if;
end if;
end process ShiftCounter;
tx_empty <= '1' when tx_ctr = x"0" else '0';
TxControllerComb:
process ( tx_start, tx_empty, br_tick, curr_state )
begin
-- defaults
next_state <= curr_state;
tx_load <= '0'; tx_shift <= '0'; tx_done_tick <= '0'; en<='0';
-- next state and output logic
case curr_state is
when sidle =>
if tx_start = '1' -- wait for start signal
then next_state <= ssync;
end if;
when ssync => -- sync up with baud rate
en<='1';
if br_tick = '1'
then next_state <= sload;
end if;
when sload => tx_load <= '1'; -- load the data register
en<='1';
next_state <= sshift;
when sshift => tx_shift <= '1'; -- shift the bits out
en<='1';
if tx_empty = '1' -- wait for shift counter
then next_state <= sdone;
end if;
when sdone => tx_done_tick <= '1'; -- raise the done flag
next_state <= sidle;
end case;
end process TxControllerComb;
TxControllerReg:
process ( Clk )
begin
if rising_edge(Clk) then
curr_state <= next_state;
end if;
end process TxControllerReg;
end Behavioral;