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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.6/] [rtl/] [bplib/] [fx2lib/] [fx2_2fifoctl_ic.vhd] - Blame information for rev 17

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

Line No. Rev Author Line
1 17 wfjm
-- $Id: fx2_2fifoctl_ic.vhd 453 2012-01-15 17:51:18Z mueller $
2
--
3
-- Copyright 2012- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4
--
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
-- Module Name:    fx2_2fifoctl_ic - syn
16
-- Description:    Cypress EZ-USB FX2 driver (2 fifo; int clk)
17
--
18
-- Dependencies:   vlib/xlib/iob_reg_o
19
--                 vlib/xlib/iob_reg_i_gen
20
--                 vlib/xlib/iob_reg_o_gen
21
--                 vlib/xlib/iob_reg_io_gen
22
--                 memlib/fifo_2c_dram
23
--
24
-- Test bench:     -
25
-- Target Devices: generic
26
-- Tool versions:  xst 13.3; ghdl 0.29
27
--
28
-- Synthesized (xst):
29
-- Date         Rev  ise         Target      flop lutl lutm slic t peri
30
-- 2012-01-14   453  13.3   O76x xc3s1200e-4  101  173   64  159 s  8.3/7.4
31
-- 2012-01-08   451  13.3   O76x xc3s1200e-4  110  166   64  163 s  7.5
32
--
33
-- Revision History: 
34
-- Date         Rev Version  Comment
35
-- 2012-01-15   453   1.1    use aempty/afull logic; collapse tx and pe flows
36
-- 2012-01-09   451   1.0    Initial version
37
-- 2012-01-01   448   0.5    First draft 
38
--
39
------------------------------------------------------------------------------
40
 
41
library ieee;
42
use ieee.std_logic_1164.all;
43
use ieee.numeric_std.all;
44
 
45
use work.slvtypes.all;
46
use work.xlib.all;
47
use work.memlib.all;
48
use work.fx2lib.all;
49
 
50
entity fx2_2fifoctl_ic is               -- EZ-USB FX2 driver (2 fifo; int clk)
51
  generic (
52
    RXFAWIDTH : positive :=  5;         -- receive  fifo address width
53
    TXFAWIDTH : positive :=  5;         -- transmit fifo address width
54
    PETOWIDTH : positive :=  7;         -- packet end time-out counter width
55
    CCWIDTH :   positive :=  5;         -- chunk counter width
56
    RXAEMPTY_THRES : natural := 1;      -- threshold for rx aempty flag
57
    TXAFULL_THRES  : natural := 1);     -- threshold for tx afull flag
58
  port (
59
    CLK : in slbit;                     -- clock
60
    RESET : in slbit := '0';            -- reset
61
    RXDATA : out slv8;                  -- receive data out
62
    RXVAL : out slbit;                  -- receive data valid
63
    RXHOLD : in slbit;                  -- receive data hold
64
    RXAEMPTY : out slbit;               -- receive almost empty flag
65
    TXDATA : in slv8;                   -- transmit data in
66
    TXENA : in slbit;                   -- transmit data enable
67
    TXBUSY : out slbit;                 -- transmit data busy
68
    TXAFULL : out slbit;                -- transmit almost full flag
69
    MONI : out fx2ctl_moni_type;        -- monitor port data
70
    I_FX2_IFCLK : in slbit;             -- fx2: interface clock
71
    O_FX2_FIFO : out slv2;              -- fx2: fifo address
72
    I_FX2_FLAG : in slv4;               -- fx2: fifo flags
73
    O_FX2_SLRD_N : out slbit;           -- fx2: read enable    (act.low)
74
    O_FX2_SLWR_N : out slbit;           -- fx2: write enable   (act.low)
75
    O_FX2_SLOE_N : out slbit;           -- fx2: output enable  (act.low)
76
    O_FX2_PKTEND_N : out slbit;         -- fx2: packet end     (act.low)
77
    IO_FX2_DATA : inout slv8            -- fx2: data lines
78
  );
79
end fx2_2fifoctl_ic;
80
 
81
 
82
architecture syn of fx2_2fifoctl_ic is
83
 
84
  constant c_rxfifo : slv2 := c_fifo_ep4;
85
  constant c_txfifo : slv2 := c_fifo_ep6;
86
 
87
  constant c_flag_prog   : integer := 0;
88
  constant c_flag_tx_ff  : integer := 1;
89
  constant c_flag_rx_ef  : integer := 2;
90
  constant c_flag_tx2_ff : integer := 3;
91
 
92
  type state_type is (
93
    s_idle,                             -- s_idle: idle state
94
    s_rxprep0,                          -- s_rxprep0: switch to rx-fifo
95
    s_rxprep1,                          -- s_rxprep1: fifo addr setup
96
    s_rxprep2,                          -- s_rxprep2: wait for flags
97
    s_rxdisp,                           -- s_rxdisp: read, dispatch
98
    s_rxpipe,                           -- s_rxpipe: read, pipe drain
99
    s_txprep0,                          -- s_txprep0: switch to tx-fifo
100
    s_txprep1,                          -- s_txprep1: fifo addr setup
101
    s_txprep2,                          -- s_txprep2: wait for flags
102
    s_txdisp                            -- s_txdisp: write, dispatch
103
  );
104
 
105
  type regs_type is record
106
    state : state_type;                 -- state
107
    petocnt : slv(PETOWIDTH-1 downto 0);  -- pktend time out counter
108
    pepend : slbit;                     -- pktend pending
109
    rxpipe : slbit;                     -- read transaction in flight
110
    ccnt : slv(CCWIDTH-1 downto 0);     -- chunk counter
111
    moni_ep4_sel : slbit;               -- ep4 (rx) select
112
    moni_ep6_sel : slbit;               -- ep6 (tx) select
113
    moni_ep4_pf : slbit;                -- ep4 (rx) prog flag
114
    moni_ep6_pf : slbit;                -- ep6 (tx) prog flag
115
  end record regs_type;
116
 
117
  constant petocnt_init : slv(PETOWIDTH-1 downto 0) := (others=>'0');
118
  constant ccnt_init : slv(CCWIDTH-1 downto 0) := (others=>'0');
119
 
120
  constant regs_init : regs_type := (
121
    s_idle,                             -- state
122
    petocnt_init,                       -- petocnt
123
    '0','0',                            -- pepend,rxpipe
124
    ccnt_init,                          -- ccnt
125
    '0','0',                            -- moni_ep(4|6)_sel
126
    '0','0'                             -- moni_ep(4|6)_pf
127
  );
128
 
129
  signal R_REGS : regs_type := regs_init;  -- state registers
130
  signal N_REGS : regs_type := regs_init;  -- next value state regs
131
 
132
  signal FX2_FIFO     : slv2 := (others=>'0');
133
  signal FX2_FIFO_CE  : slbit := '0';
134
  signal FX2_FLAG_N   : slv4 := (others=>'0');
135
  signal FX2_SLRD_N   : slbit := '1';
136
  signal FX2_SLWR_N   : slbit := '1';
137
  signal FX2_SLOE_N   : slbit := '1';
138
  signal FX2_PKTEND_N : slbit := '1';
139
  signal FX2_DATA_CEI : slbit := '0';
140
  signal FX2_DATA_CEO : slbit := '0';
141
  signal FX2_DATA_OE  : slbit := '0';
142
 
143
  signal RXFIFO_DI  : slv8 := (others=>'0');
144
  signal RXFIFO_ENA  : slbit := '0';
145
  signal RXFIFO_BUSY : slbit := '0';
146
  signal RXSIZE_FX2  : slv(RXFAWIDTH-1 downto 0) := (others=>'0');
147
  signal RXSIZE_USR  : slv(RXFAWIDTH-1 downto 0) := (others=>'0');
148
  signal TXFIFO_DO   : slv8 := (others=>'0');
149
  signal TXFIFO_VAL  : slbit := '0';
150
  signal TXFIFO_HOLD : slbit := '0';
151
  signal TXSIZE_FX2  : slv(TXFAWIDTH-1 downto 0) := (others=>'0');
152
  signal TXSIZE_USR  : slv(TXFAWIDTH-1 downto 0) := (others=>'0');
153
 
154
  signal TXBUSY_L : slbit := '0';
155
 
156
  signal R_MONI_C : fx2ctl_moni_type := fx2ctl_moni_init;
157
  signal R_MONI_S : fx2ctl_moni_type := fx2ctl_moni_init;
158
 
159
begin
160
 
161
  assert RXAEMPTY_THRES<=2**RXFAWIDTH-1 and
162
         TXAFULL_THRES<=2**TXFAWIDTH-1
163
    report "assert((RXAEMPTY|TXAFULL)_THRES <= 2**(RX|TX)FAWIDTH)-1"
164
    severity failure;
165
 
166
 
167
  IOB_FX2_FIFO : iob_reg_o_gen
168
    generic map (
169
      DWIDTH => 2,
170
      INIT   => '0')
171
    port map (
172
      CLK => I_FX2_IFCLK,
173
      CE  => FX2_FIFO_CE,
174
      DO  => FX2_FIFO,
175
      PAD => O_FX2_FIFO
176
    );
177
 
178
  IOB_FX2_FLAG : iob_reg_i_gen
179
    generic map (
180
      DWIDTH => 4,
181
      INIT   => '0')
182
    port map (
183
      CLK => I_FX2_IFCLK,
184
      CE  => '1',
185
      DI  => FX2_FLAG_N,
186
      PAD => I_FX2_FLAG
187
    );
188
 
189
  IOB_FX2_SLRD : iob_reg_o
190
    generic map (
191
      INIT   => '1')
192
    port map (
193
      CLK => I_FX2_IFCLK,
194
      CE  => '1',
195
      DO  => FX2_SLRD_N,
196
      PAD => O_FX2_SLRD_N
197
    );
198
 
199
  IOB_FX2_SLWR : iob_reg_o
200
    generic map (
201
      INIT   => '1')
202
    port map (
203
      CLK => I_FX2_IFCLK,
204
      CE  => '1',
205
      DO  => FX2_SLWR_N,
206
      PAD => O_FX2_SLWR_N
207
    );
208
 
209
  IOB_FX2_SLOE : iob_reg_o
210
    generic map (
211
      INIT   => '1')
212
    port map (
213
      CLK => I_FX2_IFCLK,
214
      CE  => '1',
215
      DO  => FX2_SLOE_N,
216
      PAD => O_FX2_SLOE_N
217
    );
218
 
219
  IOB_FX2_PKTEND : iob_reg_o
220
    generic map (
221
      INIT   => '1')
222
    port map (
223
      CLK => I_FX2_IFCLK,
224
      CE  => '1',
225
      DO  => FX2_PKTEND_N,
226
      PAD => O_FX2_PKTEND_N
227
    );
228
 
229
  IOB_FX2_DATA : iob_reg_io_gen
230
    generic map (
231
      DWIDTH => 8,
232
      PULL   => "KEEP")
233
    port map (
234
      CLK => I_FX2_IFCLK,
235
      CEI => FX2_DATA_CEI,
236
      CEO => FX2_DATA_CEO,
237
      OE  => FX2_DATA_OE,
238
      DI  => RXFIFO_DI,                 -- input data   (read from pad)
239
      DO  => TXFIFO_DO,                 -- output data  (write  to pad)
240
      PAD => IO_FX2_DATA
241
    );
242
 
243
  RXFIFO : fifo_2c_dram                -- input fifo, 2 clock, dram based
244
    generic map (
245
      AWIDTH => RXFAWIDTH,
246
      DWIDTH => 8)
247
    port map (
248
      CLKW   => I_FX2_IFCLK,
249
      CLKR   => CLK,
250
      RESETW => '0',
251
      RESETR => RESET,
252
      DI     => RXFIFO_DI,
253
      ENA    => RXFIFO_ENA,
254
      BUSY   => RXFIFO_BUSY,
255
      DO     => RXDATA,
256
      VAL    => RXVAL,
257
      HOLD   => RXHOLD,
258
      SIZEW  => RXSIZE_FX2,
259
      SIZER  => RXSIZE_USR
260
    );
261
 
262
  TXFIFO : fifo_2c_dram                -- output fifo, 2 clock, dram based
263
    generic map (
264
      AWIDTH => TXFAWIDTH,
265
      DWIDTH => 8)
266
    port map (
267
      CLKW   => CLK,
268
      CLKR   => I_FX2_IFCLK,
269
      RESETW => RESET,
270
      RESETR => '0',
271
      DI     => TXDATA,
272
      ENA    => TXENA,
273
      BUSY   => TXBUSY_L,
274
      DO     => TXFIFO_DO,
275
      VAL    => TXFIFO_VAL,
276
      HOLD   => TXFIFO_HOLD,
277
      SIZEW  => TXSIZE_USR,
278
      SIZER  => TXSIZE_FX2
279
    );
280
 
281
  proc_regs: process (I_FX2_IFCLK)
282
  begin
283
 
284
    if rising_edge(I_FX2_IFCLK) then
285
      if RESET = '1' then
286
        R_REGS <= regs_init;
287
      else
288
        R_REGS <= N_REGS;
289
      end if;
290
    end if;
291
 
292
  end process proc_regs;
293
 
294
  proc_next: process (R_REGS,
295
                      FX2_FLAG_N, TXFIFO_VAL, RXSIZE_FX2,
296
                      RXFIFO_BUSY, TXBUSY_L)
297
 
298
    variable r : regs_type := regs_init;
299
    variable n : regs_type := regs_init;
300
 
301
    variable ififo_ce : slbit := '0';
302
    variable ififo    : slv2 := "00";
303
 
304
    variable irxfifo_ena  : slbit := '0';
305
    variable itxfifo_hold : slbit := '0';
306
 
307
    variable islrd   : slbit := '0';
308
    variable islwr   : slbit := '0';
309
    variable isloe   : slbit := '0';
310
    variable ipktend : slbit := '0';
311
 
312
    variable idata_cei : slbit := '0';
313
    variable idata_ceo : slbit := '0';
314
    variable idata_oe  : slbit := '0';
315
 
316
    variable imoni  : fx2ctl_moni_type := fx2ctl_moni_init;
317
 
318
    variable slrxok : slbit := '0';
319
    variable sltxok : slbit := '0';
320
    variable pipeok : slbit := '0';
321
 
322
    variable cc_clr : slbit := '0';
323
    variable cc_cnt : slbit := '0';
324
    variable cc_done : slbit := '0';
325
 
326
  begin
327
 
328
    r := R_REGS;
329
    n := R_REGS;
330
 
331
    ififo_ce := '0';
332
    ififo    := "00";
333
 
334
    irxfifo_ena  := '0';
335
    itxfifo_hold := '1';
336
 
337
    islrd   := '0';
338
    islwr   := '0';
339
    isloe   := '0';
340
    ipktend := '0';
341
 
342
    idata_cei := '0';
343
    idata_ceo := '0';
344
    idata_oe  := '0';
345
 
346
    imoni := fx2ctl_moni_init;
347
 
348
    slrxok := FX2_FLAG_N(c_flag_rx_ef); -- empty flag is act.low!
349
    sltxok := FX2_FLAG_N(c_flag_tx_ff); --  full flag is act.low!
350
    pipeok := FX2_FLAG_N(c_flag_prog);  -- almost flag is act.low!
351
 
352
    cc_clr := '0';
353
    cc_cnt := '0';
354
    if unsigned(r.ccnt) = 0  then
355
      cc_done := '1';
356
    else
357
      cc_done := '0';
358
    end if;
359
 
360
    case r.state is
361
      when s_idle =>                    -- s_idle:
362
        if slrxok='1' and RXFIFO_BUSY='0' then
363
          ififo_ce := '1';
364
          ififo    := c_rxfifo;
365
          n.state := s_rxprep1;
366
        elsif sltxok='1' and (TXFIFO_VAL='1' or r.pepend='1')then
367
          ififo_ce := '1';
368
          ififo    := c_txfifo;
369
          n.state := s_txprep1;
370
        end if;
371
 
372
      when s_rxprep0 =>                 -- s_rxprep0: switch to rx-fifo
373
        ififo_ce := '1';
374
        ififo    := c_rxfifo;
375
        n.state := s_rxprep1;
376
 
377
      when s_rxprep1 =>                 -- s_rxprep1: fifo addr setup
378
        cc_clr  := '1';
379
        n.state := s_rxprep2;
380
 
381
      when s_rxprep2 =>                 -- s_rxprep2: wait for flags
382
        isloe   := '1';
383
        n.state := s_rxdisp;
384
 
385
      when s_rxdisp =>                  -- s_rxdisp: read, dispatch
386
        isloe := '1';
387
        if r.rxpipe = '1' then            -- read in flight ?
388
          irxfifo_ena := '1';               -- capture rxdata
389
          n.rxpipe := '0';
390
        end if;
391
 
392
        -- if chunk done and tx or pe pending and possible
393
        if cc_done='1' and sltxok='1' and (TXFIFO_VAL='1' or r.pepend='1') then
394
          n.state := s_txprep0;
395
        -- if more rx to do and possible
396
        elsif slrxok='1' and RXFIFO_BUSY='0' then
397
          cc_cnt := '1';
398
          idata_cei := '1';
399
          islrd := '1';
400
          if false and pipeok='1' and unsigned(RXSIZE_FX2)>2 then
401
            n.rxpipe := '1';
402
            n.state := s_rxdisp;
403
          else
404
            n.state := s_rxpipe;
405
          end if;
406
        -- otherwise back to idle
407
        else
408
          n.state  := s_idle;
409
        end if;
410
 
411
      when s_rxpipe =>                  -- s_rxpipe:  read, pipe drain
412
        isloe := '1';
413
        irxfifo_ena := '1';               -- capture rxdata
414
        if pipeok='1' and unsigned(RXSIZE_FX2)>1 then
415
          n.state := s_rxdisp;
416
        else
417
          n.state := s_rxprep2;
418
        end if;
419
 
420
      when s_txprep0 =>                 -- s_txprep0: switch to tx-fifo
421
        ififo_ce := '1';
422
        ififo    := c_txfifo;
423
        n.state := s_txprep1;
424
 
425
      when s_txprep1 =>                 -- s_txprep1: fifo addr setup
426
        cc_clr  := '1';
427
        n.state := s_txprep2;
428
 
429
      when s_txprep2 =>                 -- s_txprep2: wait for flags
430
        n.state := s_txdisp;
431
 
432
      when s_txdisp =>                  -- s_txdisp: write, dispatch
433
        -- if chunk done and rx pending and possible
434
        if cc_done='1' and slrxok='1' and RXFIFO_BUSY='0' then
435
          n.state := s_rxprep0;
436
        -- if pktend to do and possible
437
        elsif sltxok = '1' and r.pepend = '1' then
438
          ipktend  := '1';
439
          n.pepend := '0';
440
          n.state := s_idle;
441
        -- if more tx to do and possible
442
        elsif sltxok = '1' and TXFIFO_VAL = '1' then
443
          cc_cnt := '1';                  -- inc chunk count
444
          n.pepend := '0';                -- cancel pe (avoid back-2-back tx+pe)
445
          itxfifo_hold := '0';
446
          idata_ceo := '1';
447
          idata_oe  := '1';
448
          islwr     := '1';
449
          if pipeok = '1' then           -- if not almost full
450
            n.state   := s_txdisp;          -- stream 
451
          else
452
            n.state   := s_txprep1;         -- wait for full flag
453
          end if;
454
        -- otherwise back to idle
455
        else
456
          n.state := s_idle;
457
        end if;
458
 
459
      when others => null;
460
    end case;
461
 
462
    -- chunk counter handling
463
    if cc_clr = '1' then
464
      n.ccnt := (others=>'1');
465
    elsif cc_cnt='1' and unsigned(r.ccnt) > 0 then
466
      n.ccnt := slv(unsigned(r.ccnt) - 1);
467
    end if;
468
 
469
    -- pktend time-out handling:
470
    --   if tx fifo is non-empty, set counter to max
471
    --   if tx fifo is empty, count down every usec
472
    --   on 1->0 transition queue pktend request
473
    if TXFIFO_VAL = '1' then
474
      n.petocnt := (others=>'1');
475
    else
476
      if unsigned(r.petocnt) /= 0 then
477
        n.petocnt := slv(unsigned(r.petocnt) - 1);
478
        if unsigned(r.petocnt) = 1 then
479
          n.pepend := '1';
480
        end if;
481
      end if;
482
    end if;
483
 
484
    n.moni_ep4_sel := '0';
485
    n.moni_ep6_sel := '0';
486
    if r.state = s_rxdisp or r.state = s_rxpipe then
487
      n.moni_ep4_sel := '1';
488
      n.moni_ep4_pf  := not FX2_FLAG_N(c_flag_prog);
489
    elsif r.state = s_txdisp then
490
      n.moni_ep6_sel := '1';
491
      n.moni_ep6_pf  := not FX2_FLAG_N(c_flag_prog);
492
    end if;
493
 
494
    N_REGS <= n;
495
 
496
    FX2_FIFO_CE  <= ififo_ce;
497
    FX2_FIFO     <= ififo;
498
 
499
    FX2_SLRD_N   <= not islrd;
500
    FX2_SLWR_N   <= not islwr;
501
    FX2_SLOE_N   <= not isloe;
502
    FX2_PKTEND_N <= not ipktend;
503
 
504
    FX2_DATA_CEI <= idata_cei;
505
    FX2_DATA_CEO <= idata_ceo;
506
    FX2_DATA_OE  <= idata_oe;
507
 
508
    RXFIFO_ENA   <= irxfifo_ena;
509
    TXFIFO_HOLD  <= itxfifo_hold;
510
 
511
  end process proc_next;
512
 
513
  proc_moni: process (CLK)
514
  begin
515
 
516
    if rising_edge(CLK) then
517
      if RESET = '1' then
518
        R_MONI_C <= fx2ctl_moni_init;
519
        R_MONI_S <= fx2ctl_moni_init;
520
      else
521
        R_MONI_C <= fx2ctl_moni_init;
522
        R_MONI_C.fifo_ep4        <= R_REGS.moni_ep4_sel;
523
        R_MONI_C.fifo_ep6        <= R_REGS.moni_ep6_sel;
524
        R_MONI_C.flag_ep4_empty  <= not FX2_FLAG_N(c_flag_rx_ef);
525
        R_MONI_C.flag_ep4_almost <= R_REGS.moni_ep4_pf;
526
        R_MONI_C.flag_ep6_full   <= not FX2_FLAG_N(c_flag_tx_ff);
527
        R_MONI_C.flag_ep6_almost <= R_REGS.moni_ep6_pf;
528
        R_MONI_C.slrd            <= not FX2_SLRD_N;
529
        R_MONI_C.slwr            <= not FX2_SLWR_N;
530
        R_MONI_C.pktend          <= not FX2_PKTEND_N;
531
        R_MONI_S <= R_MONI_C;
532
      end if;
533
    end if;
534
 
535
  end process proc_moni;
536
 
537
  proc_almost: process (RXSIZE_USR, TXSIZE_USR)
538
  begin
539
 
540
    -- rxsize_usr is the number of bytes to read
541
    -- txsize_usr is the number of bytes to write
542
 
543
    if unsigned(RXSIZE_USR) <= RXAEMPTY_THRES then
544
      RXAEMPTY <= '1';
545
    else
546
      RXAEMPTY <= '0';
547
    end if;
548
 
549
    if unsigned(TXSIZE_USR) <= TXAFULL_THRES then
550
      TXAFULL <= '1';
551
    else
552
      TXAFULL <= '0';
553
    end if;
554
 
555
  end process proc_almost;
556
 
557
  TXBUSY <= TXBUSY_L;
558
 
559
  MONI <= R_MONI_S;
560
 
561
end syn;

powered by: WebSVN 2.1.0

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