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

Subversion Repositories spacewire_light

[/] [spacewire_light/] [trunk/] [rtl/] [vhdl/] [spwrecv.vhd] - Blame information for rev 12

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

Line No. Rev Author Line
1 2 jorisvr
--
2
--  SpaceWire Receiver
3
--
4
--  This entity decodes the sequence of incoming data bits into tokens.
5
--  Data bits are passed to this entity from the Receiver Front-end
6
--  in groups of rxchunk bits at a time.
7
--
8
--  The bitrate of the incoming SpaceWire signal must be strictly less
9
--  than rxchunk times the system clock frequency. 
10
--
11
 
12
library ieee;
13
use ieee.std_logic_1164.all, ieee.numeric_std.all;
14
use work.spwpkg.all;
15
 
16
entity spwrecv is
17
 
18
    generic (
19
        -- Disconnect timeout, expressed in system clock cycles.
20
        -- Should be 850 ns (727 ns .. 1000 ns) according to the standard.
21
        disconnect_time: integer range 1 to 255;
22
 
23
        -- Nr of bits sampled per system clock.
24
        rxchunk:        integer range 1 to 4
25
    );
26
 
27
    port (
28
        -- System clock.
29
        clk:        in  std_logic;
30
 
31
        -- High to enable receiver; low to disable and reset receiver.
32
        rxen:       in  std_logic;
33
 
34
        -- Output signals to spwlink.
35
        recvo:      out spw_recv_out_type;
36
 
37
        -- High if there has been recent activity on the input lines.
38
        inact:      in  std_logic;
39
 
40
        -- High if inbits contains a valid group of received bits.
41
        inbvalid:   in  std_logic;
42
 
43
        -- Received bits from receiver front-end.
44
        inbits:     in  std_logic_vector(rxchunk-1 downto 0)
45
    );
46
 
47
end entity spwrecv;
48
 
49
architecture spwrecv_arch of spwrecv is
50
 
51
    -- registers
52
    type regs_type is record
53
        -- receiver state
54
        bit_seen:   std_ulogic;         -- got a bit transition
55
        null_seen:  std_ulogic;         -- got a NULL token
56
        -- input shift register
57
        bitshift:   std_logic_vector(8 downto 0);
58
        bitcnt:     std_logic_vector(9 downto 0);   -- one-hot counter
59
        -- parity flag
60
        parity:     std_ulogic;
61
        -- decoding
62
        control:    std_ulogic;         -- next code is control code
63
        escaped:    std_ulogic;         -- last code was ESC
64
        -- output registers
65
        gotfct:     std_ulogic;
66
        tick_out:   std_ulogic;
67
        rxchar:     std_ulogic;
68
        rxflag:     std_ulogic;
69
        timereg:    std_logic_vector(7 downto 0);
70
        datareg:    std_logic_vector(7 downto 0);
71
        -- disconnect timer
72
        disccnt:    unsigned(7 downto 0);
73
        -- error flags
74
        errpar:     std_ulogic;
75
        erresc:     std_ulogic;
76
    end record;
77
 
78
    -- Initial state
79
    constant regs_reset: regs_type := (
80
        bit_seen    => '0',
81
        null_seen   => '0',
82
        bitshift    => (others => '1'),
83
        bitcnt      => (others => '0'),
84
        parity      => '0',
85
        control     => '0',
86
        escaped     => '0',
87
        gotfct      => '0',
88
        tick_out    => '0',
89
        rxchar      => '0',
90
        rxflag      => '0',
91
        timereg     => (others => '0'),
92
        datareg     => (others => '0'),
93
        disccnt     => "00000000",
94
        errpar      => '0',
95
        erresc      => '0' );
96
 
97
    -- registers
98
    signal r:       regs_type := regs_reset;
99
    signal rin:     regs_type;
100
 
101
begin
102
 
103
    -- combinatorial process
104
    process  (r, rxen, inact, inbvalid, inbits)
105
        variable v:         regs_type;
106
        variable v_inbit:   std_ulogic;
107
    begin
108
        v           := r;
109
        v_inbit     := '0';
110
 
111
        -- disconnect timer
112
        if inact = '1' then
113
            -- activity on input; reset timer
114
            v.disccnt   := to_unsigned(disconnect_time, v.disccnt'length);
115
        elsif r.disccnt /= 0 then
116
            -- count down
117
            v.disccnt   := r.disccnt - 1;
118
        end if;
119
 
120
        -- assume no new token
121
        v.gotfct    := '0';
122
        v.tick_out  := '0';
123
        v.rxchar    := '0';
124
 
125
        if inbvalid = '1' then
126
 
127
            -- process incoming bits
128
            for i in 0 to rxchunk-1 loop
129
                v_inbit     := inbits(i);
130
 
131
                -- got a bit transition
132
                v.bit_seen  := '1';
133
 
134
                if v.bitcnt(0) = '1' then
135
                    -- received new token
136 4 jorisvr
                    -- note that this will not happen before null_seen='1'
137 2 jorisvr
                    if (v.parity xor v_inbit) = '0' then
138
                        -- Parity check failed.
139
                        v.errpar    := '1';
140
                    else
141
                        if v.control = '1' then
142
                            -- received control code
143
                            case v.bitshift(7 downto 6) is
144
                                when "00" => -- FCT or NULL
145
                                    v.gotfct    := not r.escaped;
146
                                    v.escaped   := '0';
147
                                when "10" => -- EOP
148
                                    if r.escaped = '1' then
149
                                        v.erresc    := '1';
150
                                    end if;
151
                                    v.escaped   := '0';
152
                                    v.rxchar    := not r.escaped;
153
                                    v.rxflag    := '1';
154
                                    v.datareg   := "00000000";
155
                                when "01" => -- EEP
156
                                    if r.escaped = '1' then
157
                                        v.erresc    := '1';
158
                                    end if;
159
                                    v.escaped   := '0';
160
                                    v.rxchar    := not r.escaped;
161
                                    v.rxflag    := '1';
162
                                    v.datareg   := "00000001";
163
                                when others => -- ESC
164
                                    if r.escaped = '1' then
165
                                        v.erresc    := '1';
166
                                    end if;
167
                                    v.escaped   := '1';
168
                            end case;
169
                        else
170
                            -- received 8-bit character
171
                            if r.escaped = '1' then
172
                                -- received Time-Code
173
                                v.tick_out  := '1';
174
                                v.timereg   := v.bitshift(7 downto 0);
175
                            else
176
                                -- received data character
177
                                v.rxflag    := '0';
178
                                v.rxchar    := '1';
179
                                v.datareg   := v.bitshift(7 downto 0);
180
                            end if;
181
                            v.escaped   := '0';
182
                        end if;
183
                    end if;
184
                    -- prepare for next code
185
                    v.parity    := '0';
186
                    v.control   := v_inbit;
187
                    if v_inbit = '1' then
188
                        -- next word will be control code.
189
                        v.bitcnt    := (3 => '1', others => '0');
190
                    else
191
                        -- next word will be a data byte.
192
                        v.bitcnt    := (9 => '1', others => '0');
193
                    end if;
194
                else
195
                    -- wait until next code is completely received;
196
                    -- accumulate parity
197
                    v.bitcnt    := '0' & v.bitcnt(9 downto 1);
198
                    v.parity    := v.parity xor v_inbit;
199
                end if;
200
 
201
                -- detect first NULL
202
                if v.null_seen = '0' then
203
                    if v.bitshift = "000101110" then
204
                        -- got first NULL pattern
205
                        v.null_seen := '1';
206
                        v.control   := v_inbit; -- should always be '1'
207
                        v.parity    := '0';
208
                        v.bitcnt    := (3 => '1', others => '0');
209
                    end if;
210
                end if;
211
 
212
                -- shift new bit into register.
213
                v.bitshift  := v_inbit & v.bitshift(v.bitshift'high downto 1);
214
 
215
            end loop;
216
        end if;
217
 
218
        -- synchronous reset
219
        if rxen = '0' then
220
            v.bit_seen  := '0';
221
            v.null_seen := '0';
222
            v.bitshift  := "111111111";
223
            v.bitcnt    := (others => '0');
224
            v.gotfct    := '0';
225
            v.tick_out  := '0';
226
            v.rxchar    := '0';
227
            v.rxflag    := '0';
228
            v.escaped   := '0';
229
            v.timereg   := "00000000";
230
            v.datareg   := "00000000";
231
            v.disccnt   := to_unsigned(0, v.disccnt'length);
232
            v.errpar    := '0';
233
            v.erresc    := '0';
234
        end if;
235
 
236
        -- drive outputs
237
        recvo.gotbit    <= r.bit_seen;
238
        recvo.gotnull   <= r.null_seen;
239
        recvo.gotfct    <= r.gotfct;
240
        recvo.tick_out  <= r.tick_out;
241
        recvo.ctrl_out  <= r.timereg(7 downto 6);
242
        recvo.time_out  <= r.timereg(5 downto 0);
243
        recvo.rxchar    <= r.rxchar;
244
        recvo.rxflag    <= r.rxflag;
245
        recvo.rxdata    <= r.datareg;
246
        if r.bit_seen = '1' and r.disccnt = 0 then
247
            recvo.errdisc   <= '1';
248
        else
249
            recvo.errdisc   <= '0';
250
        end if;
251
        recvo.errpar    <= r.errpar;
252
        recvo.erresc    <= r.erresc;
253
 
254
        -- update registers
255
        rin         <= v;
256
 
257
    end process;
258
 
259
    -- update registers on rising edge of system clock
260
    process (clk) is
261
    begin
262
        if rising_edge(clk) then
263
            r <= rin;
264
        end if;
265
    end process;
266
 
267
end architecture spwrecv_arch;

powered by: WebSVN 2.1.0

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