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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.74/] [rtl/] [vlib/] [rlink/] [rlink_core.vhd] - Blame information for rev 38

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 37 wfjm
-- $Id: rlink_core.vhd 799 2016-08-21 09:20:19Z mueller $
2 2 wfjm
--
3 36 wfjm
-- Copyright 2007-2016 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4 2 wfjm
--
5
-- This program is free software; you may redistribute and/or modify it under
6
-- the terms of the GNU General Public License as published by the Free
7
-- Software Foundation, either version 2, or at your option any later version.
8
--
9
-- This program is distributed in the hope that it will be useful, but
10
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
11
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
-- for complete details.
13
-- 
14
------------------------------------------------------------------------------
15 9 wfjm
-- Module Name:    rlink_core - syn
16 27 wfjm
-- Description:    rlink core with 9bit interface (with rlmon+rbmon)
17 2 wfjm
--
18 27 wfjm
-- Dependencies:   memlib/ram_2swsr_rfirst_gen
19
--                 memlib/fifo_1c_dram
20
--                 comlib/crc16
21
--                 rb_sel
22
--                 rb_sres_or_2
23
--                 rlink_mon_sb    [sim only]
24
--                 rbus/rb_mon_sb  [sim only]
25 2 wfjm
--
26 9 wfjm
-- Test bench:     tb/tb_rlink_direct
27
--                 tb/tb_rlink_serport
28
--                 tb/tb_rlink_tba_ttcombo
29 2 wfjm
--
30
-- Target Devices: generic
31 37 wfjm
-- Tool versions:  ise 8.2-14.7; viv 2014.4-2016.2; ghdl 0.18-0.33
32 2 wfjm
--
33
-- Synthesized (xst):
34
-- Date         Rev  ise         Target      flop lutl lutm slic t peri
35 34 wfjm
-- 2015-12-26   718 14.7  131013 xc6slx16-2   312  460   16  150 s  7.0 ver 4.1
36 27 wfjm
-- 2014-12-20   614 14.7  131013 xc6slx16-2   310  453   16  146 s  6.8 ver 4.0
37
-- 2014-08-13   581 14.7  131013 xc6slx16-2   160  230    0   73 s  6.0 ver 3.0
38
-- 2014-08-13   581 14.7  131013 xc3s1000-4   160  358    0  221 s  8.9 ver 3.0
39 2 wfjm
--
40
-- Revision History: 
41
-- Date         Rev Version  Comment
42 37 wfjm
-- 2016-08-18   799   4.1.3  remove 'assert false' from report statements
43
-- 2016-05-22   767   4.1.2  don't init N_REGS (vivado fix for fsm inference)
44 34 wfjm
-- 2015-12-26   718   4.1.1  add proc_sres: strip 'x' from RB_SRES.dout
45 28 wfjm
-- 2014-12-21   617   4.1    use stat(_rbf_rbtout) to signal rbus timeout
46 27 wfjm
-- 2014-12-20   614   4.0    largely rewritten; 2 FSMs; v3 protocol; 4 bit STAT
47
-- 2014-08-15   583   3.5    rb_mreq addr now 16 bit; add s_rxaddrl state
48 13 wfjm
-- 2011-11-19   427   3.1.3  now numeric_std clean
49 9 wfjm
-- 2010-12-25   348   3.1.2  drop RL_FLUSH support, add RL_MONI for rlink_core;
50
-- 2010-12-24   347   3.1.1  rename: CP_*->RL->*
51
-- 2010-12-22   346   3.1    wblk dcrc error: send nak, transit to s_error now;
52
--                           rename stat flags: [cd]crc->[cd]err, ioto->rbnak,
53
--                           ioerr->rberr; '111' cmd now aborts via s_txnak and
54
--                           sets cerr flag; set [cd]err on eop/nak aborts;
55
-- 2010-12-04   343   3.0    renamed rri_ -> rlink_; rbus V3 interface: use now
56
--                           aval,re,we; add new states: s_rstart, s_wstart
57 2 wfjm
-- 2010-06-20   308   2.6    use rbinit,rbreq,rbwe state flops to drive rb_mreq;
58
--                           now nak on reserved cmd 111; use do_comma_abort();
59
-- 2010-06-18   306   2.5.1  rename rbus data fields to _rbf_
60
-- 2010-06-06   302   2.5    use sop/eop framing instead of soc+chaining
61
-- 2010-06-03   299   2.1.2  drop unneeded unsigned casts; change init encoding
62
-- 2010-05-02   287   2.1.1  ren CE_XSEC->CE_INT,RP_STAT->RB_STAT,AP_LAM->RB_LAM
63
--                           drop RP_IINT signal from interfaces
64
-- 2010-04-03   274   2.1    add CP_FLUSH output
65
-- 2009-07-12   233   2.0.1  remove snoopers
66
-- 2008-08-24   162   2.0    with new rb_mreq/rb_sres interface
67
-- 2008-03-02   121   1.1.1  comment out snoopers
68
-- 2007-11-24    98   1.1    new internal init handling (addr=11111111)
69
-- 2007-10-12    88   1.0.1  avoid ieee.std_logic_unsigned, use cast to unsigned
70
-- 2007-09-15    82   1.0    Initial version, fully functional
71
-- 2007-06-17    58   0.5    First preliminary version
72
------------------------------------------------------------------------------
73
--  7 supported commands:
74 27 wfjm
--    nak aborts to _txnak are indicated as [nak:<nakcode>]
75
--    commands to rbus engine are indicated as [bcmd:<bfunc>]
76 2 wfjm
--
77
--   000 read reg (rreg):
78 27 wfjm
--        rx: cmd al ah ccrcl ccrch
79
--        tx: cmd dl dh stat crcl crch
80
--       seq: _rxcmd _rxaddrl _rxaddrh
81
--            _rxccrcl[nak:ccrc] _rxccrch[nak:ccrc] _txcmd
82
--            _rstart[bcmd:rblk] {_txdat}*
83
--            _txstat _txcrcl[nak:rtovfl] -> _txcrch -> _rxcmd
84 2 wfjm
--
85
--   001 read blk (rblk):
86 27 wfjm
--        rx: cmd al ah cl ch ccrcl ccrch
87
--        tx: cmd cnt dl dh ... dcl dch stat crcl crch
88
--       seq: _rxcmd _rxaddrl _rxaddrh _rxcntl _rxcnth
89
--            _rxccrcl[nak:ccrc] _rxccrch[nak:ccrc] _txcmd
90
--            _txcntl _txcnth _rstart[bcmd:rblk] {_txdat}* _txdcntl _txdcnth
91
--            _txstat _txcrcl[nak:rtovfl] -> _txcrch -> _rxcmd
92 2 wfjm
--
93
--   010 write reg (wreg):
94 27 wfjm
--        rx: cmd al ah dl dh ccrcl ccrch
95
--        tx: cmd stat crcl crch
96
--       seq: _rxcmd _rxaddrl _rxaddrh _rxdatl _rxdath
97
--            _rxccrcl[nak:ccrc] _rxccrch[nak:ccrc] _txcmd
98
--            _txcmd[bcmd:wblk] _wwait0
99
--            _txstat _txcrcl[nak:rtovfl] -> _txcrch -> _rxcmd
100 2 wfjm
--
101
--   011 write blk (wblk):
102 27 wfjm
--        rx: cmd al ah cnt ccrcl ccrch dl dh ... dcrcl dcrch
103
--        tx: cmd dcl dch stat crcl crch
104
--       seq: _rxcmd _rxaddrl _rxaddrh _rxcntl _rxcnth
105
--            _rxccrcl[nak:ccrc] _rxccrch[nak:ccrc] _txcmd
106
--            _wblk {_rxwblk}* _rxdcrc[nak:dcrc,rtwblk]
107
--            _wblk0 _wblk1 _wblk2[bcmd:wblk] {_wblkl _wblkh}*
108
--            _wwait0 _wwait1 _txdcntl _txdcnth
109
--            _txstat _txcrcl[nak:rtovfl] -> _txcrch -> _rxcmd
110 2 wfjm
--
111 27 wfjm
--   100 list abort (labo):
112
--        rx: cmd ccrcl ccrch
113
--        tx: cmd babo stat crcl crch
114
--       seq: _rxcmd 
115
--            _rxccrcl[nak:ccrc] _rxccrch[nak:ccrc] _txcmd
116
--            _txlabo
117
--            _txstat_txcrcl[nak:rtovfl] -> _txcrch -> [_rxcmd|_rxeop]
118 2 wfjm
--
119
--   101 read attn (attn):
120 27 wfjm
--        rx: cmd ccrcl ccrch
121
--        tx: cmd dl dh stat crcl crch
122
--       seq: _rxcmd
123
--            _rxccrcl[nak:ccrc] _rxccrch[nak:ccrc] _txcmd
124
--            _attn _txcntl _txcnth
125
--            _txstat _txcrcl[nak:rtovfl] -> _txcrch -> _rxcmd
126 2 wfjm
--
127
--   110 write init (init):
128 27 wfjm
--        rx: cmd al ah dl dh ccrcl ccrch
129
--        tx: cmd stat crcl crch
130
--       seq: _rxcmd _rxaddrl _rxaddrh _rxdatl _rxdath
131
--            _rxccrcl[nak:ccrc] _rxccrch[nak:ccrc] _txcmd[bcmd:init]
132
--            _txstat _txcrc[nak:rtovfl] -> _rxcmd
133 2 wfjm
--
134
--   111 is currently not a legal command and causes a nak
135
--       seq: _txnak
136
--
137
-- The different rbus cycle types are encoded as:
138
--
139 9 wfjm
--        init aval re we
140
--          0    0   0  0   idle
141 27 wfjm
--          0    1   1  0   read 
142
--          0    1   0  1   write
143
--          1    0   0  0   init
144 9 wfjm
--          0    0   1  0   not allowed
145
--          0    0   0  1   not allowed
146 27 wfjm
--          1    0   0  1   not allowed
147 9 wfjm
--          1    0   1  0   not allowed
148
--          *    *   1  1   not allowed
149
--          1    1   *  *   not allowed
150 2 wfjm
--
151
 
152
library ieee;
153
use ieee.std_logic_1164.all;
154 13 wfjm
use ieee.numeric_std.all;
155 2 wfjm
 
156
use work.slvtypes.all;
157 27 wfjm
use work.memlib.all;
158 2 wfjm
use work.comlib.all;
159 9 wfjm
use work.rblib.all;
160
use work.rlinklib.all;
161 2 wfjm
 
162 9 wfjm
entity rlink_core is                    -- rlink core with 9bit interface
163 2 wfjm
  generic (
164 27 wfjm
    BTOWIDTH : positive :=  5;          -- rbus timeout counter width
165
    RTAWIDTH : positive :=  12;         -- retransmit buffer address width
166
    SYSID : slv32 := (others=>'0');     -- rlink system id
167
    ENAPIN_RLMON : integer := -1;       -- SB_CNTL for rlmon  (-1=none)
168
    ENAPIN_RBMON : integer := -1);      -- SB_CNTL for rbmon  (-1=none)
169 2 wfjm
  port (
170
    CLK  : in slbit;                    -- clock      
171 27 wfjm
    CE_INT : in slbit := '0';           -- rri ato time unit clock enable
172 2 wfjm
    RESET  : in slbit;                  -- reset
173 9 wfjm
    RL_DI : in slv9;                    -- rlink 9b: data in
174
    RL_ENA : in slbit;                  -- rlink 9b: data enable
175
    RL_BUSY : out slbit;                -- rlink 9b: data busy
176
    RL_DO : out slv9;                   -- rlink 9b: data out
177
    RL_VAL : out slbit;                 -- rlink 9b: data valid
178
    RL_HOLD : in slbit;                 -- rlink 9b: data hold
179
    RL_MONI : out rl_moni_type;         -- rlink: monitor port
180 2 wfjm
    RB_MREQ : out rb_mreq_type;         -- rbus: request
181
    RB_SRES : in rb_sres_type;          -- rbus: response
182
    RB_LAM : in slv16;                  -- rbus: look at me
183 27 wfjm
    RB_STAT : in slv4                   -- rbus: status flags
184 2 wfjm
  );
185 27 wfjm
 
186
  attribute fsm_encoding : string;
187
  attribute fsm_encoding of rlink_core : entity is "one-hot";
188
 
189 9 wfjm
end entity rlink_core;
190 2 wfjm
 
191 9 wfjm
architecture syn of rlink_core is
192 28 wfjm
   -- core config registers (top 4 in rbus space)
193
  constant rbaddr : slv16 := x"fffc";    -- fffc/4: 1111 1111 1111 11xx
194 27 wfjm
  constant rbaddr_cntl : slv2 := "11";   -- cntl address offset
195
  constant rbaddr_stat : slv2 := "10";   -- stat address offset
196
  constant rbaddr_id1  : slv2 := "01";   -- id1  address offset
197
  constant rbaddr_id0  : slv2 := "00";   -- id0  address offset
198
 
199
  constant d_f_cflag   : integer := 8;                -- d9: comma flag
200
  subtype  d_f_ctyp   is integer range  2 downto  0;  -- d9: comma type
201
  subtype  d_f_data   is integer range  7 downto  0;  -- d9: data field
202
 
203
  subtype  f_byte1    is integer range 15 downto 8;
204
  subtype  f_byte0    is integer range  7 downto 0;
205
 
206
  constant cntl_rbf_anena    : integer := 15;               -- anena flag
207
  constant cntl_rbf_atoena   : integer := 14;               -- atoena flag
208
  subtype  cntl_rbf_atoval  is integer range  7 downto  0;  -- atoval value
209
  subtype  stat_rbf_lcmd    is integer range 15 downto  8;  -- lcmd
210
  constant stat_rbf_babo     : integer :=  7;               -- block abort flag
211
  constant stat_rbf_arpend   : integer :=  6;               -- attn read pend
212
  subtype  stat_rbf_rbsize  is integer range  2 downto  0;  -- rbuf size
213
 
214
  -- following 4 constants can derived from c_rlink_dat_sop,...
215
  -- defined directly here to work around a ghdl bug
216
  constant c_sop  : slv3 := "000";
217
  constant c_eop  : slv3 := "001";
218
  constant c_nak  : slv3 := "010";
219
  constant c_attn : slv3 := "011";
220
 
221
  constant c_bcmd_stat : slv2 := "00";
222
  constant c_bcmd_init : slv2 := "01";
223
  constant c_bcmd_rblk : slv2 := "10";
224
  constant c_bcmd_wblk : slv2 := "11";
225
 
226
  constant cntawidth : positive := RTAWIDTH-1;        -- cnt is word count
227
  subtype  cnt_f_dat  is integer range cntawidth-1 downto  0;   -- cnt data
228
 
229
  -- link FSM states and state vector ----------------------------------------
230
  type lstate_type is (
231
    sl_idle,                            -- sl_idle: wait for sop
232
    sl_txanot,                          -- sl_txanot: send attn notify
233
    sl_txsop,                           -- sl_txsop: send sop
234
    sl_txnak,                           -- sl_txnak: send nak
235
    sl_txnakcode,                       -- sl_txnakcode: send nakcode
236
    sl_txrtbuf,                         -- sl_txrtbuf: send rtbuf
237
    sl_txeop,                           -- sl_txeop: send eop
238
    sl_rxeop,                           -- sl_rxeop: wait for eop
239
    sl_rxcmd,                           -- sl_rxcmd: wait for cmd
240
    sl_rxaddrl,                         -- sl_rxaddrl: wait for addr low
241
    sl_rxaddrh,                         -- sl_rxaddrh: wait for addr high
242
    sl_rxdatl,                          -- sl_rxdatl: wait for data low
243
    sl_rxdath,                          -- sl_rxdath: wait for data high
244
    sl_rxcntl,                          -- sl_rxcntl: wait for count low
245
    sl_rxcnth,                          -- sl_rxcnth: wait for count low
246
    sl_rxccrcl,                         -- sl_rxccrcl: wait for command crc low
247
    sl_rxccrch,                         -- sl_rxccrcl: wait for command crc high
248
    sl_txcmd,                           -- sl_txcmd: send cmd
249
    sl_txcntl,                          -- sl_txcntl: send cnt lsb
250
    sl_txcnth,                          -- sl_txcnth: send cnt msb
251
    sl_rstart,                          -- sl_rstart: start rreg or rblk
252
    sl_txdat,                           -- sl_txdat: send data
253
    sl_wblk,                            -- sl_wblk: setup rx wblk data
254
    sl_rxwblk,                          -- sl_rxwblk: wait for wblk data
255
    sl_rxdcrcl,                         -- sl_rxdcrcl: wait for data crc low
256
    sl_rxdcrch,                         -- sl_rxdcrch: wait for data crc high
257
    sl_wblk0,                           -- sl_wblk0: start wblk pipe
258
    sl_wblk1,                           -- sl_wblk1: start wblk data lsb
259
    sl_wblk2,                           -- sl_wblk2: start wblk data msb
260
    sl_wblkl,                           -- sl_wblkl: wblk data lsb
261
    sl_wblkh,                           -- sl_wblkh: wblk data msb
262
    sl_wwait0,                          -- sl_wwait0: wait for wdone
263
    sl_wwait1,                          -- sl_wwait1: wait for dcnt
264
    sl_txdcntl,                         -- sl_txdcntl: send dcnt lsb
265
    sl_txdcnth,                         -- sl_txdcnth: send dcnt lsb
266
    sl_txlabo,                          -- sl_txlabo: send labo flag
267
    sl_attn,                            -- sl_attn: handle attention flags
268
    sl_txstat,                          -- sl_txstat: send status
269
    sl_txcrcl,                          -- sl_txcrcl: send crc low
270
    sl_txcrch                           -- sl_txcrch: send crc high
271 2 wfjm
  );
272
 
273 27 wfjm
  type lregs_type is record
274
    state : lstate_type;                -- state
275 2 wfjm
    rcmd : slv8;                        -- received command
276 27 wfjm
    lcmd : slv8;                        -- last command
277
    addr : slv16;                       -- rbus register address
278
    din : slv16;                        -- rbus input data
279
    cnt : slv16;                        -- block transfer count
280
    bcnt : slv(RTAWIDTH-1 downto 0);    -- blk counter (byte and word)
281 2 wfjm
    attn : slv16;                       -- attn mask
282 27 wfjm
    anreq : slbit;                      -- attn notify request
283
    anact : slbit;                      -- attn notify active
284
    arpend : slbit;                     -- attn read pending
285
    atocnt : slv8;                      -- attn timeout counter
286
    babo : slbit;                       -- last blk aborted
287
    nakdone : slbit;                    -- nak done
288
    nakcode : slv3;                     -- nak code
289
    cmdseen : slbit;                    -- 1st command seen
290
    doretra : slbit;                    -- do a retransmit
291
    dinl : slv8;                        -- din lsb for wblk pipeline
292
    rtaddra : slv(RTAWIDTH-1 downto 0); -- rtbuf port a addr (write pointer)
293
    rtaddra_red : slbit;                -- rtaddra red (at max)
294
    rtaddra_bad : slbit;                -- rtaddra bad (inc beyond max)
295
    rtaddrb : slv(RTAWIDTH-1 downto 0); -- rtbuf port b addr (aux pointer)
296
    rtaddrb_red : slbit;                -- rtaddrb red (at max)
297
    rtaddrb_bad : slbit;                -- rtaddrb bad (inc beyond max)
298 9 wfjm
    moneop : slbit;                     -- rl_moni: eop send pulse
299
    monattn : slbit;                    -- rl_moni: attn send pulse
300 27 wfjm
  end record lregs_type;
301 2 wfjm
 
302 27 wfjm
  constant bcnt_zero   : slv(RTAWIDTH-1 downto 0) := (others=>'0');
303
  constant rtaddr_zero : slv(RTAWIDTH-1 downto 0) := (others=>'0');
304
  constant rtaddr_tred : slv(RTAWIDTH-1 downto 0) := (0=>'0', others=>'1');
305 2 wfjm
 
306 27 wfjm
  constant lregs_init : lregs_type := (
307
    sl_idle,                            -- state
308 2 wfjm
    (others=>'0'),                      -- rcmd
309 27 wfjm
    (others=>'1'),                      -- lcmd
310 2 wfjm
    (others=>'0'),                      -- addr
311 27 wfjm
    (others=>'0'),                      -- din
312 2 wfjm
    (others=>'0'),                      -- cnt
313 27 wfjm
    bcnt_zero,                          -- bcnt
314 2 wfjm
    (others=>'0'),                      -- attn
315 27 wfjm
    '0','0','0',                        -- anreq,anact,arpend
316
    (others=>'0'),                      -- atocnt
317
    '0',                                -- babo
318
    '0',                                -- nakdone
319
    (others=>'0'),                      -- nakcode
320
    '0','0',                            -- cmdseen,doretra
321
    (others=>'0'),                      -- dinl
322
    rtaddr_zero,                        -- rtaddra
323
    '0','0',                            -- rtaddra_red, rtaddra_bad
324
    rtaddr_zero,                        -- rtaddrb
325
    '0','0',                            -- rtaddrb_red, rtaddrb_bad
326
    '0','0'                             -- moneop,monattn
327
  );
328
 
329
  -- bus FSM states and state vector -----------------------------------------
330
  type bstate_type is (
331
    sb_idle,                            -- sb_idle: wait for cmd
332
    sb_rstart,                          -- sb_rstart: start rblk
333
    sb_rreg0,                           -- sb_rreg0: rbus read cycle
334
    sb_rreg1,                           -- sb_rreg1: send read data
335
    sb_rwait,                           -- sb_rwait: wait for fifo
336
    sb_rend,                            -- sb_rend: send last read data
337
    sb_rabo0,                           -- sb_rabo0: rblk abort, lsb data
338
    sb_rabo1,                           -- sb_rabo1: rblk abort, msb data
339
    sb_wstart,                          -- sb_wstart: start wblk
340
    sb_wreg0,                           -- sb_wreg0: rbus write cycle
341
    sb_wreg1,                           -- sb_wreg1: wait write data
342
    sb_wabo0,                           -- sb_wabo0: wblk abort, drop data
343
    sb_wabo1                            -- sb_wabo1: wblk abort, wait
344
  );
345
 
346
  type bregs_type is record
347
    state : bstate_type;                -- state
348
    rbinit : slbit;                     -- rbus init signal
349
    rbaval : slbit;                     -- rbus aval signal
350
    rbre : slbit;                       -- rbus re signal
351
    rbwe : slbit;                       -- rbus we signal
352
    rbdout : slv16;                     -- rbus dout
353 28 wfjm
    rbtout: slbit;                      -- rbus timeout
354
    rbnak: slbit;                       -- rbus no ack
355 27 wfjm
    rberr : slbit;                      -- rbus err bit set
356
    blkabo : slbit;                     -- blk abort
357
    cnt : slv(cntawidth-1 downto 0);    -- word count for rblk and wblk
358
    dcnt : slv(cntawidth-1 downto 0);   -- done count for rblk and wblk
359
    btocnt : slv(BTOWIDTH-1 downto 0);  -- rbus timeout counter
360
    dathpend : slbit;                   -- dat msb pending
361
    wfifo : slbit;                      -- wait for fifo
362
    stat : slv4;                        -- external status flags
363
  end record bregs_type;
364
 
365
  constant btocnt_init : slv(BTOWIDTH-1 downto 0) := (others=>'1');
366
  constant cnt_zero    : slv(cntawidth-1 downto 0) := (others=>'0');
367
 
368
  constant bregs_init : bregs_type := (
369
    sb_idle,                            -- state
370 9 wfjm
    '0','0','0','0',                    -- rbinit,rbaval,rbre,rbwe
371 27 wfjm
    (others=>'0'),                      -- rbdout
372 28 wfjm
    '0','0','0',                        -- rbtout,rbnak,rberr
373 27 wfjm
    '0',                                -- blkabo
374
    cnt_zero,                           -- cnt
375
    cnt_zero,                           -- dcnt
376
    btocnt_init,                        -- btocnt
377
    '0','0',                            -- dathpend,wfifo
378 2 wfjm
    (others=>'0')                       -- stat
379
  );
380
 
381 27 wfjm
  -- config state regs --------------------------------------------------------
382
  type cregs_type is record
383
    anena : slbit;                      -- attn notification enable flag
384
    atoena : slbit;                     -- attn timeout enable flag
385
    atoval : slv8;                      -- attn timeout value
386
  end record cregs_type;
387
 
388
  constant cregs_init : cregs_type := (
389
    '0','0',                            -- anena,atoena
390
    (others=>'0')                       -- atoval
391
  );
392 2 wfjm
 
393 27 wfjm
  signal R_LREGS : lregs_type := lregs_init;  -- state registers link FSM
394 36 wfjm
  signal N_LREGS : lregs_type;         -- don't init (vivado fix for fsm infer)
395 27 wfjm
  signal R_BREGS : bregs_type := bregs_init;  -- state registers bus FSM
396 36 wfjm
  signal N_BREGS : bregs_type;         -- don't init (vivado fix for fsm infer)
397 27 wfjm
  signal R_CREGS : cregs_type := cregs_init;  -- state registers config
398
  signal N_CREGS : cregs_type := cregs_init;  -- next value state regs config
399
 
400
  signal RTBUF_ENB : slbit := '0';
401
  signal RTBUF_WEA : slbit := '0';
402
  signal RTBUF_WEB : slbit := '0';
403
  signal RTBUF_DIA : slv8 := (others=>'0');
404
  signal RTBUF_DIB : slv8 := (others=>'0');
405
  signal RTBUF_DOB : slv8 := (others=>'0');
406
 
407
  signal DOFIFO_DI   : slv8  := (others=>'0');
408
  signal DOFIFO_ENA  : slbit := '0';
409
  signal DOFIFO_DO   : slv8  := (others=>'0');
410
  signal DOFIFO_VAL  : slbit := '0';
411
  signal DOFIFO_HOLD : slbit := '0';
412
  signal DOFIFO_SIZE : slv6  := (others=>'0');
413
 
414 2 wfjm
  signal CRC_RESET : slbit := '0';
415 27 wfjm
  signal ICRC_ENA  : slbit := '0';
416
  signal OCRC_ENA  : slbit := '0';
417
  signal ICRC_OUT  : slv16 := (others=>'0');
418
  signal OCRC_OUT  : slv16 := (others=>'0');
419
  signal OCRC_IN   : slv8  := (others=>'0');
420 2 wfjm
 
421 27 wfjm
  signal RBSEL : slbit := '0';
422
 
423 34 wfjm
  signal RB_MREQ_L     : rb_mreq_type := rb_mreq_init;  -- internal mreq
424
  signal RB_SRES_CLEAN : rb_sres_type := rb_sres_init;  -- cleaned rb_sres
425
  signal RB_SRES_CONF  : rb_sres_type := rb_sres_init;  -- config sres
426
  signal RB_SRES_TOT   : rb_sres_type := rb_sres_init;  -- total  sres
427 27 wfjm
 
428
  signal RL_BUSY_L : slbit := '0';
429
  signal RL_DO_L   : slv9  := (others=>'0');
430
  signal RL_VAL_L  : slbit := '0';
431
 
432
  signal L2B_GO    : slbit := '0';
433
  signal L2B_CMD  : slv2 := (others=>'0');
434
  signal B2L_WDONE : slbit := '0';
435
 
436 2 wfjm
begin
437
 
438 27 wfjm
  -- allow 11 bit (1 x 18kbit BRAM) to 15 bit (8 x 36 kbit BRAMs)
439
  assert RTAWIDTH>=11 and RTAWIDTH<=14
440
    report "assert(RTAWIDTH>=11 and RTAWIDTH<=15): unsupported RTAWIDTH"
441 2 wfjm
    severity failure;
442 27 wfjm
 
443
  RTBUF : ram_2swsr_rfirst_gen
444
    generic map (
445
      AWIDTH => RTAWIDTH,
446
      DWIDTH =>  8)
447
    port map (
448
      CLKA  => CLK,
449
      CLKB  => CLK,
450
      ENA   => RTBUF_WEA,               -- port A write only, thus en=we
451
      ENB   => RTBUF_ENB,
452
      WEA   => RTBUF_WEA,
453
      WEB   => RTBUF_WEB,
454
      ADDRA => R_LREGS.rtaddra,
455
      ADDRB => R_LREGS.rtaddrb,
456
      DIA   => RTBUF_DIA,
457
      DIB   => RTBUF_DIB,
458
      DOA   => open,
459
      DOB   => RTBUF_DOB
460
      );
461
 
462
  DOFIFO : fifo_1c_dram
463
    generic map (
464
      AWIDTH => 5,
465
      DWIDTH => 8)
466
    port map (
467
      CLK   => CLK,
468
      RESET => RESET,
469
      DI    => DOFIFO_DI,
470
      ENA   => DOFIFO_ENA,
471
      BUSY  => open,
472
      DO    => DOFIFO_DO,
473
      VAL   => DOFIFO_VAL,
474
      HOLD  => DOFIFO_HOLD,
475
      SIZE  => DOFIFO_SIZE
476
    );
477 2 wfjm
 
478 27 wfjm
  ICRC : crc16                          -- crc generator for input data
479
    port map (
480
      CLK   => CLK,
481
      RESET => CRC_RESET,
482
      ENA   => ICRC_ENA,
483
      DI    => RL_DI(d_f_data),
484
      CRC   => ICRC_OUT
485
    );
486 2 wfjm
 
487 27 wfjm
  OCRC : crc16                          -- crc generator for output data
488
    port map (
489
      CLK   => CLK,
490
      RESET => CRC_RESET,
491
      ENA   => OCRC_ENA,
492
      DI    => OCRC_IN,
493
      CRC   => OCRC_OUT
494
    );
495 2 wfjm
 
496 27 wfjm
  SEL : rb_sel                          -- rbus address select for config regs
497
    generic map (
498
      RB_ADDR => rbaddr,
499
      SAWIDTH => 2)
500
    port map (
501
      CLK     => CLK,
502
      RB_MREQ => RB_MREQ_L,
503
      SEL     => RBSEL
504
    );
505
 
506
  RB_SRES_OR : rb_sres_or_2
507
    port map (
508 34 wfjm
      RB_SRES_1  => RB_SRES_CLEAN,
509 27 wfjm
      RB_SRES_2  => RB_SRES_CONF,
510
      RB_SRES_OR => RB_SRES_TOT
511
    );
512
 
513 34 wfjm
  proc_sres: process (RB_SRES)
514
    variable sres : rb_sres_type := rb_sres_init;
515
    variable datax01 : slv16 := (others=>'0');
516
    variable data01  : slv16 := (others=>'0');
517
  begin
518
    sres.ack  := to_x01(RB_SRES.ack);
519
    sres.busy := to_x01(RB_SRES.busy);
520
    sres.err  := to_x01(RB_SRES.err);
521
    sres.dout := to_x01(RB_SRES.dout);
522
 
523
    if sres.ack = '1' and sres.busy = '0' and is_x(sres.dout) then
524 37 wfjm
      report "rlink_core: seen 'x' in rb_sres.data"
525 34 wfjm
        severity warning;
526
      sres.dout := (others=>'1');
527
    end if;
528
 
529
    RB_SRES_CLEAN <= sres;
530
  end process proc_sres;
531
 
532 2 wfjm
  proc_regs: process (CLK)
533
  begin
534
 
535 13 wfjm
    if rising_edge(CLK) then
536 2 wfjm
      if RESET = '1' then
537 27 wfjm
        R_LREGS <= lregs_init;
538
        R_BREGS <= bregs_init;
539
        R_CREGS <= cregs_init;
540 2 wfjm
      else
541 27 wfjm
        R_LREGS <= N_LREGS;
542
        R_BREGS <= N_BREGS;
543
        R_CREGS <= N_CREGS;
544
     end if;
545 2 wfjm
    end if;
546
 
547
  end process proc_regs;
548
 
549 27 wfjm
  -- link FSM ================================================================
550 2 wfjm
 
551 27 wfjm
  proc_lnext: process (R_LREGS, R_CREGS, R_BREGS,
552
                       CE_INT, RL_DI, RL_ENA, RL_HOLD, RB_LAM,
553
                       ICRC_OUT, OCRC_OUT, RTBUF_DOB,
554
                       DOFIFO_DO, DOFIFO_VAL,
555
                       B2L_WDONE)
556 2 wfjm
 
557 27 wfjm
    variable r : lregs_type := lregs_init;
558
    variable n : lregs_type := lregs_init;
559
 
560 2 wfjm
    variable ival : slbit := '0';
561
    variable ibusy : slbit := '0';
562
    variable ido : slv9 := (others=>'0');
563
    variable crcreset : slbit := '0';
564
    variable icrcena : slbit := '0';
565
    variable ocrcena : slbit := '0';
566
    variable has_attn : slbit := '0';
567
    variable idi8 : slv8 := (others=>'0');
568
    variable is_comma : slbit := '0';
569 27 wfjm
    variable comma_typ : slv3 := "000";
570
    variable idohold : slbit := '0';
571
    variable cnt_iszero : slbit := '0';
572
    variable bcnt_load : slbit := '0';
573
    variable bcnt_val : slv(RTAWIDTH-1 downto 0) := (others=>'0');
574
    variable bcnt_dec : slbit := '0';
575
    variable bcnt_end : slbit := '0';
576
    variable irtwea : slbit := '0';
577
    variable irtreb : slbit := '0';
578
    variable irtweb : slbit := '0';
579
    variable addra_clear : slbit := '0';
580
    variable addrb_load  : slbit := '0';
581
    variable addrb_sela  : slbit := '0';
582
    variable ibcmd : slv2 := (others=>'0');
583
    variable ibgo  : slbit := '0';
584 2 wfjm
 
585
  begin
586
 
587 27 wfjm
    r := R_LREGS;
588
    n := R_LREGS;
589 2 wfjm
 
590 9 wfjm
    n.moneop  := '0';                   -- default '0', only set by states
591
    n.monattn := '0';                   -- "
592 2 wfjm
 
593 27 wfjm
    ival := '0';
594 2 wfjm
    ibusy := '1';                       -- default is to hold input
595
    ido  := (others=>'0');
596
 
597
    crcreset := '0';
598
    icrcena  := '0';
599
    ocrcena  := '0';
600
 
601
    has_attn := '0';
602 27 wfjm
 
603
    is_comma  := RL_DI(d_f_cflag);      -- get comma marker
604
    comma_typ := RL_DI(d_f_ctyp);       -- get comma type
605
    idi8      := RL_DI(d_f_data);       -- get data part of RL_DI
606
 
607
    idohold := '1';                     -- default is to hold DOFIFO
608
 
609
    cnt_iszero := '0';
610
    if unsigned(r.cnt(cnt_f_dat)) = 0 then
611
      cnt_iszero := '1';
612
    end if;
613 9 wfjm
 
614 27 wfjm
    bcnt_load := '0';
615
    bcnt_val  := r.cnt(cnt_f_dat) & '0'; -- default: 2*cnt (most used)
616
    bcnt_dec  := '0';
617
    bcnt_end  := '0';
618
    if unsigned(r.bcnt) = 1 then
619
      bcnt_end := '1';
620
    end if;
621
 
622
    irtwea  := '0';
623
    irtreb  := '0';
624
    irtweb  := '0';
625
    addra_clear := '0';
626
    addrb_load  := '0';
627
    addrb_sela  := '1';           -- default: addra (most used)
628
 
629
    ibcmd := (others=>'0');
630
    ibgo := '0';
631
 
632
    -- handle attention "LAM's"
633
    n.attn := r.attn or RB_LAM;
634
 
635
    -- detect attn notify requests
636
    if unsigned(r.attn) /= 0 then       -- if any of the attn bits set
637 9 wfjm
      has_attn  := '1';
638 27 wfjm
      if R_CREGS.anena='1' and r.arpend='0' then -- if attn to be send
639
        n.anreq := '1';                      -- set notify request flag
640 9 wfjm
      end if;
641 2 wfjm
    end if;
642 9 wfjm
 
643 27 wfjm
    -- handle attn read timeouts
644
    --  atocnt is held in reset when no attn read is pending
645
    --    counting down in CE_INT cycles till zero
646
    --    when zero, an attn notify is requested when atoena is set
647
    --    the attn notify flag will reset atocnt to its start value
648
    --    --> when atoena='1' this creates a notify every atoval CE_INT periods
649
    --    --> when atoena='0' atocnt will count to zero and stay there
650 2 wfjm
 
651 27 wfjm
    if r.arpend = '0' or r.anreq = '1' then   -- if no attn read pending
652
      n.atocnt := R_CREGS.atoval;         -- keep at start value
653
    else                                -- otherwise
654
      if CE_INT = '1' then                -- if CE_INT
655
        if unsigned(r.atocnt) = 0 then      -- alread counted down 
656
          n.anreq :=  R_CREGS.atoena;         -- request attn notify if enabled
657
        else                                -- not yet down
658
          n.atocnt := slv(unsigned(r.atocnt) - 1);  -- decrement
659
        end if;
660
      end if;
661 2 wfjm
    end if;
662
 
663
    case r.state is
664 27 wfjm
 
665
      when sl_idle =>                   -- sl_idle: wait for sop -------------
666
        bcnt_val := r.rtaddra;            -- used for nak handling
667
        addrb_sela := '0';
668
        n.anact    := '0';
669
        n.doretra := '0';
670
        crcreset := '1';                  -- reset crc generators
671
        if r.anreq = '1' then             -- if attn notify requested
672
          n.anreq  := '0';                  -- acknowledge request
673
          n.arpend := '1';                  -- mark attn read pending
674
          n.state := sl_txanot;             -- next: send attn notify
675 2 wfjm
        else
676
          ibusy := '0';                   -- accept input
677 9 wfjm
          if RL_ENA = '1' then            -- if input
678 2 wfjm
            if is_comma = '1' then          -- if comma
679
              case comma_typ is
680
                when c_sop =>                 -- if sop
681 27 wfjm
                  n.cmdseen := '0';             -- clear cmd seen flag
682
                  n.state := sl_txsop;          -- next: echo it
683 2 wfjm
                when c_attn =>                -- if attn
684 27 wfjm
                  n.state := sl_txanot;         -- next: send attn notify
685
                when c_nak =>
686
                  addrb_load := '1';
687
                  bcnt_load  := '1';
688
                  n.doretra  := '1';
689
                  n.state := sl_txsop;          -- next: send sop
690 2 wfjm
                when others => null;          -- other commas: silently ignore
691 27 wfjm
                                                -- especially: eop is ignored
692 2 wfjm
              end case;
693
            else                             -- if normal data
694 27 wfjm
              n.state := sl_idle;              -- silently dropped
695 2 wfjm
            end if;
696
          end if;
697
        end if;
698 27 wfjm
 
699
      when sl_txanot =>                 -- sl_txanot: send attn notify -------
700
        n.cnt := r.attn;                  -- transfer attn to cnt for transmit
701
        n.anact := '1';                   -- signal attn notify active 
702
        ido  := c_rlink_dat_attn;         -- send attn symbol
703 2 wfjm
        ival := '1';
704 9 wfjm
        if RL_HOLD = '0' then             -- wait for accept
705 27 wfjm
          n.monattn := '1';                 -- signal on rl_moni
706
          n.state := sl_txcntl;             -- next: send cnt lsb
707 2 wfjm
        end if;
708
 
709 27 wfjm
      when sl_txsop =>                  -- sl_txsop: send sop ----------------
710 9 wfjm
        ido := c_rlink_dat_sop;           -- send sop character
711 2 wfjm
        ival := '1';
712 9 wfjm
        if RL_HOLD = '0' then             -- wait for accept
713 27 wfjm
          if r.doretra = '1' then           -- if retra request
714
            irtreb := '1';                    -- request first byte
715
            n.state := sl_txrtbuf;            -- next: send rtbuf
716
          else                              -- or normal command
717
            n.state := sl_rxcmd;              -- next: read first command
718
          end if;
719 2 wfjm
        end if;
720
 
721 27 wfjm
      when sl_txnak =>                  -- sl_txnak: send nak ----------------
722
        n.nakdone := '1';                 -- set nakdone flag
723 9 wfjm
        ido := c_rlink_dat_nak;           -- send nak character
724 2 wfjm
        ival := '1';
725 9 wfjm
        if RL_HOLD = '0' then             -- wait for accept
726 27 wfjm
          n.state := sl_txnakcode;          -- next: send nakcode
727 2 wfjm
        end if;
728
 
729 27 wfjm
      when sl_txnakcode =>              -- sl_txnakcode: send nakcode --------
730
        ido := '0' & "10" & (not r.nakcode) & r.nakcode;
731 2 wfjm
        ival := '1';
732 9 wfjm
        if RL_HOLD = '0' then             -- wait for accept
733 27 wfjm
          n.state := sl_rxeop;            -- next: wait for eop
734 2 wfjm
        end if;
735
 
736 27 wfjm
      when sl_rxeop =>                  -- sl_rxeop: wait for eop ------------
737 2 wfjm
        ibusy := '0';                     -- accept input
738 9 wfjm
        if RL_ENA = '1' then
739 27 wfjm
          if is_comma = '1' and comma_typ = c_eop then  -- if eop seen
740
            n.state  := sl_txeop;          -- next: echo eop
741 2 wfjm
          end if;
742
        end if;
743
 
744 27 wfjm
      when sl_txrtbuf =>                -- sl_txrtbuf: send rtbuf ------------
745
        ido := '0' & RTBUF_DOB;           -- send rtbuf data
746
        ival := '1';
747
        if RL_HOLD = '0' then             -- wait for accept
748
          bcnt_dec := '1';
749
          if bcnt_end = '0' then            -- if not yet done
750
            irtreb := '1';                    -- request next byte
751
          else                              -- all done
752
            if r.nakdone = '0' then         -- if no nak active
753
              n.state := sl_txeop;              -- next: send eop
754
            else
755
              n.state := sl_txnak;              -- next: send nak
756
            end if;
757
          end if;
758
        end if;
759
 
760
      when sl_txeop =>                  -- sl_txeop: send eop ----------------
761 36 wfjm
        n.state := sl_txeop;              -- needed to prevent vivado iSTATE
762 27 wfjm
        ido := c_rlink_dat_eop;           -- send eop character
763
        ival := '1';
764
        if RL_HOLD = '0' then             -- wait for accept
765
          n.moneop := '1';                  -- signal on rl_moni
766
          n.state := sl_idle;               -- next: idle state, wait for sop
767
        end if;
768
 
769
       when sl_rxcmd =>                  -- sl_rxcmd: wait for cmd ------------
770
        ibusy := '0';                      -- accept input
771
        n.cnt := slv(to_unsigned(1,16));   -- preset cnt=1 (used for rreg)
772
        n.rcmd := idi8;                    -- latch cmd (follow till valid)
773 9 wfjm
        if RL_ENA = '1' then
774 2 wfjm
          if is_comma = '1' then          -- if comma
775 27 wfjm
            if comma_typ = c_eop then       -- eop seen
776
              n.state  := sl_txeop;           -- next: echo eop
777
            else                            -- any other comma seen
778
              n.nakcode := c_rlink_nakcode_frame; -- signal framing error
779
              n.state  := sl_txnak;         -- next: send nak
780
            end if;
781 9 wfjm
          else                            -- if not comma
782 27 wfjm
            if r.cmdseen = '0' then         -- if first cmd
783
              n.nakdone := '0';               -- clear nakdone flag
784
              addra_clear := '1';             -- clear rtbuf
785
            end if;
786
            n.cmdseen := '1';               -- set cmd seen flag
787 9 wfjm
            icrcena   := '1';               -- update input crc
788
            case RL_DI(c_rlink_cmd_rbf_code) is
789
              when c_rlink_cmd_rreg |
790
                   c_rlink_cmd_rblk |
791
                   c_rlink_cmd_wreg |
792
                   c_rlink_cmd_wblk |
793
                   c_rlink_cmd_init =>      -- for commands needing addr(data)
794 27 wfjm
                n.state := sl_rxaddrl;        -- next: read address lsb
795
              when c_rlink_cmd_labo |
796
                   c_rlink_cmd_attn =>      -- labo and attn commands
797
                n.state := sl_rxccrcl;        -- next: read command crc low
798 2 wfjm
              when others =>
799 27 wfjm
                n.nakcode := c_rlink_nakcode_cmd; -- signal bad cmd
800
                n.state := sl_txnak;          -- next: send nak
801
            end case;
802 2 wfjm
          end if;
803
        end if;
804 27 wfjm
 
805
      when sl_rxaddrl =>                -- sl_rxaddrl: wait for addr lsb -----
806 2 wfjm
        ibusy := '0';                     -- accept input
807 27 wfjm
        n.addr(f_byte0) := idi8;          -- latch addr lsb (follow till valid)
808 9 wfjm
        if RL_ENA = '1' then
809 27 wfjm
          if is_comma = '1' then          -- if comma 
810
            n.nakcode := c_rlink_nakcode_frame; -- signal framing error
811
            n.state   := sl_txnak;          -- next: send nak,
812
         else
813
            icrcena  := '1';              -- update input crc
814
            n.state := sl_rxaddrh;          -- next: read addr msb
815
          end if;
816
        end if;
817
 
818
      when sl_rxaddrh =>                -- sl_rxaddrh: wait for addr msb -----
819
        ibusy := '0';                     -- accept input
820
        n.addr(f_byte1) := idi8;          -- latch addr msb (follow till valid)
821
        if RL_ENA = '1' then
822 2 wfjm
          if is_comma = '1' then          -- if comma
823 27 wfjm
            n.nakcode := c_rlink_nakcode_frame; -- signal framing error
824
            n.state   := sl_txnak;          -- next: send nak
825 2 wfjm
          else
826
            icrcena  := '1';              -- update input crc
827 9 wfjm
            case r.rcmd(c_rlink_cmd_rbf_code) is
828
              when c_rlink_cmd_rreg =>      -- for rreg command
829 27 wfjm
                n.state := sl_rxccrcl;        -- next: read command crc low
830 9 wfjm
              when c_rlink_cmd_wreg |
831
                   c_rlink_cmd_init =>      -- for wreg, init command
832 27 wfjm
                n.state := sl_rxdatl;         -- next: read data lsb
833 9 wfjm
              when others =>                -- for rblk or wblk
834 27 wfjm
                n.state := sl_rxcntl;         -- next: read count lsb
835 2 wfjm
            end case;
836
          end if;
837
        end if;
838
 
839 27 wfjm
      when sl_rxdatl =>                 -- sl_rxdatl: wait for data low ------
840 2 wfjm
        ibusy := '0';                     -- accept input
841 27 wfjm
        n.din(f_byte0) := idi8;           -- latch data lsb (follow till valid)
842 9 wfjm
        if RL_ENA = '1' then
843 2 wfjm
          if is_comma = '1' then          -- if comma 
844 27 wfjm
            n.nakcode := c_rlink_nakcode_frame; -- signal framing error
845
            n.state   := sl_txnak;          -- next: send nak
846 2 wfjm
         else
847
            icrcena  := '1';              -- update input crc
848 27 wfjm
            n.state := sl_rxdath;         -- next: read data msb
849 2 wfjm
          end if;
850
        end if;
851 27 wfjm
 
852
      when sl_rxdath =>                 -- sl_rxdath: wait for data high -----
853 2 wfjm
        ibusy := '0';                     -- accept input
854 27 wfjm
        n.din(f_byte1) := idi8;           -- latch data msb (follow till valid)
855 9 wfjm
        if RL_ENA = '1' then
856 2 wfjm
          if is_comma = '1' then          -- if comma
857 27 wfjm
            n.nakcode := c_rlink_nakcode_frame; -- signal framing error
858
            n.state   := sl_txnak;          -- next: send nak
859 2 wfjm
          else
860
            icrcena  := '1';              -- update input crc
861 27 wfjm
            n.state := sl_rxccrcl;        -- next: read command crc low
862 2 wfjm
          end if;
863 27 wfjm
        end if;
864
 
865
      when sl_rxcntl =>                 -- sl_rxcntl: wait for count lsb -----
866
        ibusy := '0';                     -- accept input
867
        n.cnt(f_byte0) := idi8;           -- latch count lsb (follow till valid)
868
        if RL_ENA = '1' then
869
          if is_comma = '1' then            -- if comma
870
            n.nakcode := c_rlink_nakcode_frame; -- signal framing error
871
            n.state   := sl_txnak;            -- next: send nak
872
          else
873
            icrcena  := '1';              -- update input crc
874
            n.state := sl_rxcnth;         -- next: read count msb
875
          end if;
876 2 wfjm
        end if;
877 27 wfjm
 
878
      when sl_rxcnth =>                 -- sl_rxcnth: wait for count msb -----
879 2 wfjm
        ibusy := '0';                     -- accept input
880 27 wfjm
        n.cnt(f_byte1) := idi8;           -- latch count lsb (follow till valid)
881 9 wfjm
        if RL_ENA = '1' then
882 2 wfjm
          if is_comma = '1' then            -- if comma
883 27 wfjm
            n.nakcode := c_rlink_nakcode_frame; -- signal framing error
884
            n.state   := sl_txnak;            -- next: send nak
885 2 wfjm
          else
886
            icrcena  := '1';              -- update input crc
887 27 wfjm
            if unsigned(idi8(7 downto cntawidth-8)) = 0 then  -- if cnt ok
888
              n.state := sl_rxccrcl;        -- next: read command crc low
889
            else
890
              n.nakcode := c_rlink_nakcode_cnt; -- signal bad cnt
891
              n.state := sl_txnak;              -- next: send nak
892
            end if;
893 2 wfjm
          end if;
894 27 wfjm
        end if;
895 2 wfjm
 
896 27 wfjm
      when sl_rxccrcl =>                -- sl_rxccrcl: wait for command crc low
897 2 wfjm
        ibusy := '0';                     -- accept input
898 9 wfjm
        if RL_ENA = '1' then
899 2 wfjm
          if is_comma = '1' then            -- if comma
900 27 wfjm
            n.nakcode := c_rlink_nakcode_frame;  -- signal framing error
901
            n.state   := sl_txnak;               -- next: send nak
902 2 wfjm
          else
903 27 wfjm
            if idi8 /= ICRC_OUT(f_byte0) then    -- if crc error (lsb)
904
              n.nakcode := c_rlink_nakcode_ccrc; -- signal bad ccrc
905
              n.state := sl_txnak;            -- next: send nak
906 2 wfjm
            else                            -- if crc ok
907 27 wfjm
              n.state := sl_rxccrch;          -- next: wait for command crc high
908 2 wfjm
            end if;
909
          end if;
910
        end if;
911
 
912 27 wfjm
      when sl_rxccrch =>                -- sl_rxccrcl: wait for command crc high
913
        ibusy := '0';                     -- accept input
914
        if RL_ENA = '1' then
915
          if is_comma = '1' then            -- if comma
916
            n.nakcode := c_rlink_nakcode_frame;  -- signal framing error
917
            n.state   := sl_txnak;               -- next: send nak
918
          else
919
            if idi8 /= ICRC_OUT(f_byte1) then   -- if crc error (msb)
920
              n.nakcode := c_rlink_nakcode_ccrc; -- signal bad ccrc
921
              n.state := sl_txnak;            -- next: send nak
922
            else                            -- if crc ok
923
              n.state := sl_txcmd;            -- next: echo command
924
            end if;
925
          end if;
926
        end if;
927
 
928
      when sl_txcmd =>                  -- sl_txcmd: send cmd -----------------
929 2 wfjm
        ido := '0' & r.rcmd;              -- send read command
930
        ival := '1';
931 9 wfjm
        if RL_HOLD = '0' then             -- wait for accept
932 27 wfjm
          irtwea  := '1';
933
          ocrcena := '1';                  -- update output crc
934
          ibcmd   := c_bcmd_stat;          -- latch external status bits
935
          ibgo    := '1';
936 9 wfjm
 
937
          case r.rcmd(c_rlink_cmd_rbf_code) is -- main command dispatcher
938
            when c_rlink_cmd_rreg  =>          -- rreg ----------------
939 27 wfjm
              n.state := sl_rstart;              -- next: start rreg
940 9 wfjm
            when c_rlink_cmd_rblk =>           -- rblk ----------------
941 27 wfjm
              n.babo := '0';                    -- clear babo flag
942
              n.state := sl_txcntl;
943 9 wfjm
            when c_rlink_cmd_wreg =>           -- wreg ----------------
944 27 wfjm
              ibcmd := c_bcmd_wblk;
945
              ibgo  := '1';
946
              n.state := sl_wwait0;              -- next: wait for wdone
947 9 wfjm
            when c_rlink_cmd_wblk =>           -- wblk ----------------
948 27 wfjm
              n.babo := '0';                    -- clear babo flag
949
              if cnt_iszero = '0' then            -- if cnt /= 0
950
                n.state := sl_wblk;                 -- next: read wblk data
951
              else                                -- otherwise cnt = 0
952
                n.state := sl_rxdcrcl;              -- next: wait for dcrc low
953
              end if;
954
            when c_rlink_cmd_labo =>           -- labo ----------------
955
              n.state := sl_txlabo;
956 9 wfjm
            when c_rlink_cmd_attn =>           -- attn ----------------
957 27 wfjm
              n.state := sl_attn;
958 9 wfjm
            when c_rlink_cmd_init =>           -- init ----------------
959 27 wfjm
              ibcmd := c_bcmd_init;
960
              ibgo  := '1';
961
              n.state := sl_txstat;
962 2 wfjm
 
963
            when others =>                    -- '111' ---------------
964 27 wfjm
              n.nakcode := c_rlink_nakcode_cmd; -- signal bad cmd
965
              n.state := sl_txnak;              -- send NAK on reserved command
966 2 wfjm
          end case;
967
        end if;
968 27 wfjm
 
969
      when sl_txcntl =>                 -- sl_txcntl: send cnt lsb ------------
970
        ido := '0' & r.cnt(f_byte0);      -- send cnt lsb
971 2 wfjm
        ival := '1';
972 9 wfjm
        if RL_HOLD = '0' then             -- wait for accept
973 27 wfjm
          irtwea := not r.anact;            -- no rtbuf for attn notify
974 9 wfjm
          ocrcena  := '1';                  -- update output crc
975 27 wfjm
          n.state  := sl_txcnth;            -- next: send cnt msb
976 2 wfjm
        end if;
977
 
978 27 wfjm
      when sl_txcnth =>                 -- sl_txcnth: send cnt msb ------------
979
        ido := '0' & r.cnt(f_byte1);      -- send cnt msb
980 2 wfjm
        ival := '1';
981 9 wfjm
        if RL_HOLD = '0' then             -- wait for accept
982 27 wfjm
          irtwea := not r.anact;            -- no rtbuf for attn notify
983
          ocrcena  := '1';                  -- update output crc
984
          if r.anact = '1' then              -- if in attn notify
985
            n.state := sl_txcrcl;             -- next: send crc low
986
          elsif r.rcmd(c_rlink_cmd_rbf_code) = c_rlink_cmd_rblk then -- if rblk
987
            if cnt_iszero = '0' then            -- if cnt /= 0
988
              n.state := sl_rstart;               -- next: start rblk
989
            else                                -- otherwise cnt = 0
990
              n.state := sl_txdcntl;              -- next: send dcnt lsb
991
            end if;
992
          else                                -- otherwise, must be attn
993
            n.state  := sl_txstat;            -- next: send stat
994
          end if;
995 2 wfjm
        end if;
996 27 wfjm
 
997
      when sl_rstart =>                 -- sl_rstart: start rreg or rblk -----
998
        ibcmd := c_bcmd_rblk;
999
        ibgo  := '1';
1000
        bcnt_load := '1';
1001
        bcnt_val  := r.cnt(cnt_f_dat) & '0';   -- 2*cnt
1002
        n.state := sl_txdat;
1003
 
1004
      when sl_txdat =>                  -- sl_txdat: send data ---------------
1005
        ido := '0' & DOFIFO_DO;
1006
        if DOFIFO_VAL = '1'  then         -- wait for input
1007
          ival := '1';
1008
          if RL_HOLD = '0' then             -- wait for accept
1009
            idohold := '0';
1010
            irtwea  := '1';
1011
            ocrcena := '1';                   -- update output crc
1012
            bcnt_dec := '1';
1013
            if bcnt_end = '1' then
1014
              if r.rcmd(c_rlink_cmd_rbf_code) = c_rlink_cmd_rblk then -- if rblk
1015
                n.state := sl_txdcntl;
1016
              else
1017
                n.state := sl_txstat;
1018
              end if;
1019
            end if;
1020 2 wfjm
          end if;
1021
        end if;
1022
 
1023 27 wfjm
      when sl_wblk =>                   -- sl_wblk: setup rx wblk data -------
1024
        addrb_load := '1';                -- must be done here because addra
1025
        addrb_sela := '1';                -- is incremented in _txcmd 
1026
        bcnt_load  := '1';
1027
        bcnt_val   := r.cnt(cnt_f_dat) & '0';   -- 2*cnt
1028
        n.state := sl_rxwblk;
1029 9 wfjm
 
1030 27 wfjm
      when sl_rxwblk =>                 -- sl_rxwblk: wait for wblk data -----
1031
        ibusy := '0';                     -- accept input
1032
        if RL_ENA = '1' then
1033
          if is_comma = '1' then            -- if comma
1034
            n.nakcode := c_rlink_nakcode_frame; -- signal framing error
1035
            n.state   := sl_txnak;            -- next: send nak
1036
          else
1037
            icrcena := '1';               -- update input crc
1038
            irtweb  := '1';               -- write into rtbuf via b port
1039
            bcnt_dec := '1';
1040
            if bcnt_end = '1' then        -- if all done
1041
              n.state := sl_rxdcrcl;        -- next: wait for data crc low
1042
            end if;
1043 2 wfjm
          end if;
1044
        end if;
1045
 
1046 27 wfjm
      when sl_rxdcrcl =>                -- sl_rxdcrcl: wait for data crc low -
1047
        ibusy := '0';                     -- accept input
1048
        bcnt_val  := r.cnt(cnt_f_dat) & '0';   -- 2 * cnt
1049
        addrb_sela := '1';
1050
        if RL_ENA = '1' then
1051
          if is_comma = '1' then            -- if comma
1052
            n.nakcode := c_rlink_nakcode_frame;  -- signal framing error
1053
            n.state   := sl_txnak;               -- next: send nak
1054
          else
1055
            if idi8 /= ICRC_OUT(f_byte0) then    -- if crc error lsb
1056
              n.nakcode := c_rlink_nakcode_dcrc; -- signal bad dcrc
1057
              n.state := sl_txnak;            -- next: send nak
1058
            else                            -- if crc ok
1059
              n.state := sl_rxdcrch;           -- next: wait for data crc high
1060
            end if;
1061 2 wfjm
          end if;
1062
        end if;
1063
 
1064 27 wfjm
      when sl_rxdcrch =>                -- sl_rxdcrch: wait for data crc high
1065 2 wfjm
        ibusy := '0';                     -- accept input
1066 27 wfjm
        bcnt_val  := r.cnt(cnt_f_dat) & '0';   -- 2 * cnt
1067
        addrb_sela := '1';
1068 9 wfjm
        if RL_ENA = '1' then
1069 2 wfjm
          if is_comma = '1' then            -- if comma
1070 27 wfjm
            n.nakcode := c_rlink_nakcode_frame;  -- signal framing error
1071
            n.state   := sl_txnak;               -- next: send nak
1072 2 wfjm
          else
1073 27 wfjm
            if idi8 /= ICRC_OUT(f_byte1) then    -- if crc error msb
1074
              n.nakcode := c_rlink_nakcode_dcrc; -- signal bad dcrc
1075
              n.state := sl_txnak;            -- next: send nak
1076
            else                            -- if crc ok
1077
              addrb_load := '1';
1078
              bcnt_load  := '1';
1079
              if r.rtaddrb_bad = '0' then     -- if rtbuf ok
1080
                n.state := sl_wblk0;            -- next: start wblk pipe
1081
              else                            -- else rtbuf ovfl
1082
                n.nakcode := c_rlink_nakcode_rtwblk; -- signal ovfl in wblk
1083
                n.state := sl_txnak;            -- next: send nak
1084
              end if;
1085 2 wfjm
            end if;
1086
          end if;
1087
        end if;
1088
 
1089 27 wfjm
      when sl_wblk0 =>                  -- sl_wblk0: start wblk pipe ---------
1090
        if cnt_iszero = '0' then            -- if cnt /= 0
1091
          irtreb := '1';                    -- request next byte
1092
          n.state := sl_wblk1;              -- next: start data lsb
1093
        else                                -- otherwise cnt = 0
1094
          n.state := sl_txdcntl;              -- next: send dcnt lsb
1095
        end if;
1096 2 wfjm
 
1097 27 wfjm
      when sl_wblk1 =>                  -- sl_wblk1: start wblk data lsb -----
1098
        n.dinl := RTBUF_DOB;              -- latch data lsb
1099
        irtreb := '1';                    -- request next byte
1100
        bcnt_dec := '1';
1101
        n.state := sl_wblk2;              -- next: start data msb
1102
 
1103
      when sl_wblk2 =>                  -- sl_wblk2: start wblk data msb -----
1104
        n.din := RTBUF_DOB & r.dinl;      -- setup din
1105
        bcnt_dec := '1';
1106
        ibcmd := c_bcmd_wblk;             -- start rbus sequencer
1107
        ibgo  := '1';
1108
        if bcnt_end = '0' then            -- if not yet done
1109
          irtreb := '1';                    -- request next byte
1110
          n.state := sl_wblkl;              -- next: enter wblk pipe
1111
        else                              -- all done
1112
          n.state := sl_wwait0;             -- next: wait for wdone
1113
        end if;
1114
 
1115
      when sl_wblkl =>                  -- sl_wblkl: pipe wblk data lsb ------
1116
        n.dinl := RTBUF_DOB;              -- latch data lsb
1117
        irtreb := '1';                    -- request next byte
1118
        bcnt_dec := '1';
1119
        n.state := sl_wblkh;              -- next: pipe msb
1120
 
1121
      when sl_wblkh =>                  -- sl_wblkh: pipe wblk data msb ------
1122
        if B2L_WDONE = '1' then           -- if last write done
1123
          n.din := RTBUF_DOB & r.dinl;      -- setup next din
1124
          bcnt_dec := '1';
1125
          if bcnt_end = '0' then            -- if not yet done
1126
            irtreb := '1';
1127
            n.state := sl_wblkl;              -- next: pipe lsb
1128
          else                              -- all done
1129
            n.state := sl_wwait0;             -- next: wait last wdone
1130
          end if;
1131
        end if;
1132
 
1133
      when sl_wwait0 =>                 -- sl_wwait0: wait for wdone ---------
1134
        if B2L_WDONE = '1' then
1135
          if r.rcmd(c_rlink_cmd_rbf_code) = c_rlink_cmd_wblk then  -- if wblk
1136
            n.state := sl_wwait1;             -- next: wait for dcnt
1137
          else
1138
            n.state := sl_txstat;             -- next: send stat
1139
          end if;
1140
        end if;
1141
 
1142
      when sl_wwait1 =>                 -- sl_wwait1: wait for dcnt ----------
1143
        n.state := sl_txdcntl;            -- next: send dcnt lsb
1144
 
1145
      when sl_txdcntl =>                -- sl_txdcntl: send dcnt lsb ---------
1146 28 wfjm
        n.babo := R_BREGS.blkabo;         -- remember blk abort
1147 27 wfjm
        ido := '0' & R_BREGS.dcnt(f_byte0); -- send dcnt lsb
1148 2 wfjm
        ival := '1';
1149 9 wfjm
        if RL_HOLD = '0' then             -- wait for accept
1150 27 wfjm
          irtwea := '1';
1151 2 wfjm
          ocrcena  := '1';                -- update output crc
1152 27 wfjm
          n.state := sl_txdcnth;          -- next: send dcnt msb
1153 2 wfjm
        end if;
1154
 
1155 27 wfjm
      when sl_txdcnth =>                -- sl_txdcnth: send dcnt msb ---------
1156
        ido := (others=>'0');             -- send dcnt msb
1157
        ido(cntawidth-9 downto 0) := R_BREGS.dcnt(cntawidth-1 downto 8);
1158
        ival := '1';
1159
        if RL_HOLD = '0' then             -- wait for accept
1160
          irtwea := '1';
1161
          ocrcena  := '1';                -- update output crc
1162
          n.state := sl_txstat;           -- next: send stat
1163
        end if;
1164
 
1165
      when sl_txlabo =>                 -- sl_txlabo: send labo flag ---------
1166
        ido := '0' & "0000000" & r.babo;   -- send babo
1167
        ival := '1';
1168
        if RL_HOLD = '0' then             -- wait for accept
1169
          irtwea := '1';
1170
          ocrcena  := '1';                -- update output crc
1171
          n.state := sl_txstat;           -- next: send stat
1172
        end if;
1173
 
1174
      when sl_attn =>                   -- sl_attn: handle attention flags ---
1175
        n.cnt := r.attn;                  -- use cnt to latch attn status
1176
        n.attn := RB_LAM;                 -- LAM in current cycle send next time
1177
        n.arpend := '0';                  -- reenable attn nofification
1178
        n.anreq := '0';                   -- cancel pending notify requests
1179
        n.state := sl_txcntl;             -- next: send cnt lsb (holding attn)
1180
 
1181
      when sl_txstat =>                 -- sl_txstat: send status ------------
1182 28 wfjm
        ido(c_rlink_stat_rbf_stat)   := R_BREGS.stat;
1183
        ido(c_rlink_stat_rbf_attn)   := has_attn;
1184
        ido(c_rlink_stat_rbf_rbtout) := R_BREGS.rbtout;
1185
        ido(c_rlink_stat_rbf_rbnak)  := R_BREGS.rbnak;
1186
        ido(c_rlink_stat_rbf_rberr)  := R_BREGS.rberr;
1187 2 wfjm
        ival := '1';
1188 9 wfjm
        if RL_HOLD  ='0' then             -- wait for accept
1189 27 wfjm
          irtwea := '1';
1190 2 wfjm
          ocrcena  := '1';                -- update output crc
1191 27 wfjm
          n.state := sl_txcrcl;           -- next: send crc low
1192 2 wfjm
        end if;
1193
 
1194 27 wfjm
      when sl_txcrcl =>                 -- sl_txcrcl: send crc low -----------
1195
        ido := "0" & OCRC_OUT(f_byte0);   -- send crc code low
1196 2 wfjm
        ival := '1';
1197 9 wfjm
        if RL_HOLD = '0' then             -- wait for accept
1198 27 wfjm
          irtwea := not r.anact;            -- no rtbuf for attn notify
1199
          n.state := sl_txcrch;             -- next: send crc high
1200
        end if;
1201
 
1202
      when sl_txcrch =>                 -- sl_txcrch: send crc high ----------
1203
        ido := "0" & OCRC_OUT(f_byte1);   -- send crc code high
1204
        -- here check for rtbuf overflow
1205
        -- if space for 1 byte complete command and write crc
1206
        if r.rtaddra_red = '0' then       -- if space for 1 byte
1207
          n.lcmd  := r.rcmd;                -- latch current command in lcmd
1208
          ival := '1';
1209
          if RL_HOLD = '0' then             -- wait for accept
1210
            irtwea := not r.anact;            -- no rtbuf for attn notify
1211
            -- if this was attn notify, back to idle
1212
            if r.anact = '1' then
1213
              n.state := sl_txeop;           -- next: send eop
1214
            -- here handle labo: if labo cmd and babo set, eat rest of list
1215
            elsif r.rcmd(c_rlink_cmd_rbf_code)=c_rlink_cmd_labo and
1216
                  r.babo='1' then
1217
              n.state := sl_rxeop;              -- next: wait for eop
1218
            else
1219
              n.state := sl_rxcmd;              -- next: read command or eop
1220
            end if;
1221 9 wfjm
          end if;
1222 27 wfjm
        else
1223
          n.nakcode := c_rlink_nakcode_rtovfl; -- signal rtbuf ovfl
1224
          n.state := sl_txnak;            -- next: send nak
1225 2 wfjm
        end if;
1226 27 wfjm
 
1227 2 wfjm
      when others => null;              -- <> --------------------------------
1228 27 wfjm
 
1229 2 wfjm
    end case;
1230
 
1231 27 wfjm
    -- addra logic (write pointer)
1232
    if addra_clear = '1' then           -- clear
1233
      n.rtaddra := (others=>'0');
1234
      n.rtaddra_red := '0';
1235
      n.rtaddra_bad := '0';
1236 2 wfjm
    else
1237 27 wfjm
      if irtwea = '1' then                -- inc when write on port a
1238
        if r.rtaddra_red = '1' then         -- if already red
1239
          n. rtaddra_bad := '1';              -- than flag bad
1240
        else                                -- still ok
1241
          n.rtaddra := slv(unsigned(r.rtaddra) + 1);  -- inc
1242
          if r.rtaddra = rtaddr_tred then             -- if inc'ed to red
1243
            n. rtaddra_red := '1';                      -- flag red
1244
          end if;
1245
        end if;
1246
      end if;
1247 2 wfjm
    end if;
1248 27 wfjm
 
1249
    -- addrb logic (write and read pointer)
1250
    if addrb_load = '1' then            -- load
1251
      if addrb_sela = '1' then
1252
        n.rtaddrb := r.rtaddra;
1253
        n.rtaddrb_red := r.rtaddra_red;
1254
        n.rtaddrb_bad := r.rtaddra_bad;
1255
      else
1256
        n.rtaddrb := (others=>'0');
1257
        n.rtaddrb_red := '0';
1258
        n.rtaddrb_bad := '0';
1259
      end if;
1260 2 wfjm
    else
1261 27 wfjm
      if irtreb = '1' or irtweb = '1' then  -- inc when read/write on port b
1262
        if r.rtaddrb_red = '1' then           -- if already red
1263
          n. rtaddrb_bad := '1';                -- than flag bad
1264
        else                                  -- still ok
1265
          n.rtaddrb := slv(unsigned(r.rtaddrb) + 1);  -- inc
1266
          if r.rtaddrb = rtaddr_tred then             -- if inc'ed to red
1267
            n. rtaddrb_red := '1';                      -- flag red
1268
          end if;
1269
        end if;
1270 2 wfjm
      end if;
1271
    end if;
1272
 
1273 27 wfjm
    -- bcnt logic
1274
    if bcnt_load = '1' then
1275
      n.bcnt := bcnt_val;
1276
    else
1277
      if bcnt_dec ='1' then
1278
        n.bcnt := slv(unsigned(r.bcnt) - 1);
1279
      end if;
1280
    end if;
1281 9 wfjm
 
1282 27 wfjm
    N_LREGS <= n;
1283
 
1284
    RL_BUSY_L <= ibusy;
1285
    RL_DO_L   <= ido;
1286
    RL_VAL_L  <= ival;
1287
 
1288 9 wfjm
    RL_MONI.eop  <= r.moneop;
1289
    RL_MONI.attn <= r.monattn;
1290 27 wfjm
    RL_MONI.lamp <= r.arpend;
1291
 
1292
    DOFIFO_HOLD <= idohold;
1293 2 wfjm
 
1294 27 wfjm
    RTBUF_WEA <= irtwea;
1295
    RTBUF_DIA <= ido(d_f_data);
1296
    RTBUF_ENB <= irtreb or irtweb;
1297
    RTBUF_WEB <= irtweb;
1298
    RTBUF_DIB <= idi8;
1299
 
1300 2 wfjm
    CRC_RESET <= crcreset;
1301
    ICRC_ENA  <= icrcena;
1302
    OCRC_ENA  <= ocrcena;
1303 27 wfjm
    OCRC_IN   <= ido(d_f_data);
1304 2 wfjm
 
1305 27 wfjm
    L2B_CMD <= ibcmd;
1306
    L2B_GO  <= ibgo;
1307
 
1308
  end process proc_lnext;
1309
 
1310
  -- bus FSM =================================================================
1311 2 wfjm
 
1312 27 wfjm
  proc_bnext: process (R_BREGS, R_LREGS,
1313
                       RB_STAT, RB_SRES_TOT,
1314
                       DOFIFO_SIZE,
1315
                       L2B_CMD, L2B_GO)
1316
 
1317
    variable r : bregs_type := bregs_init;
1318
    variable n : bregs_type := bregs_init;
1319
 
1320
    variable bto_go : slbit := '0';
1321
    variable bto_end : slbit := '0';
1322
    variable cnt_load : slbit := '0';
1323
    variable cnt_dec  : slbit := '0';
1324
    variable cnt_end  : slbit := '0';
1325
    variable dcnt_clear : slbit := '0';
1326
    variable dcnt_inc   : slbit := '0';
1327
    variable ival   : slbit := '0';
1328
    variable ido    : slv8 := (others=>'0');
1329
    variable iwdone : slbit := '0';
1330
 
1331
  begin
1332
 
1333
    r := R_BREGS;
1334
    n := R_BREGS;
1335
 
1336
    bto_go := '0';                      -- default: keep rbus timeout in reset
1337
    bto_end := '0';
1338
    if unsigned(r.btocnt) = 0 then      -- if rbus timeout count at zero
1339
      bto_end := '1';                   -- signal expiration
1340
    end if;
1341
 
1342
    cnt_load := '0';
1343
    cnt_dec  := '0';
1344
    cnt_end  := '0';
1345
    if unsigned(r.cnt) = 0 then
1346
      cnt_end := '1';
1347
    end if;
1348
 
1349
    dcnt_clear := '0';
1350
    dcnt_inc   := '0';
1351
 
1352
    ival := '0';
1353
    ido  := (others=>'0');
1354
 
1355
    iwdone := '0';
1356
 
1357
    -- FIXME: what is proper almost full limit ?
1358
    if unsigned(DOFIFO_SIZE) >= 28 then   -- almost full
1359
      n.wfifo := '1';
1360
    elsif unsigned(DOFIFO_SIZE) <= 2 then -- almost empty
1361
      n.wfifo := '0';
1362
    end if;
1363
 
1364
    n.rbinit  := '0';                   -- clear rb(init|aval|re|we) by default
1365
    n.rbaval  := '0';                   --   they must always be set by the
1366
    n.rbre    := '0';                   --   'previous state'
1367
    n.rbwe    := '0';                   -- 
1368
 
1369
    case r.state is
1370
 
1371
      when sb_idle =>                   -- sb_idle: wait for cmd ------------
1372
        if L2B_GO = '1' then              -- if cmd seen 
1373
          n.stat := RB_STAT;                -- always latch external status bits
1374 28 wfjm
          n.rbtout := '0';
1375
          n.rbnak  := '0';
1376
          n.rberr  := '0';
1377 27 wfjm
          n.blkabo := '0';
1378
          n.dathpend := '0';
1379
          dcnt_clear := '1';
1380
          cnt_load := '1';
1381
          case L2B_CMD is
1382
            when c_bcmd_stat =>           -- stat ---------------------
1383
              null;                         -- nothing else todo
1384
            when c_bcmd_init =>           -- init ---------------------
1385
              n.rbinit := '1';              -- send init pulse
1386
            when c_bcmd_rblk =>           -- rblk ---------------------
1387
              n.rbaval := '1';              -- start aval chunk
1388
              n.state := sb_rstart;         -- next: start rblk
1389
            when c_bcmd_wblk =>           -- wblk ---------------------
1390
              n.rbaval := '1';              -- start aval chunk
1391
              n.state := sb_wstart;         -- next: start wblk
1392
            when others => null;
1393
          end case;
1394
        end if;
1395
 
1396
      when sb_rstart =>                 -- sb_rstart: start rblk -------------
1397
        n.rbaval := '1';                  -- extend aval
1398
        n.rbre := '1';                    -- start read cycle
1399
        n.state := sb_rreg0;              -- next: do rreg
1400
 
1401
      when sb_rreg0 =>                  -- sb_rreg0: rbus read cycle ---------
1402
        ido  := r.rbdout(f_byte1);
1403
        n.stat := RB_STAT;                -- follow external status bits
1404
        if r.dathpend = '1' then          -- if pending data msb
1405
          ival := '1';
1406
          n.dathpend := '0';
1407
        end if;
1408
        n.rbaval := '1';                  -- extend aval
1409
        bto_go := '1';                    -- activate rbus timeout counter
1410
        if RB_SRES_TOT.err = '1' then       -- latch rbus error flag
1411 28 wfjm
          n.rberr  := '1';
1412 27 wfjm
          n.blkabo := '1';
1413
        end if;
1414
        n.rbdout := RB_SRES_TOT.dout;       -- latch data (follow till valid)
1415
        if RB_SRES_TOT.busy='0' or bto_end='1' then -- wait non-busy or timeout
1416
          if RB_SRES_TOT.busy='1' and bto_end='1' then -- if timeout and busy
1417 28 wfjm
            n.rbtout := '1';                    -- set rbus timeout flag
1418 27 wfjm
            n.blkabo := '1';
1419
          elsif RB_SRES_TOT.ack = '0' then    -- if non-busy and no ack
1420
            n.rbnak := '1';                     -- set rbus nak flag            
1421
            n.blkabo := '1';
1422
          end if;
1423
          cnt_dec := '1';
1424
          n.state := sb_rreg1;              -- next: send data lsb
1425
        else                              -- otherwise rbus read continues
1426
          n.rbre   := '1';                  -- extend read cycle
1427
        end if;
1428
 
1429
      when sb_rreg1 =>                  -- sb_rreg1: send read data ----------
1430
        ido  := r.rbdout(f_byte0);
1431
        ival := '1';                      -- send lsb
1432
        n.dathpend := '1';                -- signal mdb pending
1433
        dcnt_inc := not r.blkabo;         -- inc dcnt if no error
1434
        if cnt_end = '0' then             -- if not yet done
1435
          if r.blkabo = '0' then            -- if no errors
1436
            if r.wfifo = '0' then             -- if fifo fine
1437
              n.rbaval := '1';                  -- extend aval
1438
              n.rbre := '1';                    -- start read cycle
1439
              n.state := sb_rreg0;              -- next: do rreg
1440
            else                              -- fifo is full
1441
              n.state := sb_rwait;              -- next: fifo wait
1442
            end if;
1443
          else                              -- errors seen, rblk abort
1444
            n.state := sb_rabo1;              -- next: send rblk abort msb data
1445
          end if;
1446
        else                              -- all done
1447
          n.state := sb_rend;
1448
        end if;
1449
 
1450
      when sb_rwait =>                  -- sb_rwait: wait for fifo -----------
1451
        if r.wfifo = '0' then             -- if fifo fine
1452
          n.rbaval := '1';                  -- start aval chunk
1453
          n.state := sb_rstart;             -- restart rblk
1454
        end if;
1455
 
1456
      when sb_rend =>                   -- sb_rend: send last read data ------
1457
        ido  := r.rbdout(f_byte1);
1458
        ival := '1';                      -- send msb
1459
        n.dathpend := '0';
1460
        n.state := sb_idle;               -- next: idle
1461
 
1462
      when sb_rabo0 =>                  -- sb_rabo0: rblk abort, lsb data ----
1463
        ido  := (others=>'0');
1464
        ival := '1';
1465
        cnt_dec := '1';
1466
        n.state := sb_rabo1;              -- next: send rblk abort, msb data
1467
 
1468
      when sb_rabo1 =>                  -- sb_rabo1: rblk abort, msb data ----
1469
        ido  := (others=>'0');
1470
        if r.wfifo = '0' then
1471
          n.dathpend := '0';              -- cancel msb pend
1472
          ival := '1';
1473
          if cnt_end = '0' then           -- if not yet done
1474
            n.state := sb_rabo0;            -- next: send rblk abort, lsb data
1475
          else                            -- all done
1476
            n.state := sb_idle;             -- next: idle
1477
          end if;
1478
        end if;
1479
 
1480
      when sb_wstart =>                 -- sb_wstart: start wblk
1481
        n.rbaval := '1';                  -- start aval chunk
1482
        n.rbwe := '1';                    -- start write cycle
1483
        n.state := sb_wreg0;
1484
 
1485
      when sb_wreg0 =>                  -- sb_wreg0: rbus write cycle
1486
        n.stat := RB_STAT;                -- follow external status bits
1487
        n.rbaval := '1';                  -- extend aval
1488
        bto_go := '1';                    -- activate rbus timeout counter
1489
        if RB_SRES_TOT.err = '1' then     -- latch rbus error flag
1490 28 wfjm
          n.rberr  := '1';
1491 27 wfjm
          n.blkabo := '1';
1492
        end if;
1493
        if RB_SRES_TOT.busy='0' or bto_end='1' then -- wait non-busy or timeout
1494
          if RB_SRES_TOT.busy='1' and bto_end='1' then -- if timeout and busy
1495 28 wfjm
            n.rbtout := '1';                     -- set rbus timeout flag
1496 27 wfjm
            n.blkabo := '1';
1497
          elsif RB_SRES_TOT.ack='0' then       -- if non-busy and no ack
1498
            n.rbnak := '1';                      -- set rbus nak flag            
1499
            n.blkabo := '1';
1500
          end if;
1501
          cnt_dec := '1';
1502
          iwdone := '1';
1503
          n.state := sb_wreg1;
1504
        else                              -- otherwise rbus write continues
1505
          n.rbwe   := '1';                  -- extend write cycle
1506
        end if;
1507
 
1508
      when sb_wreg1 =>                  -- sb_wreg1: wait write data
1509
        dcnt_inc := not r.blkabo;         -- inc dcnt if no error
1510
        if cnt_end = '0' then             -- if not yet done
1511
          if r.blkabo = '0' then            -- if no errors
1512
            n.rbaval := '1';                  -- extend aval
1513
            n.rbwe := '1';                    -- start write cycle
1514
            n.state := sb_wreg0;
1515
          else                              -- errors seen, rblk abort
1516
            n.state := sb_wabo0;              -- next: drop wblk rest
1517
          end if;
1518
        else                              -- all done
1519
          n.state := sb_idle;               -- next: idle
1520
        end if;
1521
 
1522
      when sb_wabo0 =>                  -- sb_wabo0: wblk abort, drop data --
1523
        iwdone := '1';                    -- drop data
1524
        cnt_dec := '1';
1525
        n.state := sb_wabo1;              -- next: wblk abort, wair
1526
 
1527
      when sb_wabo1 =>                  -- sb_wabo1: wblk abort, wait --------
1528
        if cnt_end = '0' then             -- if not yet done
1529
          n.state := sb_wabo0;              -- next: wblk abort, drop 
1530
        else                              -- all done
1531
          n.state := sb_idle;               -- next: idle
1532
        end if;
1533
 
1534
      when others => null;              -- <> --------------------------------
1535
 
1536
    end case;
1537
 
1538
    if bto_go = '0' then                -- handle access timeout counter
1539
      n.btocnt := btocnt_init;          -- if bto_go=0, keep in reset
1540
    else
1541
      n.btocnt := slv(unsigned(r.btocnt) - 1);-- otherwise count down
1542
    end if;
1543
 
1544
    if cnt_load = '1' then
1545
      n.cnt := R_LREGS.cnt(cnt_f_dat);
1546
    else
1547
      if cnt_dec ='1' then
1548
        n.cnt := slv(unsigned(r.cnt) - 1);
1549
      end if;
1550
    end if;
1551
 
1552
    if dcnt_clear = '1' then
1553
      n.dcnt := (others=>'0');
1554
    else
1555
      if dcnt_inc ='1' then
1556
        n.dcnt := slv(unsigned(r.dcnt) + 1);
1557
      end if;
1558
    end if;
1559
 
1560
    N_BREGS <= n;
1561
 
1562
    DOFIFO_DI  <= ido;
1563
    DOFIFO_ENA <= ival;
1564
 
1565
    B2L_WDONE <= iwdone;
1566
 
1567
  end process proc_bnext;
1568
 
1569
  -- config rbus iface =======================================================
1570
 
1571
  proc_cnext: process (R_CREGS, R_LREGS, RBSEL, RB_MREQ_L)
1572
 
1573
    variable r : cregs_type := cregs_init;
1574
    variable n : cregs_type := cregs_init;
1575
    variable irb_ack  : slbit := '0';
1576
    variable irb_dout : slv16 := (others=>'0');
1577
 
1578
  begin
1579
 
1580
    r := R_CREGS;
1581
    n := R_CREGS;
1582
 
1583
    irb_ack  := '0';
1584
    irb_dout := (others=>'0');
1585
 
1586
    -- rbus transactions
1587
    if RBSEL = '1' then
1588
      irb_ack := RB_MREQ_L.re or RB_MREQ_L.we;
1589
 
1590
      -- config register writes
1591
      if RB_MREQ_L.we = '1' then
1592
        case RB_MREQ_L.addr(1 downto 0) is
1593
          when rbaddr_cntl =>
1594
            n.anena  := RB_MREQ_L.din(cntl_rbf_anena);
1595
            n.atoena := RB_MREQ_L.din(cntl_rbf_atoena);
1596
            n.atoval := RB_MREQ_L.din(cntl_rbf_atoval);
1597
          when others => null;
1598
        end case;
1599
      end if;
1600
 
1601
      -- rbus output driver
1602
      case RB_MREQ_L.addr(1 downto 0) is
1603
        when rbaddr_cntl =>
1604
          irb_dout(cntl_rbf_anena)  := r.anena;
1605
          irb_dout(cntl_rbf_atoena) := r.atoena;
1606
          irb_dout(cntl_rbf_atoval) := r.atoval;
1607
        when rbaddr_stat =>
1608
          irb_dout(stat_rbf_lcmd)   := R_LREGS.lcmd;
1609
          irb_dout(stat_rbf_babo)   := R_LREGS.babo;
1610
          irb_dout(stat_rbf_arpend) := R_LREGS.arpend;
1611
          irb_dout(stat_rbf_rbsize) := slv(to_unsigned(RTAWIDTH-10,3));
1612
        when rbaddr_id0  =>
1613
          irb_dout := SYSID(15 downto  0);
1614
        when rbaddr_id1  =>
1615
          irb_dout := SYSID(31 downto 16);
1616
        when others => null;
1617
      end case;
1618
 
1619
    end if;
1620
 
1621
    N_CREGS <= n;
1622
 
1623
    RB_SRES_CONF.dout <= irb_dout;
1624
    RB_SRES_CONF.ack  <= irb_ack;
1625
    RB_SRES_CONF.err  <= '0';
1626
    RB_SRES_CONF.busy <= '0';
1627
 
1628
  end process proc_cnext;
1629
 
1630
  -- rbus driver -----------------------------------------------------
1631
 
1632
  proc_mreq: process (R_LREGS, R_BREGS)
1633
  begin
1634
 
1635
    RB_MREQ_L      <= rb_mreq_init;
1636
    RB_MREQ_L.aval <= R_BREGS.rbaval;
1637
    RB_MREQ_L.re   <= R_BREGS.rbre;
1638
    RB_MREQ_L.we   <= R_BREGS.rbwe;
1639
    RB_MREQ_L.init <= R_BREGS.rbinit;
1640
    RB_MREQ_L.addr <= R_LREGS.addr;
1641
    RB_MREQ_L.din  <= R_LREGS.din;
1642
 
1643
  end process proc_mreq;
1644
 
1645
  RB_MREQ <= RB_MREQ_L;
1646
 
1647
  RL_BUSY <= RL_BUSY_L;
1648
  RL_DO   <= RL_DO_L;
1649
  RL_VAL  <= RL_VAL_L;
1650
 
1651
-- synthesis translate_off
1652
 
1653
  RLMON: if ENAPIN_RLMON >= 0  generate
1654
    MON : rlink_mon_sb
1655
      generic map (
1656
        DWIDTH => RL_DI'length,
1657
        ENAPIN => ENAPIN_RLMON)
1658
      port map (
1659
        CLK     => CLK,
1660
        RL_DI   => RL_DI,
1661
        RL_ENA  => RL_ENA,
1662
        RL_BUSY => RL_BUSY_L,
1663
        RL_DO   => RL_DO_L,
1664
        RL_VAL  => RL_VAL_L,
1665
        RL_HOLD => RL_HOLD
1666
      );
1667
  end generate RLMON;
1668
 
1669
  RBMON: if ENAPIN_RBMON >= 0  generate
1670
    MON : rb_mon_sb
1671
      generic map (
1672
        DBASE  => 8,
1673
        ENAPIN => ENAPIN_RBMON)
1674
      port map (
1675
        CLK     => CLK,
1676
        RB_MREQ => RB_MREQ_L,
1677
        RB_SRES => RB_SRES_TOT,
1678
        RB_LAM  => RB_LAM,
1679
        RB_STAT => RB_STAT
1680
      );
1681
  end generate RBMON;
1682
 
1683
-- synthesis translate_on
1684
 
1685 2 wfjm
end syn;

powered by: WebSVN 2.1.0

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