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 2

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
                    if (v.parity xor v_inbit) = '0' then
137
                        -- Parity check failed.
138
                        v.errpar    := '1';
139
                    else
140
                        if v.control = '1' then
141
                            -- received control code
142
                            case v.bitshift(7 downto 6) is
143
                                when "00" => -- FCT or NULL
144
                                    v.gotfct    := not r.escaped;
145
                                    v.escaped   := '0';
146
                                when "10" => -- EOP
147
                                    if r.escaped = '1' then
148
                                        v.erresc    := '1';
149
                                    end if;
150
                                    v.escaped   := '0';
151
                                    v.rxchar    := not r.escaped;
152
                                    v.rxflag    := '1';
153
                                    v.datareg   := "00000000";
154
                                when "01" => -- EEP
155
                                    if r.escaped = '1' then
156
                                        v.erresc    := '1';
157
                                    end if;
158
                                    v.escaped   := '0';
159
                                    v.rxchar    := not r.escaped;
160
                                    v.rxflag    := '1';
161
                                    v.datareg   := "00000001";
162
                                when others => -- ESC
163
                                    if r.escaped = '1' then
164
                                        v.erresc    := '1';
165
                                    end if;
166
                                    v.escaped   := '1';
167
                            end case;
168
                        else
169
                            -- received 8-bit character
170
                            if r.escaped = '1' then
171
                                -- received Time-Code
172
                                v.tick_out  := '1';
173
                                v.timereg   := v.bitshift(7 downto 0);
174
                            else
175
                                -- received data character
176
                                v.rxflag    := '0';
177
                                v.rxchar    := '1';
178
                                v.datareg   := v.bitshift(7 downto 0);
179
                            end if;
180
                            v.escaped   := '0';
181
                        end if;
182
                    end if;
183
                    -- prepare for next code
184
                    v.parity    := '0';
185
                    v.control   := v_inbit;
186
                    if v_inbit = '1' then
187
                        -- next word will be control code.
188
                        v.bitcnt    := (3 => '1', others => '0');
189
                    else
190
                        -- next word will be a data byte.
191
                        v.bitcnt    := (9 => '1', others => '0');
192
                    end if;
193
                else
194
                    -- wait until next code is completely received;
195
                    -- accumulate parity
196
                    v.bitcnt    := '0' & v.bitcnt(9 downto 1);
197
                    v.parity    := v.parity xor v_inbit;
198
                end if;
199
 
200
                -- detect first NULL
201
                if v.null_seen = '0' then
202
                    if v.bitshift = "000101110" then
203
                        -- got first NULL pattern
204
                        v.null_seen := '1';
205
                        v.control   := v_inbit; -- should always be '1'
206
                        v.parity    := '0';
207
                        v.bitcnt    := (3 => '1', others => '0');
208
                    end if;
209
                end if;
210
 
211
                -- shift new bit into register.
212
                v.bitshift  := v_inbit & v.bitshift(v.bitshift'high downto 1);
213
 
214
            end loop;
215
        end if;
216
 
217
        -- synchronous reset
218
        if rxen = '0' then
219
            v.bit_seen  := '0';
220
            v.null_seen := '0';
221
            v.bitshift  := "111111111";
222
            v.bitcnt    := (others => '0');
223
            v.gotfct    := '0';
224
            v.tick_out  := '0';
225
            v.rxchar    := '0';
226
            v.rxflag    := '0';
227
            v.escaped   := '0';
228
            v.timereg   := "00000000";
229
            v.datareg   := "00000000";
230
            v.disccnt   := to_unsigned(0, v.disccnt'length);
231
            v.errpar    := '0';
232
            v.erresc    := '0';
233
        end if;
234
 
235
        -- drive outputs
236
        recvo.gotbit    <= r.bit_seen;
237
        recvo.gotnull   <= r.null_seen;
238
        recvo.gotfct    <= r.gotfct;
239
        recvo.tick_out  <= r.tick_out;
240
        recvo.ctrl_out  <= r.timereg(7 downto 6);
241
        recvo.time_out  <= r.timereg(5 downto 0);
242
        recvo.rxchar    <= r.rxchar;
243
        recvo.rxflag    <= r.rxflag;
244
        recvo.rxdata    <= r.datareg;
245
        if r.bit_seen = '1' and r.disccnt = 0 then
246
            recvo.errdisc   <= '1';
247
        else
248
            recvo.errdisc   <= '0';
249
        end if;
250
        recvo.errpar    <= r.errpar;
251
        recvo.erresc    <= r.erresc;
252
 
253
        -- update registers
254
        rin         <= v;
255
 
256
    end process;
257
 
258
    -- update registers on rising edge of system clock
259
    process (clk) is
260
    begin
261
        if rising_edge(clk) then
262
            r <= rin;
263
        end if;
264
    end process;
265
 
266
end architecture spwrecv_arch;

powered by: WebSVN 2.1.0

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