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

Subversion Repositories System11

[/] [System11/] [trunk/] [rtl/] [vhdl/] [rxunit3.vhd] - Blame information for rev 4

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

Line No. Rev Author Line
1 4 dilbert57
--===========================================================================--
2
--
3
--  S Y N T H E Z I A B L E    miniUART   C O R E
4
--
5
--  www.OpenCores.Org - January 2000
6
--  This core adheres to the GNU public license  
7
--
8
-- Design units   : miniUART core for the System68
9
--
10
-- File name      : rxunit3.vhd
11
--
12
-- Purpose        : Implements an miniUART device for communication purposes 
13
--                  between the cpu68 cpu and the Host computer through
14
--                  an RS-232 communication protocol.
15
--                  
16
-- Dependencies   : ieee.std_logic_1164.all;
17
--                  ieee.numeric_std.all;
18
--
19
--===========================================================================--
20
-------------------------------------------------------------------------------
21
-- Revision list
22
-- Version   Author                 Date                        Changes
23
--
24
-- 0.1      Ovidiu Lupas     15 January 2000                   New model
25
-- 2.0      Ovidiu Lupas     17 April   2000  samples counter cleared for bit 0
26
--        olupas@opencores.org
27
--
28
-- 3.0      John Kent         5 January 2003  Added 6850 word format control
29
-- 3.1      John Kent        12 January 2003  Significantly revamped receive code.
30
-- 3.2      John Kent        10 January 2004  Rewrite of code.
31
--        dilbert57@opencores.org
32
-------------------------------------------------------------------------------
33
-- Description    : Implements the receive unit of the miniUART core. Samples
34
--                  16 times the RxD line and retain the value in the middle of
35
--                  the time interval. 
36
library ieee;
37
   use ieee.std_logic_1164.all;
38
   use ieee.std_logic_unsigned.all;
39
 
40
-------------------------------------------------------------------------------
41
-- Receive unit
42
-------------------------------------------------------------------------------
43
entity RxUnit is
44
  port (
45
     Clk    : in  Std_Logic;  -- Clock signal
46
     Reset  : in  Std_Logic;  -- Reset input
47
     ReadD  : in  Std_Logic;  -- Read data signal
48
     WdFmt  : in  Std_Logic_Vector(2 downto 0); -- word format
49
     BdFmt  : in  Std_Logic_Vector(1 downto 0); -- baud format
50
     RxClk  : in  Std_Logic;  -- RS-232 clock input
51
     RxDat  : in  Std_Logic;  -- RS-232 data input
52
     FRErr  : out Std_Logic;  -- Status signal
53
     ORErr  : out Std_Logic;  -- Status signal
54
          PAErr  : out Std_logic;  -- Status signal
55
     DARdy  : out Std_Logic;  -- Status signal
56
     DAOut  : out Std_Logic_Vector(7 downto 0)
57
          );
58
end; --================== End of entity ==============================--
59
-------------------------------------------------------------------------------
60
-- Architecture for receive Unit
61
-------------------------------------------------------------------------------
62
architecture Behaviour of RxUnit is
63
  -----------------------------------------------------------------------------
64
  -- Signals
65
  -----------------------------------------------------------------------------
66
  signal RxDebDel0  : Std_Logic;             -- Debounce Delayed Rx Data
67
  signal RxDebDel1  : Std_Logic;             -- Debounce Delayed Rx Data
68
  signal RxDebDel2  : Std_Logic;             -- Debounce Delayed Rx Data
69
  signal RxDebDel3  : Std_Logic;             -- Debounce Delayed Rx Data
70
  signal RxDeb      : Std_Logic;             -- Debounced Rx Data
71
  signal RxDatDel   : Std_Logic;             -- Delayed Rx Data
72
  signal RxDatEdge  : Std_Logic;             -- Rx Data Edge pulse
73
  signal RxClkDel   : Std_Logic;             -- Delayed Rx Input Clock
74
  signal RxClkEdge  : Std_Logic;             -- Rx Input Clock Edge pulse
75
  signal RxClkCnt   : Std_Logic_Vector(5 downto 0); -- Rx Baud Clock Counter
76
  signal RxBdClk    : Std_Logic;             -- Rx Baud Clock
77
  signal RxBdDel    : Std_Logic;             -- Delayed Rx Baud Clock
78
  signal RxBdEdge   : Std_Logic;             -- Rx Baud Clock Edge pulse
79
  signal RxStart    : Std_Logic;                                        -- Rx Start bit detected
80
 
81
  signal tmpDRdy    : Std_Logic;             -- Data Ready flag
82
  signal RxValid    : Std_Logic;             -- Rx Data Valid
83
  signal tmpRxVal   : Std_Logic;             -- Rx Data Valid
84
  signal outErr     : Std_Logic;             -- Over run error bit
85
  signal frameErr   : Std_Logic;             -- Framing error bit
86
  signal ParityErr  : Std_Logic;             -- Parity Error Bit
87
  signal RxParity   : Std_Logic;             -- Calculated RX parity bit
88
  signal RxState    : Std_Logic_Vector(3 downto 0);  -- receive bit state
89
  signal ShtReg     : Std_Logic_Vector(7 downto 0);  -- Shift Register
90
  signal DataOut    : Std_Logic_Vector(7 downto 0);  -- Data Output register
91
 
92
begin
93
 
94
  ---------------------------------------------------------------------
95
  -- Receiver Data Debounce
96
  -- Input level must be stable for 4 Receive Clock cycles.
97
  ---------------------------------------------------------------------
98
  rxunit_data_debounce : process(Clk, Reset, RxClkEdge, RxDat,
99
                                 RxDebDel0, RxDebDel1, RxDebDel2, RxDebDel3 )
100
  begin
101
    if Reset = '1' then
102
           RxDebDel0 <= RxDat;
103
           RxDebDel1 <= RxDat;
104
           RxDebDel2 <= RxDat;
105
           RxDebDel3 <= RxDat;
106
         elsif Clk'event and Clk = '0' then
107
           if RxClkEdge = '1' then
108
             RxDebDel0  <= RxDat;
109
             RxDebDel1  <= RxDebDel0;
110
             RxDebDel2  <= RxDebDel1;
111
             RxDebDel3  <= RxDebDel2;
112
                  if (RxDebDel3 or RxDebDel2 or RxDebDel1 or RxDebDel0) = '0' then
113
                    RxDeb <= '0';
114
        elsif (RxDebDel3 and RxDebDel2 and RxDebDel1 and RxDebDel0) = '1' then
115
                    RxDeb <= '1';
116
        else
117
                    RxDeb <= RxDeb;
118
        end if;
119
      else
120
             RxDebDel0  <= RxDebDel0;
121
             RxDebDel1  <= RxDebDel1;
122
             RxDebDel2  <= RxDebDel2;
123
             RxDebDel3  <= RxDebDel3;
124
                  RxDeb      <= RxDeb;
125
      end if;
126
         end if;
127
  end process;
128
 
129
  ---------------------------------------------------------------------
130
  -- Receiver Data Edge Detection
131
  -- A falling edge will produce a one clock cycle pulse
132
  ---------------------------------------------------------------------
133
  rxunit_data_edge : process(Clk, Reset, RxDeb, RxDatDel )
134
  begin
135
    if Reset = '1' then
136
           RxDatDel  <= RxDeb;
137
                RxDatEdge <= '0';
138
         elsif Clk'event and Clk = '0' then
139
           RxDatDel  <= RxDeb;
140
                RxDatEdge <= RxDatDel and (not RxDeb);
141
         end if;
142
  end process;
143
 
144
  ---------------------------------------------------------------------
145
  -- Receiver Clock Edge Detection
146
  -- A rising edge will produce a one clock cycle pulse
147
  -- RxClock 
148
  ---------------------------------------------------------------------
149
  rxunit_clock_edge : process(Clk, Reset, RxClk, RxClkDel )
150
  begin
151
    if Reset = '1' then
152
           RxClkDel  <= RxClk;
153
                RxClkEdge <= '0';
154
         elsif Clk'event and Clk = '0' then
155
           RxClkDel  <= RxClk;
156
                RxClkEdge <= RxClk and (not RxClkDel);
157
         end if;
158
  end process;
159
 
160
 
161
  ---------------------------------------------------------------------
162
  -- Receiver Clock Divider
163
  -- Reset the Rx Clock divider on any data edge
164
  -- Note that debounce data will be skewed by 4 clock cycles.
165
  -- Advance the count only on an input clock pulse
166
  ---------------------------------------------------------------------
167
  rxunit_clock_divide : process(Clk, Reset, RxDatEdge, RxState, RxStart,
168
                                RxClkEdge, RxClkCnt )
169
  begin
170
    if Reset = '1' then
171
           RxClkCnt  <= "000000";
172
                RxStart   <= '0';
173
         elsif Clk'event and Clk = '0' then
174
 
175
           if RxState = "1111" then     -- idle state
176
                  if RxStart = '0' then      -- in hunt mode
177
                    if RxDatEdge = '1' then -- falling edge starts counter
178
                      RxStart <= '1';
179
          else
180
                           RxStart <= RxStart;    -- other wise remain halted
181
          end if;
182
        else
183
                    RxStart <= RxStart;           -- Acquired start, stay in this state
184
        end if;
185
      else
186
                  RxStart <= '0';                   -- non idle, reset start flag
187
      end if; -- RxState
188
 
189
      if RxState = "1111" and RxStart = '0' then
190
                  RxClkCnt <= "000011";  -- Reset to 3 to account for debounce skew
191
                else
192
                  if RxClkEdge = '1' then
193
                    RxClkCnt <= RxClkCnt + "000001";
194
        else
195
                    RxClkCnt <= RxClkCnt;
196
        end if; -- RxClkEdge
197
      end if; -- RxState
198
         end if;         -- clk / reset
199
  end process;
200
 
201
  ---------------------------------------------------------------------
202
  -- Receiver Clock Selector
203
  -- Select output then look for rising edge
204
  ---------------------------------------------------------------------
205
  rxunit_clock_select : process(Clk, Reset, BdFmt, RxClk, RxClkCnt,
206
                                RxBdDel, RxBdEdge )
207
  begin
208
  -- BdFmt
209
  -- 0 0     - Baud Clk divide by 1
210
  -- 0 1     - Baud Clk divide by 16
211
  -- 1 0     - Baud Clk divide by 64
212
  -- 1 1     - reset
213
    case BdFmt is
214
         when "00" =>     -- Div by 1
215
           RxBdClk <= RxClk;
216
         when "01" =>     -- Div by 16
217
           RxBdClk <= RxClkCnt(3);
218
         when "10" =>     -- Div by 64
219
           RxBdClk <= RxClkCnt(5);
220
         when others =>  -- reset
221
           RxBdClk <= '0';
222
    end case;
223
 
224
    if Reset = '1' then
225
           RxBdDel  <= RxBdClk;
226
                RxBdEdge <= '0';
227
         elsif Clk'event and Clk = '0' then
228
           RxBdDel  <= RxBdClk;
229
                RxBdEdge <= RxBdClk and (not RxBdDel);
230
         end if;
231
 
232
  end process;
233
 
234
 
235
  ---------------------------------------------------------------------
236
  -- Receiver process
237
  ---------------------------------------------------------------------
238
  rxunit_receive : process(Clk, Reset, RxState, RxBdEdge, RxDat )
239
  begin
240
    if Reset = '1' then
241
        frameErr  <= '0';
242
        outErr    <= '0';
243
                  parityErr <= '0';
244
 
245
        ShtReg    <= "00000000";  -- Shift register
246
                  DataOut   <= "00000000";
247
                  RxParity  <= '0';         -- Parity bit
248
                  RxValid   <= '0';         -- Data RX data valid flag
249
        RxState   <= "1111";
250
    elsif Clk'event and Clk='0' then
251
        if RxBdEdge = '1' then
252
          case RxState is
253
          when "0000" | "0001" | "0010" | "0011" |
254
                                        "0100" | "0101" | "0110" => -- data bits 0 to 6
255
            ShtReg    <= RxDat & ShtReg(7 downto 1);
256
                           RxParity  <= RxParity xor RxDat;
257
                                parityErr <= parityErr;
258
                                frameErr  <= frameErr;
259
                                outErr    <= outErr;
260
                                RxValid   <= '0';
261
                                DataOut   <= DataOut;
262
                                if RxState = "0110" then
263
                             if WdFmt(2) = '0' then
264
                RxState <= "1000";          -- 7 data + parity
265
                             else
266
                RxState <= "0111";          -- 8 data bits
267
                                  end if; -- WdFmt(2)
268
                                else
269
              RxState   <= RxState + "0001";
270
                                end if; -- RxState
271
 
272
          when "0111" =>                 -- data bit 7
273
            ShtReg    <= RxDat & ShtReg(7 downto 1);
274
                           RxParity  <= RxParity xor RxDat;
275
                                parityErr <= parityErr;
276
                                frameErr  <= frameErr;
277
                                outErr    <= outErr;
278
                                RxValid   <= '0';
279
                                DataOut   <= DataOut;
280
                           if WdFmt(1) = '1' then      -- parity bit ?
281
              RxState <= "1000";         -- yes, go to parity
282
                                else
283
              RxState <= "1001";         -- no, must be 2 stop bit bits
284
                           end if;
285
 
286
               when "1000" =>                 -- parity bit
287
                           if WdFmt(2) = '0' then
288
              ShtReg <= RxDat & ShtReg(7 downto 1); -- 7 data + parity
289
                                else
290
                                  ShtReg <= ShtReg;          -- 8 data + parity
291
                                end if;
292
                                RxParity <= RxParity;
293
                                if WdFmt(0) = '0' then      -- parity polarity ?
294
                                  if RxParity = RxDat then  -- check even parity
295
                                          parityErr <= '1';
296
                                  else
297
                                          parityErr <= '0';
298
                                  end if;
299
                                else
300
                                  if RxParity = RxDat then  -- check for odd parity
301
                                          parityErr <= '0';
302
                                  else
303
                                          parityErr <= '1';
304
                                  end if;
305
                                end if;
306
                                frameErr  <= frameErr;
307
                                outErr    <= outErr;
308
                                RxValid   <= '0';
309
                                DataOut   <= DataOut;
310
            RxState   <= "1001";
311
 
312
          when "1001" =>                 -- stop bit (Only one required for RX)
313
                           ShtReg    <= ShtReg;
314
                                RxParity  <= RxParity;
315
                                parityErr <= parityErr;
316
            if RxDat = '1' then         -- stop bit expected
317
              frameErr <= '0';           -- yes, no framing error
318
            else
319
              frameErr <= '1';           -- no, framing error
320
            end if;
321
            if tmpDRdy = '1' then        -- Has previous data been read ? 
322
              outErr <= '1';             -- no, overrun error
323
            else
324
              outErr <= '0';             -- yes, no over run error
325
            end if;
326
                                RxValid   <= '1';
327
                                DataOut   <= ShtReg;
328
            RxState   <= "1111";
329
 
330
          when others =>                 -- this is the idle state
331
            ShtReg    <= ShtReg;
332
                           RxParity  <= RxParity;
333
                                parityErr <= parityErr;
334
                                frameErr  <= frameErr;
335
                                outErr    <= outErr;
336
                                RxValid   <= '0';
337
                                DataOut   <= DataOut;
338
                           if RxDat = '0' then  -- look for start request
339
              RxState  <= "0000"; -- yes, read data
340
                           else
341
                                  RxState <= "1111";    -- otherwise idle
342
                           end if;
343
          end case; -- RxState
344
                  else  -- RxBdEdge
345
            ShtReg    <= ShtReg;
346
                           RxParity  <= RxParity;
347
                                parityErr <= parityErr;
348
                                frameErr  <= frameErr;
349
                                outErr    <= outErr;
350
                                RxValid   <= RxValid;
351
                                DataOut   <= DataOut;
352
                                RxState   <= RxState;
353
        end if; -- RxBdEdge
354
    end if; -- clk / reset
355
  end process;
356
 
357
 
358
  ---------------------------------------------------------------------
359
  -- Receiver Read process
360
  ---------------------------------------------------------------------
361
  rxunit_read : process(Clk, Reset, ReadD, RxValid, tmpRxVal, tmpDRdy )
362
  begin
363
    if Reset = '1' then
364
        tmpDRdy   <= '0';
365
                  tmpRxVal  <= '0';
366
    elsif Clk'event and Clk='0' then
367
        if ReadD = '1' then
368
                    -- Data was read, reset data ready
369
          tmpDRdy  <= '0';
370
                         tmpRxVal <= tmpRxVal;
371
                  else
372
                    if RxValid = '1' and tmpRxVal = '0' then
373
                           -- Data was received, set Data ready
374
                           tmpDRdy  <= '1';
375
                                tmpRxVal <= '1';
376
                         else
377
                           -- Test for falling edge of RxValid.
378
                      tmpDRdy <= tmpDRdy;
379
                           if RxValid = '0' and tmpRxVal = '1' then
380
                             tmpRxVal  <= '0';
381
                           else
382
                             tmpRxVal  <= tmpRxVal;
383
                                end if;
384
                         end if; -- RxValid
385
        end if; -- ReadD
386
    end if; -- clk / reset
387
  end process;
388
 
389
 
390
  DARdy <= tmpDRdy;
391
  DAOut <= DataOut;
392
  FRErr <= frameErr;
393
  ORErr <= outErr;
394
  PAErr <= parityErr;
395
 
396
end Behaviour; --==================== End of architecture ====================--

powered by: WebSVN 2.1.0

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