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

Subversion Repositories manchesteruart

[/] [manchesteruart/] [trunk/] [rtl/] [vhdl/] [decode.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 skeptonomi
--*************************************************************************
2
--*                                                                       *
3
--* Copyright (C) 2014 William B Hunter - LGPL                            *
4
--*                                                                       *
5
--* This source file may be used and distributed without                  *
6
--* restriction provided that this copyright statement is not             *
7
--* removed from the file and that any derivative work contains           *
8
--* the original copyright notice and the associated disclaimer.          *
9
--*                                                                       *
10
--* This source file is free software; you can redistribute it            *
11
--* and/or modify it under the terms of the GNU Lesser General            *
12
--* Public License as published by the Free Software Foundation;          *
13
--* either version 2.1 of the License, or (at your option) any            *
14
--* later version.                                                        *
15
--*                                                                       *
16
--* This source is distributed in the hope that it will be                *
17
--* useful, but WITHout ANY WARRANTY; without even the implied            *
18
--* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR               *
19
--* PURPOSE.  See the GNU Lesser General Public License for more          *
20
--* details.                                                              *
21
--*                                                                       *
22
--* You should have received a copy of the GNU Lesser General             *
23
--* Public License along with this source; if not, download it            *
24
--* from http://www.opencores.org/lgpl.shtml                              *
25
--*                                                                       *
26
--*************************************************************************
27
--
28
-- Engineer: William B Hunter
29
-- Create Date: 08/08/2014
30
-- Project: Manchester Uart
31
-- File: decode.vhd
32
-- Description: This decoder recieves short bursts of 16 bit data words encoded with as manchester data.
33
--   Because this is not a stream decoder, it has no sync pattern or packet alignment typical of manchester decoders.
34
--   It therefore uses start and stop bits much like a UART. Both the start and stop bits are always ones. The idle 
35
--   state is always high, and the ones are a low to high transition in the middle of the bit period, and a zero is a 
36
--   high to low transition in the middle of the bit period. A high for 3 bit periods is a reset/resync.
37
----------------------------------------------------------------------------------
38
 
39
 
40
library IEEE;
41
use IEEE.STD_LOGIC_1164.ALL;
42
use IEEE.NUMERIC_STD.ALL;
43
 
44
entity decode is
45
  Port(
46
    clk16x : in STD_LOGIC;
47
    srst : in STD_LOGIC;
48
    rxd : in STD_LOGIC;
49
    rx_data : out STD_LOGIC_VECTOR (15 downto 0);
50
    rx_stb : out STD_LOGIC;
51
    fm_err : out STD_LOGIC;
52
    rx_idle : out STD_LOGIC
53
  );
54
end decode;
55
 
56
architecture rtl of decode is
57
  signal shifter : std_logic_vector(15 downto 0);
58
  signal tick_cnt : integer range 0 to 31 := 0;
59
  signal bit_cnt : integer range 0 to 15 := 0;
60
  signal rcv_stb : std_logic := '0';
61
  signal debounce : std_logic_vector(3 downto 0) := (others=>'1');
62
  signal filt : std_logic := '1';
63
  signal filt_old : std_logic := '1';
64
  signal fall_det : std_logic := '0';
65
  signal rst_det : std_logic := '0';
66
  signal rst_cnt :integer range 0 to 15 := 0;
67
  signal rise_det : std_logic := '0';
68
 
69
 
70
  type rcv_state_type is (SM_SEEK, SM_START, SM_RCV, SM_END, SM_ERR);
71
  signal rcv_state : rcv_state_type := SM_SEEK;
72
 
73
begin
74
  --this process debounces the input signal to remove noise. It also detects rising 
75
  --  and falling edges and reset conditions.
76
  p_debounce: process(clk16x)
77
  begin
78
    if rising_edge(clk16x) then
79
      if srst = '1' then
80
        debounce <= "1111";
81
        rise_det <= '0';
82
        fall_det <= '0';
83
        rst_cnt <= 0;
84
        rst_det <= '0';
85
        filt_old <= '1';
86
      else
87
        if filt_old = '0' and filt = '1' then
88
          rise_det <= '1';
89
          fall_det <= '0';
90
        elsif filt_old = '1' and filt = '0' then
91
          rise_det <= '0';
92
          fall_det <= '1';
93
        else
94
          rise_det <= '0';
95
          fall_det <= '0';
96
        end if;
97
        if filt = '0' then
98
          rst_cnt <= 0;
99
          rst_det <= '0';
100
        elsif rst_cnt = 47 then
101
          rst_det <= '1';
102
        else
103
          rst_det <= '0';
104
          rst_cnt <= rst_cnt +1;
105
        end if;
106
        debounce <= debounce(2 downto 0) & rxd;
107
        filt_old <= filt;
108
      end if;
109
    end if;
110
  end process;
111
 
112
  --this is the actual debounce logic. It is a basic 2 out of three majority vote
113
  with debounce(3 downto 1) select filt <=
114
    '1' when "111",
115
    '1' when "110",
116
    '1' when "101",
117
    '1' when "011",
118
    '0' when others;
119
 
120
 
121
  --This process is the main reciever. It detects the start bit, 16 data bits and the stop bit.
122
  --  it does this by having a window for which it looks for the midbit transistions. When a transition is found,
123
  --  it syncs on the new transition so that it can look for the next. This allows the wide variation in clock rates
124
  --  between the transmitter and reciever.
125
  p_reciever: process(clk16x)
126
  begin
127
    if rising_edge(clk16x) then
128
      if srst = '1' then
129
         rcv_state <= SM_SEEK;
130
         rcv_stb <= '0';
131
         tick_cnt <= 0;
132
         bit_cnt <= 0;
133
      else
134
        case rcv_state is
135
          --The idle state is high, so look for the leading edge of the start bit which is a falling edge
136
          when SM_SEEK =>
137
            rcv_stb <= '0';
138
            tick_cnt <= 0;
139
            bit_cnt <= 0;
140
            if fall_det = '1' then
141
              rcv_state <= SM_START;
142
            end if;
143
          --After the falling edge, there should be the mid bit rising edge of the start bit, Make sure 
144
          -- this appears in the right window
145
          when SM_START =>
146
              --skip the first 4 clock periods
147
              if tick_cnt < 4 then
148
                tick_cnt <= tick_cnt + 1;
149
              --The active window is ticks 4 to 10, look for the rising edge in this window
150
              elsif tick_cnt < 11 then
151
                --a rising edge in the window allows us to start recieveing data
152
                if rise_det = '1' then
153
                  tick_cnt <= 0;
154
                  rcv_state <= SM_RCV;
155
                --two falling edges in a row is an error
156
                elsif fall_det = '1' then
157
                  rcv_state <= SM_ERR;
158
                  tick_cnt <= 0;
159
                  bit_cnt <= 0;
160
                else
161
                  tick_cnt <= tick_cnt + 1;
162
                end if;
163
              --if there was no rising edge in the window, than error out
164
              else
165
                rcv_state <= SM_ERR;
166
                tick_cnt <= 0;
167
                bit_cnt <= 0;
168
              end if;
169
          when SM_RCV =>
170
            --During recieve, we only look for the mid bit transisions in the window of
171
            --  12 to 18 ticks from the previous mid bit transition
172
            if tick_cnt < 12 then
173
              tick_cnt <= tick_cnt + 1;
174
            elsif tick_cnt < 19 then
175
              if rise_det = '1' or fall_det = '1' then
176
                tick_cnt <= 0;
177
                shifter <= shifter(14 downto 0) & rise_det;
178
                if bit_cnt = 15 then
179
                  rcv_state <= SM_END;
180
                  tick_cnt <= 0;
181
                else
182
                  bit_cnt <= bit_cnt + 1;
183
                end if;
184
              else
185
                tick_cnt <= tick_cnt + 1;
186
              end if;
187
            else
188
              rcv_state <= SM_ERR;
189
              tick_cnt <= 0;
190
              bit_cnt <= 0;
191
            end if;
192
          when SM_END =>
193
            --after all 16 data bits, we should see a stop bit which is always 1 (rising edge)
194
            if tick_cnt < 12 then
195
              tick_cnt <= tick_cnt + 1;
196
            elsif tick_cnt < 19 then
197
              if rise_det = '1' then
198
                tick_cnt <= 0;
199
                bit_cnt <= 0;
200
                rcv_stb <= '1';
201
                rcv_state <= SM_SEEK;
202
              elsif fall_det  = '1' then
203
                rcv_state <= SM_ERR;
204
                tick_cnt <= 0;
205
                bit_cnt <= 0;
206
              else
207
                 tick_cnt <= tick_cnt + 1;
208
              end if;
209
            else
210
              rcv_state <= SM_ERR;
211
              tick_cnt <= 0;
212
              bit_cnt <= 0;
213
            end if;
214
          --this state handles the error conditions. The error persists until a reset condition
215
          --It is up to external logic to latch errors if nessesary
216
          when SM_ERR =>
217
            rcv_stb <= '0';
218
            tick_cnt <= 4;
219
            bit_cnt <= 0;
220
            if rst_det = '1' then
221
              rcv_state <= SM_SEEK;
222
            end if;
223
          --we should never get here
224
          when others =>
225
            rcv_stb <= '0';
226
            tick_cnt <= 4;
227
            bit_cnt <= 0;
228
            rcv_state <= SM_SEEK;
229
        end case;
230
      end if; --srst
231
    end if;  --clk16x
232
  end process;
233
 
234
  rx_idle <= '1' when rcv_state = SM_SEEK else '0';
235
  fm_err <= '1' when rcv_state = SM_ERR else '0';
236
  rx_data <= shifter;
237
  rx_stb <= rcv_stb;
238
 
239
end rtl;

powered by: WebSVN 2.1.0

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