OpenCores
URL https://opencores.org/ocsvn/uart_block/uart_block/trunk

Subversion Repositories uart_block

[/] [uart_block/] [trunk/] [hdl/] [iseProject/] [uart_control.vhd] - Blame information for rev 24

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 leonardoar
--! uart control unit
2
library IEEE;
3 22 leonardoar
use IEEE.STD_LOGIC_1164.ALL;
4
use ieee.std_logic_unsigned.all;
5
use ieee.std_logic_arith.all;
6 9 leonardoar
 
7
--! Use CPU Definitions package
8
use work.pkgDefinitions.all;
9
 
10
entity uart_control is
11 13 leonardoar
    Port ( rst : in  std_logic;                                                                                                         -- Global reset
12
           clk : in  std_logic;                                                                                                         -- Global clock
13
                          WE    : in std_logic;                                                                                                         -- Write enable
14
           reg_addr : in  std_logic_vector (1 downto 0);                                         -- Register address
15 10 leonardoar
                          start : in std_logic;                                                                                                         -- Start (Strobe)
16
                          done : out std_logic;                                                                                                         -- Done (ACK)
17 13 leonardoar
           DAT_I : in  std_logic_vector ((nBitsLarge-1) downto 0);               -- Data Input (Wishbone)
18
           DAT_O : out  std_logic_vector ((nBitsLarge-1) downto 0);              -- Data output (Wishbone)
19
                          baud_wait : out std_logic_vector ((nBitsLarge-1) downto 0);    -- Signal to control the baud rate frequency
20 10 leonardoar
                          data_byte_tx : out std_logic_vector((nBits-1) downto 0);               -- 1 Byte to be send to serial_transmitter
21
                          data_byte_rx : in std_logic_vector((nBits-1) downto 0);        -- 1 Byte to be received by serial_receiver
22 13 leonardoar
           tx_data_sent : in  std_logic;                                                                                        -- Signal comming from serial_transmitter
23 14 leonardoar
                          tx_start : out std_logic;                                                                                             -- Signal to start sending serial data...
24 13 leonardoar
                          rst_comm_blocks : out std_logic;                                                                              -- Reset Communication blocks
25
           rx_data_ready : in  std_logic);                                                                              -- Signal comming from serial_receiver
26 9 leonardoar
end uart_control;
27
 
28
architecture Behavioral of uart_control is
29
signal config_clk : std_logic_vector((nBitsLarge-1) downto 0);
30
signal config_baud : std_logic_vector((nBitsLarge-1) downto 0);
31 22 leonardoar
signal received_byte : std_logic_vector((nBits-1) downto 0);
32
signal byte_to_transmit : std_logic_vector((nBits-1) downto 0);
33 9 leonardoar
 
34
signal sigDivRst : std_logic;
35
signal sigDivDone : std_logic;
36
signal sigDivQuotient : std_logic_vector((nBitsLarge-1) downto 0);
37
signal sigDivNumerator : std_logic_vector((nBitsLarge-1) downto 0);
38 22 leonardoar
signal sigDivDividend : std_logic_vector((nBitsLarge-1) downto 0);
39
 
40
-- Signals used to control the configuration
41
signal startConfigBaud : std_logic;
42
signal startConfigClk : std_logic;
43
signal startDataSend : std_logic;
44
signal commBlocksInitiated : std_logic;
45 23 leonardoar
signal startReadReg : std_logic;
46
signal alreadyConfBaud : std_logic;
47
signal alreadyConfClk : std_logic;
48 9 leonardoar
 
49
-- Divisor component
50
component divisor is
51
    Port ( rst : in  STD_LOGIC;
52
           clk : in  STD_LOGIC;
53
           quotient : out  STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0);
54
                          reminder : out  STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0);
55
           numerator : in  STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0);
56
           divident : in  STD_LOGIC_VECTOR ((nBitsLarge-1) downto 0);
57
           done : out  STD_LOGIC);
58
end component;
59
 
60
begin
61
        -- Instantiate block for calculate division
62
        uDiv : divisor port map (
63
                rst => sigDivRst,
64
                clk => clk,
65
                quotient => sigDivQuotient,
66 16 leonardoar
                reminder => open,       -- Indicates that this port will not be connected to anything
67 9 leonardoar
                numerator => sigDivNumerator,
68
                divident => sigDivDividend,
69
                done => sigDivDone
70
        );
71
 
72 22 leonardoar
        -- Process to handle the of writting the registers
73
        process (clk)
74 10 leonardoar
        begin
75 22 leonardoar
                -- On the wishbone specification we should handle the reset synchronously
76
                if rising_edge(clk) then
77
                        if rst = '1' then
78
                                config_clk <= (others => '0');
79
                                config_baud <= (others => '0');
80
                                byte_to_transmit <= (others => '0');
81
                                startConfigBaud <= '0';
82
                                startConfigClk <= '0';
83 24 leonardoar
                                startDataSend <= '0';
84 23 leonardoar
                                alreadyConfClk <= '0';
85
                                alreadyConfBaud <= '0';
86 22 leonardoar
                        elsif (WE and start) = '1'      then
87
                                case reg_addr is
88
                                        when "00" =>
89
                                                config_clk <= DAT_I;
90
                                                startConfigClk <= '1';
91
                                                startDataSend <= '0';
92
                                                startConfigBaud <= '0';
93 23 leonardoar
                                                alreadyConfClk <= '1';
94 22 leonardoar
                                        when "01" =>
95
                                                config_baud <= DAT_I;
96
                                                startConfigBaud <= '1';
97
                                                startDataSend <= '0';
98
                                                startConfigClk <= '0';
99 23 leonardoar
                                                alreadyConfBaud <= '1';
100 22 leonardoar
                                        when "10" =>
101 24 leonardoar
                                                byte_to_transmit <= DAT_I((nBits-1) downto 0);
102 22 leonardoar
                                                startConfigBaud <= '0';
103
                                                startConfigClk <= '0';
104
                                                startDataSend <= '1';
105
                                        when others =>
106
                                                startConfigBaud <= '0';
107
                                                startConfigClk <= '0';
108
                                                startDataSend <= '0';
109
                                end case;
110 24 leonardoar
                        else
111
                                startDataSend <= '0';
112 22 leonardoar
                        end if;
113
                end if;
114 10 leonardoar
        end process;
115
 
116 22 leonardoar
        -- Process to handle the reading of registers
117
        process (clk)
118
        begin
119
                -- On the wishbone specification we should handle the reset synchronously
120
                if rising_edge(clk) then
121
                        if rst = '1' then
122
                                DAT_O <= (others => 'Z');
123
                                startReadReg <= '0';
124
                        elsif ((WE = '0') and (start = '1')) then
125
                                startReadReg <= '1';
126
                                case reg_addr is
127
                                        when "00" =>
128
                                                DAT_O <= config_clk;
129
                                        when "01" =>
130
                                                DAT_O <= config_baud;
131
                                        when "10" =>
132
                                                DAT_O <= conv_std_logic_vector(0, (nBitsLarge-nBits)) & byte_to_transmit;
133
                                        when "11" =>
134
                                                DAT_O <= conv_std_logic_vector(0, (nBitsLarge-nBits)) & received_byte;
135
                                        when others =>
136
                                                null;
137
                                end case;
138
                        end if;
139
                end if;
140
        end process;
141
 
142
        -- Process that stores the data that comes from the serial receiver block
143
        process (rx_data_ready)
144
        begin
145
                if rising_edge(rx_data_ready) then
146
                        received_byte <= data_byte_rx;
147
                else
148
                        received_byte <= received_byte;
149
                end if;
150
        end process;
151
 
152
        -- Process to send data over the serial transmitter
153 24 leonardoar
        process (clk)
154
        variable sendDataStates : sendByte;
155 22 leonardoar
        begin
156 23 leonardoar
                if rising_edge(clk) then
157
                        if (rst = '1') then
158 24 leonardoar
                                sendDataStates := idle;
159 23 leonardoar
                        else
160 24 leonardoar
                                case sendDataStates is
161
                                        when idle =>
162
                                                if commBlocksInitiated = '1' and startDataSend = '1' then
163
                                                        sendDataStates := prepare_byte;
164
                                                end if;
165
 
166
                                        when prepare_byte =>
167
                                                data_byte_tx <= byte_to_transmit;
168
                                                tx_start <= '0';
169
                                                sendDataStates := start_sending;
170
 
171
                                        when start_sending =>
172
                                                tx_start <= '1';
173
                                                sendDataStates := wait_completion;
174
 
175
                                        when wait_completion =>
176
                                                if tx_data_sent = '1' then
177
                                                        sendDataStates := idle;
178
                                                end if;
179
                                end case;
180 22 leonardoar
                        end if;
181
                end if;
182
        end process;
183
 
184
        -- Process to send the ACK signal, remember that optimally this ACK should be as fast as possible
185
        -- to avoid locking the bus, on this case if you send a more bytes then you can transmit the ideal
186
        -- is to create an error flag to indicate overrun.
187
        -- On this case on any attempt of reading or writting on registers we will be lock on 1 cycle
188
        process (clk, rst, startConfigBaud, startConfigClk, startDataSend, startReadReg )
189
        variable joinSignal : std_logic_vector(3 downto 0);
190
        variable cont_steps : integer range 0 to 3;
191
        begin
192
                if rising_edge(clk) then
193
                        if rst = '1' then
194
                                done <= '1';
195
                                cont_steps := 0;
196
                        else
197
                                joinSignal := startConfigBaud & startConfigClk & startDataSend & startReadReg;
198
                                if (joinSignal = "0000") then
199 10 leonardoar
                                        done <= '1';
200 22 leonardoar
                                else
201
                                        case cont_steps is
202
                                                when 0 =>
203
                                                        if start = '1' then
204
                                                                done <= '0';
205
                                                        end if;
206
                                                when others =>
207
                                                        done <= '1';
208
                                        end case;
209 10 leonardoar
 
210 22 leonardoar
                                        if cont_steps < 2 then
211
                                                cont_steps := cont_steps + 1;
212 10 leonardoar
                                        else
213 22 leonardoar
                                                cont_steps := 0;
214 10 leonardoar
                                        end if;
215 22 leonardoar
                                end if;
216
                        end if;
217
                end if;
218
        end process;
219
 
220
        -- Process to calculate the amount of cycles to wait (clock_speed / desired_baud), and initiate the board
221 24 leonardoar
        process (alreadyConfClk,alreadyConfBaud, clk)
222 22 leonardoar
        variable cont_steps : integer range 0 to 3;
223
        begin
224 23 leonardoar
                if (alreadyConfClk and alreadyConfBaud) = '0' then
225 22 leonardoar
                        sigDivRst <= '1';
226
                        cont_steps := 0;
227
                        baud_wait <= (others => '0');
228
                        commBlocksInitiated <= '0';
229
                elsif rising_edge(clk) then
230
                        if cont_steps < 3 then
231
                                cont_steps := cont_steps + 1;
232
                        else
233
                                cont_steps := 3;
234
                        end if;
235
 
236
                        case cont_steps is
237
                                when 1 =>
238
                                        sigDivNumerator <= config_clk;
239
                                        sigDivDividend <= config_baud;
240
                                        sigDivRst <= '1';
241
                                when 2 =>
242
                                        sigDivRst <= '0';
243
                                when others =>
244
                                        null;
245
                        end case;
246
 
247
                        -- Enable the communication block when the baud is calculated
248
                        if sigDivDone = '1' then
249
                                rst_comm_blocks <= '0';
250
                                baud_wait <= sigDivQuotient;
251
                                commBlocksInitiated <= '1';
252
                        else
253
                                baud_wait <= (others => '0');
254
                                rst_comm_blocks <= '1';
255
                                commBlocksInitiated <= '0';
256
                        end if;
257
                end if;
258 9 leonardoar
        end process;
259
 
260
end Behavioral;
261
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.