2 use ieee.std_logic_1164.all;
3 use ieee.std_logic_arith.all;
4 use ieee.std_logic_unsigned.all;
8 output_fifo_width : integer := 2;
9 input_fifo_width : integer := 2
13 per_addr : in std_logic_vector (7 downto 0);
14 per_din : in std_logic_vector (15 downto 0);
15 per_en : in std_logic;
16 per_wen : in std_logic_vector (1 downto 0);
18 per_irq_acc : in std_logic;
19 per_irq : out std_logic;
20 per_dout : out std_logic_vector (15 downto 0);
27 --------------------------------------------------------------------------------
29 architecture dataflow of uart is
31 component tx_control is
35 tx_ready : in std_logic;
36 fifo_empty : in std_logic;
37 tx_we : out std_logic;
38 fifo_pop : out std_logic
42 component transmitter is
46 data : in std_logic_vector (7 downto 0);
48 ready : out std_logic;
53 component rx_control is
58 bad_start_bit : in std_logic;
59 bad_stop_bit : in std_logic;
60 rx_ready : in std_logic;
61 rx_reset : out std_logic;
62 rx_en : out std_logic;
63 fifo_we : out std_logic;
64 clk_en : out std_logic
66 end component rx_control;
74 ready : out std_logic;
75 bad_start_bit : out std_logic;
76 bad_stop_bit : out std_logic;
77 data : out std_logic_vector (7 downto 0)
79 end component receiver;
90 clear_ow : in std_logic;
91 d_in : in std_logic_vector (7 downto 0);
92 d_out : out std_logic_vector (7 downto 0);
94 hfull : out std_logic;
95 empty : out std_logic;
96 overflow : out std_logic
100 component baud_gen is
104 reset : in std_logic;
105 scale : in std_logic_vector (15 downto 0);
106 clk_baud : out std_logic
110 --------------------------------------------------------------------------------
112 alias per_din_low : std_logic_vector (7 downto 0) is per_din (7 downto 0);
113 alias per_din_high : std_logic_vector (7 downto 0) is per_din (15 downto 8);
115 type boolean_vector is array (natural range <>) of boolean;
117 --------------------------------------------------------------------------------
119 constant base_addr : integer := 16#0100#;
121 constant UBAUD : integer := base_addr + 00; -- 2B - Baud rate generator
122 constant UTX : integer := base_addr + 02; -- 1B - Transmit data
123 constant URX : integer := base_addr + 04; -- 1B - Read data
124 constant USTAT : integer := base_addr + 06; -- 1B - Rx & Tx status
125 constant UIE : integer := base_addr + 07; -- 1B - Interrupt enable
127 signal reg_we : std_logic_vector (511 downto 0);
128 signal reg_re : std_logic_vector (511 downto 0);
129 signal reg_re_b : boolean_vector (512 downto 0);
132 signal reg_baud : std_logic_vector (15 downto 0) := (others => '0');
133 signal reg_stat : std_logic_vector (7 downto 0);
134 signal reg_ie : std_logic_vector (7 downto 0) := (others => '0');
137 signal tx_clk : std_logic;
138 signal tx_data : std_logic_vector (7 downto 0);
139 signal tx_we : std_logic;
140 signal tx_ready : std_logic;
141 signal tx_fifo_full : std_logic;
142 signal tx_fifo_hfull : std_logic;
143 signal tx_fifo_empty : std_logic;
144 signal tx_fifo_re : std_logic;
146 signal rx_clk : std_logic;
147 signal rx_clk_en : std_logic;
148 signal rx_en : std_logic;
149 signal rx_ready : std_logic;
150 signal rx_reset : std_logic;
151 signal rx_data : std_logic_vector (7 downto 0);
152 signal rx_bad_start_bit : std_logic;
153 signal rx_bad_stop_bit : std_logic;
154 signal rx_fifo_we : std_logic;
155 signal rx_fifo_out : std_logic_vector (7 downto 0);
156 signal rx_fifo_full : std_logic;
157 signal rx_fifo_hfull : std_logic;
158 signal rx_fifo_empty : std_logic;
159 signal rx_fifo_ow : std_logic;
160 signal rx_fifo_ow_clear : std_logic;
162 --------------------------------------------------------------------------------
167 process (per_addr, per_wen, per_en)
169 for i in reg_re'range loop
170 reg_re_b (i) <= false;
174 if (per_en = '1' and per_addr = i/2) then
175 -- Register of the corresponding address is always read, so
176 -- read-modify-write operation in one cycle is possible.
177 reg_re_b (i) <= true;
180 if (per_wen (i mod 2) = '1') then
187 --------------------------------------------------------------------------------
189 --------------------------------------------------------------------------------
191 tx_control_0 : tx_control port map (
194 tx_ready => tx_ready,
195 fifo_empty => tx_fifo_empty,
197 fifo_pop => tx_fifo_re
200 tx_transmitter_0 : transmitter port map (
209 tx_fifo_0 : fifo port map (
215 d_in => per_din (7 downto 0),
217 full => tx_fifo_full,
218 hfull => tx_fifo_hfull,
219 empty => tx_fifo_empty,
223 tx_baud_gen_0 : baud_gen port map (
231 --------------------------------------------------------------------------------
233 --------------------------------------------------------------------------------
235 rx_control_0 : rx_control
240 bad_start_bit => rx_bad_start_bit,
241 bad_stop_bit => rx_bad_stop_bit,
242 rx_ready => rx_ready,
243 rx_reset => rx_reset,
245 fifo_we => rx_fifo_we,
246 clk_en => rx_clk_en);
248 rx_receiver_0 : receiver
255 bad_start_bit => rx_bad_start_bit,
256 bad_stop_bit => rx_bad_stop_bit,
265 clear_ow => rx_fifo_ow_clear,
267 d_out => rx_fifo_out,
268 full => rx_fifo_full,
269 hfull => rx_fifo_hfull,
270 empty => rx_fifo_empty,
271 overflow => rx_fifo_ow);
273 rx_baud_gen_0 : baud_gen
281 --------------------------------------------------------------------------------
283 --------------------------------------------------------------------------------
285 process (mclk, puc) is
288 reg_baud <= (others => '0');
289 reg_ie <= (others => '0');
291 elsif mclk'event and mclk = '1' then
292 if reg_we (UBAUD) = '1' then
293 reg_baud (7 downto 0) <= per_din_low;
296 if reg_we (UBAUD+1) = '1' then
297 reg_baud (15 downto 8) <= per_din_high;
300 if reg_we (USTAT) = '1' then
301 reg_ie <= per_din_low;
307 reg_stat <= tx_fifo_empty &
317 per_irq <= '1' when (reg_stat and reg_ie and "10011100") /= "00000000" else '0' ;
319 per_dout <= reg_baud when reg_re_b (UBAUD) else
320 "00000000" & tx_data when reg_re_b (UTX) else
321 "00000000" & rx_fifo_out when reg_re_b (URX) else
322 reg_ie & reg_stat when reg_re_b (USTAT) else
325 --------------------------------------------------------------------------------
327 rx_fifo_ow_clear <= per_din (1) and reg_we (USTAT);