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 36

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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