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

Subversion Repositories w11

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /w11/tags/w11a_V0.6/rtl/bplib/fx2lib
    from Rev 19 to Rev 24
    Reverse comparison

Rev 19 → Rev 24

/Makefile
0,0 → 1,26
# $Id: Makefile 477 2013-01-27 14:07:10Z mueller $
#
# Revision History:
# Date Rev Version Comment
# 2011-08-13 405 1.1 use includes from rtl/make
# 2010-05-23 293 1.0 Initial version (cloned..)
#
VBOM_all = $(wildcard *.vbom)
NGC_all = $(VBOM_all:.vbom=.ngc)
#
include $(RETROBASE)/rtl/make/xflow_default_nexys2.mk
#
.PHONY : all clean
#
all : $(NGC_all)
#
clean : ise_clean
#
#----
#
include $(RETROBASE)/rtl/make/generic_xflow.mk
#
ifndef DONTINCDEP
include $(VBOM_all:.vbom=.dep_xst)
endif
#
/fx2_2fifoctl_ic.vhd
0,0 → 1,566
-- $Id: fx2_2fifoctl_ic.vhd 472 2013-01-06 14:39:10Z mueller $
--
-- Copyright 2012-2013 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: fx2_2fifoctl_ic - syn
-- Description: Cypress EZ-USB FX2 driver (2 fifo; int clk)
--
-- Dependencies: vlib/xlib/iob_reg_o
-- vlib/xlib/iob_reg_i_gen
-- vlib/xlib/iob_reg_o_gen
-- vlib/xlib/iob_reg_io_gen
-- memlib/fifo_2c_dram
--
-- Test bench: -
-- Target Devices: generic
-- Tool versions: xst 13.3; ghdl 0.29
--
-- Synthesized (xst):
-- Date Rev ise Target flop lutl lutm slic t peri
-- 2013-01-04 469 13.3 O76x xc3s1200e-4 112 172 64 169 s 7.4/7.4
-- 2012-01-14 453 13.3 O76x xc3s1200e-4 101? 173 64 159 s 8.3/7.4
-- 2012-01-08 451 13.3 O76x xc3s1200e-4 110 166 64 163 s 7.5
--
-- Revision History:
-- Date Rev Version Comment
-- 2013-01-04 469 1.2 BUGFIX: redo rx logic, now properly pipelined
-- 2012-01-15 453 1.1 use aempty/afull logic; collapse tx and pe flows
-- 2012-01-09 451 1.0 Initial version
-- 2012-01-01 448 0.5 First draft
--
------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.slvtypes.all;
use work.xlib.all;
use work.memlib.all;
use work.fx2lib.all;
 
entity fx2_2fifoctl_ic is -- EZ-USB FX2 driver (2 fifo; int clk)
generic (
RXFAWIDTH : positive := 5; -- receive fifo address width
TXFAWIDTH : positive := 5; -- transmit fifo address width
PETOWIDTH : positive := 7; -- packet end time-out counter width
CCWIDTH : positive := 5; -- chunk counter width
RXAEMPTY_THRES : natural := 1; -- threshold for rx aempty flag
TXAFULL_THRES : natural := 1); -- threshold for tx afull flag
port (
CLK : in slbit; -- clock
RESET : in slbit := '0'; -- reset
RXDATA : out slv8; -- receive data out
RXVAL : out slbit; -- receive data valid
RXHOLD : in slbit; -- receive data hold
RXAEMPTY : out slbit; -- receive almost empty flag
TXDATA : in slv8; -- transmit data in
TXENA : in slbit; -- transmit data enable
TXBUSY : out slbit; -- transmit data busy
TXAFULL : out slbit; -- transmit almost full flag
MONI : out fx2ctl_moni_type; -- monitor port data
I_FX2_IFCLK : in slbit; -- fx2: interface clock
O_FX2_FIFO : out slv2; -- fx2: fifo address
I_FX2_FLAG : in slv4; -- fx2: fifo flags
O_FX2_SLRD_N : out slbit; -- fx2: read enable (act.low)
O_FX2_SLWR_N : out slbit; -- fx2: write enable (act.low)
O_FX2_SLOE_N : out slbit; -- fx2: output enable (act.low)
O_FX2_PKTEND_N : out slbit; -- fx2: packet end (act.low)
IO_FX2_DATA : inout slv8 -- fx2: data lines
);
end fx2_2fifoctl_ic;
 
 
architecture syn of fx2_2fifoctl_ic is
 
constant c_rxfifo : slv2 := c_fifo_ep4;
constant c_txfifo : slv2 := c_fifo_ep6;
 
constant c_flag_prog : integer := 0;
constant c_flag_tx_ff : integer := 1;
constant c_flag_rx_ef : integer := 2;
constant c_flag_tx2_ff : integer := 3;
type state_type is (
s_idle, -- s_idle: idle state
s_rxprep0, -- s_rxprep0: switch to rx-fifo
s_rxprep1, -- s_rxprep1: fifo addr setup
s_rxprep2, -- s_rxprep2: wait for flags
s_rxdisp, -- s_rxdisp: read, dispatch
s_rxpipe, -- s_rxpipe: read, pipe wait
s_txprep0, -- s_txprep0: switch to tx-fifo
s_txprep1, -- s_txprep1: fifo addr setup
s_txprep2, -- s_txprep2: wait for flags
s_txdisp -- s_txdisp: write, dispatch
);
type regs_type is record
state : state_type; -- state
petocnt : slv(PETOWIDTH-1 downto 0); -- pktend time out counter
pepend : slbit; -- pktend pending
rxpipe1 : slbit; -- read pipe 1: iob capture stage
rxpipe2 : slbit; -- read pipe 2: fifo write stage
ccnt : slv(CCWIDTH-1 downto 0); -- chunk counter
moni_ep4_sel : slbit; -- ep4 (rx) select
moni_ep6_sel : slbit; -- ep6 (tx) select
moni_ep4_pf : slbit; -- ep4 (rx) prog flag
moni_ep6_pf : slbit; -- ep6 (tx) prog flag
end record regs_type;
 
constant petocnt_init : slv(PETOWIDTH-1 downto 0) := (others=>'0');
constant ccnt_init : slv(CCWIDTH-1 downto 0) := (others=>'0');
 
constant regs_init : regs_type := (
s_idle, -- state
petocnt_init, -- petocnt
'0', -- pepend
'0','0', -- rxpipe1, rxpipe2
ccnt_init, -- ccnt
'0','0', -- moni_ep(4|6)_sel
'0','0' -- moni_ep(4|6)_pf
);
signal R_REGS : regs_type := regs_init; -- state registers
signal N_REGS : regs_type := regs_init; -- next value state regs
 
signal FX2_FIFO : slv2 := (others=>'0');
signal FX2_FIFO_CE : slbit := '0';
signal FX2_FLAG_N : slv4 := (others=>'0');
signal FX2_SLRD_N : slbit := '1';
signal FX2_SLWR_N : slbit := '1';
signal FX2_SLOE_N : slbit := '1';
signal FX2_PKTEND_N : slbit := '1';
signal FX2_DATA_CEI : slbit := '0';
signal FX2_DATA_CEO : slbit := '0';
signal FX2_DATA_OE : slbit := '0';
 
signal RXFIFO_DI : slv8 := (others=>'0');
signal RXFIFO_ENA : slbit := '0';
signal RXFIFO_BUSY : slbit := '0';
signal RXSIZE_FX2 : slv(RXFAWIDTH-1 downto 0) := (others=>'0');
signal RXSIZE_USR : slv(RXFAWIDTH-1 downto 0) := (others=>'0');
signal TXFIFO_DO : slv8 := (others=>'0');
signal TXFIFO_VAL : slbit := '0';
signal TXFIFO_HOLD : slbit := '0';
signal TXSIZE_FX2 : slv(TXFAWIDTH-1 downto 0) := (others=>'0');
signal TXSIZE_USR : slv(TXFAWIDTH-1 downto 0) := (others=>'0');
 
signal TXBUSY_L : slbit := '0';
 
signal R_MONI_C : fx2ctl_moni_type := fx2ctl_moni_init;
signal R_MONI_S : fx2ctl_moni_type := fx2ctl_moni_init;
 
begin
 
assert RXAEMPTY_THRES<=2**RXFAWIDTH-1 and
TXAFULL_THRES<=2**TXFAWIDTH-1
report "assert((RXAEMPTY|TXAFULL)_THRES <= 2**(RX|TX)FAWIDTH)-1"
severity failure;
 
 
IOB_FX2_FIFO : iob_reg_o_gen
generic map (
DWIDTH => 2,
INIT => '0')
port map (
CLK => I_FX2_IFCLK,
CE => FX2_FIFO_CE,
DO => FX2_FIFO,
PAD => O_FX2_FIFO
);
IOB_FX2_FLAG : iob_reg_i_gen
generic map (
DWIDTH => 4,
INIT => '0')
port map (
CLK => I_FX2_IFCLK,
CE => '1',
DI => FX2_FLAG_N,
PAD => I_FX2_FLAG
);
IOB_FX2_SLRD : iob_reg_o
generic map (
INIT => '1')
port map (
CLK => I_FX2_IFCLK,
CE => '1',
DO => FX2_SLRD_N,
PAD => O_FX2_SLRD_N
);
IOB_FX2_SLWR : iob_reg_o
generic map (
INIT => '1')
port map (
CLK => I_FX2_IFCLK,
CE => '1',
DO => FX2_SLWR_N,
PAD => O_FX2_SLWR_N
);
IOB_FX2_SLOE : iob_reg_o
generic map (
INIT => '1')
port map (
CLK => I_FX2_IFCLK,
CE => '1',
DO => FX2_SLOE_N,
PAD => O_FX2_SLOE_N
);
IOB_FX2_PKTEND : iob_reg_o
generic map (
INIT => '1')
port map (
CLK => I_FX2_IFCLK,
CE => '1',
DO => FX2_PKTEND_N,
PAD => O_FX2_PKTEND_N
);
 
IOB_FX2_DATA : iob_reg_io_gen
generic map (
DWIDTH => 8,
PULL => "KEEP")
port map (
CLK => I_FX2_IFCLK,
CEI => FX2_DATA_CEI,
CEO => FX2_DATA_CEO,
OE => FX2_DATA_OE,
DI => RXFIFO_DI, -- input data (read from pad)
DO => TXFIFO_DO, -- output data (write to pad)
PAD => IO_FX2_DATA
);
 
RXFIFO : fifo_2c_dram -- input fifo, 2 clock, dram based
generic map (
AWIDTH => RXFAWIDTH,
DWIDTH => 8)
port map (
CLKW => I_FX2_IFCLK,
CLKR => CLK,
RESETW => '0',
RESETR => RESET,
DI => RXFIFO_DI,
ENA => RXFIFO_ENA,
BUSY => RXFIFO_BUSY,
DO => RXDATA,
VAL => RXVAL,
HOLD => RXHOLD,
SIZEW => RXSIZE_FX2,
SIZER => RXSIZE_USR
);
 
TXFIFO : fifo_2c_dram -- output fifo, 2 clock, dram based
generic map (
AWIDTH => TXFAWIDTH,
DWIDTH => 8)
port map (
CLKW => CLK,
CLKR => I_FX2_IFCLK,
RESETW => RESET,
RESETR => '0',
DI => TXDATA,
ENA => TXENA,
BUSY => TXBUSY_L,
DO => TXFIFO_DO,
VAL => TXFIFO_VAL,
HOLD => TXFIFO_HOLD,
SIZEW => TXSIZE_USR,
SIZER => TXSIZE_FX2
);
proc_regs: process (I_FX2_IFCLK)
begin
 
if rising_edge(I_FX2_IFCLK) then
if RESET = '1' then
R_REGS <= regs_init;
else
R_REGS <= N_REGS;
end if;
end if;
 
end process proc_regs;
 
proc_next: process (R_REGS,
FX2_FLAG_N, TXFIFO_VAL, RXSIZE_FX2,
RXFIFO_BUSY, TXBUSY_L)
 
variable r : regs_type := regs_init;
variable n : regs_type := regs_init;
 
variable ififo_ce : slbit := '0';
variable ififo : slv2 := "00";
 
variable irxfifo_ena : slbit := '0';
variable itxfifo_hold : slbit := '0';
 
variable islrd : slbit := '0';
variable islwr : slbit := '0';
variable isloe : slbit := '0';
variable ipktend : slbit := '0';
 
variable idata_cei : slbit := '0';
variable idata_ceo : slbit := '0';
variable idata_oe : slbit := '0';
 
variable slrxok : slbit := '0';
variable sltxok : slbit := '0';
variable pipeok : slbit := '0';
 
variable cc_clr : slbit := '0';
variable cc_cnt : slbit := '0';
variable cc_done : slbit := '0';
begin
 
r := R_REGS;
n := R_REGS;
 
ififo_ce := '0';
ififo := "00";
 
irxfifo_ena := '0';
itxfifo_hold := '1';
islrd := '0';
islwr := '0';
isloe := '0';
ipktend := '0';
 
idata_cei := '0';
idata_ceo := '0';
idata_oe := '0';
 
slrxok := FX2_FLAG_N(c_flag_rx_ef); -- empty flag is act.low!
sltxok := FX2_FLAG_N(c_flag_tx_ff); -- full flag is act.low!
pipeok := FX2_FLAG_N(c_flag_prog); -- almost flag is act.low!
 
cc_clr := '0';
cc_cnt := '0';
if unsigned(r.ccnt) = 0 then
cc_done := '1';
else
cc_done := '0';
end if;
 
n.rxpipe1 := '0';
case r.state is
when s_idle => -- s_idle:
if slrxok='1' and RXFIFO_BUSY='0' then
ififo_ce := '1';
ififo := c_rxfifo;
n.state := s_rxprep1;
elsif sltxok='1' and (TXFIFO_VAL='1' or r.pepend='1')then
ififo_ce := '1';
ififo := c_txfifo;
n.state := s_txprep1;
end if;
 
when s_rxprep0 => -- s_rxprep0: switch to rx-fifo
ififo_ce := '1';
ififo := c_rxfifo;
n.state := s_rxprep1;
 
when s_rxprep1 => -- s_rxprep1: fifo addr setup
cc_clr := '1';
n.state := s_rxprep2;
 
when s_rxprep2 => -- s_rxprep2: wait for flags
isloe := '1';
n.state := s_rxdisp;
 
when s_rxdisp => -- s_rxdisp: read, dispatch
isloe := '1';
-- if chunk done and tx or pe pending and possible
if cc_done='1' and sltxok='1' and (TXFIFO_VAL='1' or r.pepend='1') then
if r.rxpipe1='1' or r.rxpipe2='1' then -- rx pipe busy ?
n.state := s_rxdisp; -- wait
else
n.state := s_txprep0; -- otherwise switch to tx flow
end if;
-- if more rx to do and possible
elsif slrxok='1' and unsigned(RXSIZE_FX2)>3 then -- !thres must be >3!
islrd := '1';
cc_cnt := '1';
n.rxpipe1 := '1';
if pipeok='1' then
n.state := s_rxdisp; -- 1 cycle read
--n.state := s_rxprep2; -- 2 cycle read
else
n.state := s_rxpipe;
end if;
-- otherwise back to idle
else
if r.rxpipe1='1' or r.rxpipe2='1' then -- rx pipe busy ?
n.state := s_rxdisp; -- wait
else
n.state := s_idle; -- to idle
end if;
end if;
 
when s_rxpipe => -- s_rxpipe: read, pipe wait
isloe := '1';
n.state := s_rxprep2;
when s_txprep0 => -- s_txprep0: switch to tx-fifo
ififo_ce := '1';
ififo := c_txfifo;
n.state := s_txprep1;
 
when s_txprep1 => -- s_txprep1: fifo addr setup
cc_clr := '1';
n.state := s_txprep2;
 
when s_txprep2 => -- s_txprep2: wait for flags
n.state := s_txdisp;
 
when s_txdisp => -- s_txdisp: write, dispatch
-- if chunk done and rx pending and possible
if cc_done='1' and slrxok='1' and RXFIFO_BUSY='0' then
n.state := s_rxprep0;
-- if pktend to do and possible
elsif sltxok = '1' and r.pepend = '1' then
ipktend := '1';
n.pepend := '0';
n.state := s_idle;
-- if more tx to do and possible
elsif sltxok = '1' and TXFIFO_VAL = '1' then
cc_cnt := '1'; -- inc chunk count
n.pepend := '0'; -- cancel pe (avoid back-2-back tx+pe)
itxfifo_hold := '0';
idata_ceo := '1';
idata_oe := '1';
islwr := '1';
if pipeok = '1' then -- if not almost full
n.state := s_txdisp; -- stream
else
n.state := s_txprep1; -- wait for full flag
end if;
-- otherwise back to idle
else
n.state := s_idle;
end if;
when others => null;
end case;
 
-- rx pipe handling
idata_cei := r.rxpipe1;
n.rxpipe2 := r.rxpipe1;
irxfifo_ena := r.rxpipe2;
-- chunk counter handling
if cc_clr = '1' then
n.ccnt := (others=>'1');
elsif cc_cnt='1' and unsigned(r.ccnt) > 0 then
n.ccnt := slv(unsigned(r.ccnt) - 1);
end if;
-- pktend time-out handling:
-- if tx fifo is non-empty, set counter to max
-- if tx fifo is empty, count down every usec
-- on 1->0 transition queue pktend request
if TXFIFO_VAL = '1' then
n.petocnt := (others=>'1');
else
if unsigned(r.petocnt) /= 0 then
n.petocnt := slv(unsigned(r.petocnt) - 1);
if unsigned(r.petocnt) = 1 then
n.pepend := '1';
end if;
end if;
end if;
 
n.moni_ep4_sel := '0';
n.moni_ep6_sel := '0';
if r.state = s_rxdisp or r.state = s_rxpipe then
n.moni_ep4_sel := '1';
n.moni_ep4_pf := not FX2_FLAG_N(c_flag_prog);
elsif r.state = s_txdisp then
n.moni_ep6_sel := '1';
n.moni_ep6_pf := not FX2_FLAG_N(c_flag_prog);
end if;
 
N_REGS <= n;
 
FX2_FIFO_CE <= ififo_ce;
FX2_FIFO <= ififo;
 
FX2_SLRD_N <= not islrd;
FX2_SLWR_N <= not islwr;
FX2_SLOE_N <= not isloe;
FX2_PKTEND_N <= not ipktend;
 
FX2_DATA_CEI <= idata_cei;
FX2_DATA_CEO <= idata_ceo;
FX2_DATA_OE <= idata_oe;
 
RXFIFO_ENA <= irxfifo_ena;
TXFIFO_HOLD <= itxfifo_hold;
end process proc_next;
 
proc_moni: process (CLK)
begin
 
if rising_edge(CLK) then
if RESET = '1' then
R_MONI_C <= fx2ctl_moni_init;
R_MONI_S <= fx2ctl_moni_init;
else
R_MONI_C <= fx2ctl_moni_init;
R_MONI_C.fifo_ep4 <= R_REGS.moni_ep4_sel;
R_MONI_C.fifo_ep6 <= R_REGS.moni_ep6_sel;
R_MONI_C.flag_ep4_empty <= not FX2_FLAG_N(c_flag_rx_ef);
R_MONI_C.flag_ep4_almost <= R_REGS.moni_ep4_pf;
R_MONI_C.flag_ep6_full <= not FX2_FLAG_N(c_flag_tx_ff);
R_MONI_C.flag_ep6_almost <= R_REGS.moni_ep6_pf;
R_MONI_C.slrd <= not FX2_SLRD_N;
R_MONI_C.slwr <= not FX2_SLWR_N;
R_MONI_C.pktend <= not FX2_PKTEND_N;
R_MONI_S <= R_MONI_C;
end if;
end if;
 
end process proc_moni;
 
proc_almost: process (RXSIZE_USR, TXSIZE_USR)
begin
 
-- rxsize_usr is the number of bytes to read
-- txsize_usr is the number of bytes to write
if unsigned(RXSIZE_USR) <= RXAEMPTY_THRES then
RXAEMPTY <= '1';
else
RXAEMPTY <= '0';
end if;
 
if unsigned(TXSIZE_USR) <= TXAFULL_THRES then
TXAFULL <= '1';
else
TXAFULL <= '0';
end if;
 
end process proc_almost;
 
TXBUSY <= TXBUSY_L;
 
MONI <= R_MONI_S;
end syn;
/fx2_3fifoctl_ic.vhd
0,0 → 1,699
-- $Id: fx2_3fifoctl_ic.vhd 472 2013-01-06 14:39:10Z mueller $
--
-- Copyright 2012-2013 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: fx2_3fifoctl_ic - syn
-- Description: Cypress EZ-USB FX2 driver (3 fifo; int clk)
--
-- Dependencies: vlib/xlib/iob_reg_o
-- vlib/xlib/iob_reg_i_gen
-- vlib/xlib/iob_reg_o_gen
-- vlib/xlib/iob_reg_io_gen
-- memlib/fifo_2c_dram
--
-- Test bench: -
-- Target Devices: generic
-- Tool versions: xst 13.3; ghdl 0.29
--
-- Synthesized (xst):
-- Date Rev ise Target flop lutl lutm slic t peri
-- 2012-01-15 453 13.3 O76x xc3s1200e-4 157 265 96 243 s 7.7/7.4
-- 2012-01-15 453 13.3 O76x xc3s1200e-4 156 259 96 238 s 7.9/7.5
--
-- Revision History:
-- Date Rev Version Comment
-- 2013-01-04 469 1.1 BUGFIX: redo rx logic, now properly pipelined
-- 2012-01-09 453 1.0 Initial version (derived from 2fifo_ic)
--
------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.slvtypes.all;
use work.xlib.all;
use work.memlib.all;
use work.fx2lib.all;
 
entity fx2_3fifoctl_ic is -- EZ-USB FX2 driver (3 fifo; int clk)
generic (
RXFAWIDTH : positive := 5; -- receive fifo address width
TXFAWIDTH : positive := 5; -- transmit fifo address width
PETOWIDTH : positive := 7; -- packet end time-out counter width
CCWIDTH : positive := 5; -- chunk counter width
RXAEMPTY_THRES : natural := 1; -- threshold for rx aempty flag
TXAFULL_THRES : natural := 1; -- threshold for tx afull flag
TX2AFULL_THRES : natural := 1); -- threshold for tx2 afull flag
port (
CLK : in slbit; -- clock
RESET : in slbit := '0'; -- reset
RXDATA : out slv8; -- receive data out
RXVAL : out slbit; -- receive data valid
RXHOLD : in slbit; -- receive data hold
RXAEMPTY : out slbit; -- receive almost empty flag
TXDATA : in slv8; -- transmit 1 data in
TXENA : in slbit; -- transmit 1 data enable
TXBUSY : out slbit; -- transmit 1 data busy
TXAFULL : out slbit; -- transmit 1 almost full flag
TX2DATA : in slv8; -- transmit 2 data in
TX2ENA : in slbit; -- transmit 2 data enable
TX2BUSY : out slbit; -- transmit 2 data busy
TX2AFULL : out slbit; -- transmit 2 almost full flag
MONI : out fx2ctl_moni_type; -- monitor port data
I_FX2_IFCLK : in slbit; -- fx2: interface clock
O_FX2_FIFO : out slv2; -- fx2: fifo address
I_FX2_FLAG : in slv4; -- fx2: fifo flags
O_FX2_SLRD_N : out slbit; -- fx2: read enable (act.low)
O_FX2_SLWR_N : out slbit; -- fx2: write enable (act.low)
O_FX2_SLOE_N : out slbit; -- fx2: output enable (act.low)
O_FX2_PKTEND_N : out slbit; -- fx2: packet end (act.low)
IO_FX2_DATA : inout slv8 -- fx2: data lines
);
end fx2_3fifoctl_ic;
 
 
architecture syn of fx2_3fifoctl_ic is
 
constant c_rxfifo : slv2 := c_fifo_ep4;
constant c_txfifo : slv2 := c_fifo_ep6;
constant c_tx2fifo: slv2 := c_fifo_ep8;
 
constant c_flag_prog : integer := 0;
constant c_flag_tx_ff : integer := 1;
constant c_flag_rx_ef : integer := 2;
constant c_flag_tx2_ff : integer := 3;
type state_type is (
s_idle, -- s_idle: idle state
s_rxprep0, -- s_rxprep0: switch to rx-fifo
s_rxprep1, -- s_rxprep1: fifo addr setup
s_rxprep2, -- s_rxprep2: wait for flags
s_rxdisp, -- s_rxdisp: read, dispatch
s_rxpipe, -- s_rxpipe: read, pipe wait
s_txprep0, -- s_txprep0: switch to tx-fifo
s_txprep1, -- s_txprep1: fifo addr setup
s_txprep2, -- s_txprep2: wait for flags
s_txdisp, -- s_txdisp: write, dispatch
s_tx2prep0, -- s_tx2prep0: switch to tx2-fifo
s_tx2prep1, -- s_tx2prep1: fifo addr setup
s_tx2prep2, -- s_tx2prep2: wait for flags
s_tx2disp -- s_tx2disp: write, dispatch
);
type regs_type is record
state : state_type; -- state
petocnt : slv(PETOWIDTH-1 downto 0); -- pktend 1 time out counter
pe2tocnt : slv(PETOWIDTH-1 downto 0); -- pktend 2 time out counter
pepend : slbit; -- pktend 1 pending
pe2pend : slbit; -- pktend 2 pending
rxpipe1 : slbit; -- read pipe 1: iob capture stage
rxpipe2 : slbit; -- read pipe 2: fifo write stage
ccnt : slv(CCWIDTH-1 downto 0); -- chunk counter
moni_ep4_sel : slbit; -- ep4 (rx) select
moni_ep6_sel : slbit; -- ep6 (tx) select
moni_ep8_sel : slbit; -- ep8 (tx2) select
moni_ep4_pf : slbit; -- ep4 (rx) prog flag
moni_ep6_pf : slbit; -- ep6 (tx) prog flag
moni_ep8_pf : slbit; -- ep8 (tx2) prog flag
end record regs_type;
 
constant petocnt_init : slv(PETOWIDTH-1 downto 0) := (others=>'0');
constant ccnt_init : slv(CCWIDTH-1 downto 0) := (others=>'0');
 
constant regs_init : regs_type := (
s_idle, -- state
petocnt_init, -- petocnt
petocnt_init, -- pe2tocnt
'0','0', -- pepend,pe2pend
'0','0', -- rxpipe1, rxpipe2
ccnt_init, -- ccnt
'0','0','0', -- moni_ep(4|6|8)_sel
'0','0','0' -- moni_ep(4|6|8)_pf
);
signal R_REGS : regs_type := regs_init; -- state registers
signal N_REGS : regs_type := regs_init; -- next value state regs
 
signal FX2_FIFO : slv2 := (others=>'0');
signal FX2_FIFO_CE : slbit := '0';
signal FX2_FLAG_N : slv4 := (others=>'0');
signal FX2_SLRD_N : slbit := '1';
signal FX2_SLWR_N : slbit := '1';
signal FX2_SLOE_N : slbit := '1';
signal FX2_PKTEND_N : slbit := '1';
signal FX2_DATA_CEI : slbit := '0';
signal FX2_DATA_CEO : slbit := '0';
signal FX2_DATA_OE : slbit := '0';
signal FX2_DATA_DO : slv8 := (others=>'0');
 
signal RXFIFO_DI : slv8 := (others=>'0');
signal RXFIFO_ENA : slbit := '0';
signal RXFIFO_BUSY : slbit := '0';
signal RXSIZE_FX2 : slv(RXFAWIDTH-1 downto 0) := (others=>'0');
signal RXSIZE_USR : slv(RXFAWIDTH-1 downto 0) := (others=>'0');
signal TXFIFO_DO : slv8 := (others=>'0');
signal TXFIFO_VAL : slbit := '0';
signal TXFIFO_HOLD : slbit := '0';
signal TXSIZE_FX2 : slv(TXFAWIDTH-1 downto 0) := (others=>'0');
signal TXSIZE_USR : slv(TXFAWIDTH-1 downto 0) := (others=>'0');
signal TX2FIFO_DO : slv8 := (others=>'0');
signal TX2FIFO_VAL : slbit := '0';
signal TX2FIFO_HOLD : slbit := '0';
signal TX2SIZE_FX2 : slv(TXFAWIDTH-1 downto 0) := (others=>'0');
signal TX2SIZE_USR : slv(TXFAWIDTH-1 downto 0) := (others=>'0');
 
signal TXBUSY_L : slbit := '0';
signal TX2BUSY_L : slbit := '0';
 
signal R_MONI_C : fx2ctl_moni_type := fx2ctl_moni_init;
signal R_MONI_S : fx2ctl_moni_type := fx2ctl_moni_init;
 
begin
 
assert RXAEMPTY_THRES<=2**RXFAWIDTH-1 and
TXAFULL_THRES<=2**TXFAWIDTH-1 and
TX2AFULL_THRES<=2**TXFAWIDTH-1
report "assert((RXAEMPTY|TXAFULL|TX2AFULL)_THRES <= 2**(RX|TX)FAWIDTH)-1"
severity failure;
 
 
IOB_FX2_FIFO : iob_reg_o_gen
generic map (
DWIDTH => 2,
INIT => '0')
port map (
CLK => I_FX2_IFCLK,
CE => FX2_FIFO_CE,
DO => FX2_FIFO,
PAD => O_FX2_FIFO
);
IOB_FX2_FLAG : iob_reg_i_gen
generic map (
DWIDTH => 4,
INIT => '0')
port map (
CLK => I_FX2_IFCLK,
CE => '1',
DI => FX2_FLAG_N,
PAD => I_FX2_FLAG
);
IOB_FX2_SLRD : iob_reg_o
generic map (
INIT => '1')
port map (
CLK => I_FX2_IFCLK,
CE => '1',
DO => FX2_SLRD_N,
PAD => O_FX2_SLRD_N
);
IOB_FX2_SLWR : iob_reg_o
generic map (
INIT => '1')
port map (
CLK => I_FX2_IFCLK,
CE => '1',
DO => FX2_SLWR_N,
PAD => O_FX2_SLWR_N
);
IOB_FX2_SLOE : iob_reg_o
generic map (
INIT => '1')
port map (
CLK => I_FX2_IFCLK,
CE => '1',
DO => FX2_SLOE_N,
PAD => O_FX2_SLOE_N
);
IOB_FX2_PKTEND : iob_reg_o
generic map (
INIT => '1')
port map (
CLK => I_FX2_IFCLK,
CE => '1',
DO => FX2_PKTEND_N,
PAD => O_FX2_PKTEND_N
);
 
IOB_FX2_DATA : iob_reg_io_gen
generic map (
DWIDTH => 8,
PULL => "KEEP")
port map (
CLK => I_FX2_IFCLK,
CEI => FX2_DATA_CEI,
CEO => FX2_DATA_CEO,
OE => FX2_DATA_OE,
DI => RXFIFO_DI, -- input data (read from pad)
DO => FX2_DATA_DO, -- output data (write to pad)
PAD => IO_FX2_DATA
);
 
RXFIFO : fifo_2c_dram -- input fifo, 2 clock, dram based
generic map (
AWIDTH => RXFAWIDTH,
DWIDTH => 8)
port map (
CLKW => I_FX2_IFCLK,
CLKR => CLK,
RESETW => '0',
RESETR => RESET,
DI => RXFIFO_DI,
ENA => RXFIFO_ENA,
BUSY => RXFIFO_BUSY,
DO => RXDATA,
VAL => RXVAL,
HOLD => RXHOLD,
SIZEW => RXSIZE_FX2,
SIZER => RXSIZE_USR
);
 
TXFIFO : fifo_2c_dram -- output fifo, 2 clock, dram based
generic map (
AWIDTH => TXFAWIDTH,
DWIDTH => 8)
port map (
CLKW => CLK,
CLKR => I_FX2_IFCLK,
RESETW => RESET,
RESETR => '0',
DI => TXDATA,
ENA => TXENA,
BUSY => TXBUSY_L,
DO => TXFIFO_DO,
VAL => TXFIFO_VAL,
HOLD => TXFIFO_HOLD,
SIZEW => TXSIZE_USR,
SIZER => TXSIZE_FX2
);
TX2FIFO : fifo_2c_dram -- output 2 fifo, 2 clock, dram based
generic map (
AWIDTH => TXFAWIDTH,
DWIDTH => 8)
port map (
CLKW => CLK,
CLKR => I_FX2_IFCLK,
RESETW => RESET,
RESETR => '0',
DI => TX2DATA,
ENA => TX2ENA,
BUSY => TX2BUSY_L,
DO => TX2FIFO_DO,
VAL => TX2FIFO_VAL,
HOLD => TX2FIFO_HOLD,
SIZEW => TX2SIZE_USR,
SIZER => TX2SIZE_FX2
);
proc_regs: process (I_FX2_IFCLK)
begin
 
if rising_edge(I_FX2_IFCLK) then
if RESET = '1' then
R_REGS <= regs_init;
else
R_REGS <= N_REGS;
end if;
end if;
 
end process proc_regs;
 
proc_next: process (R_REGS,
FX2_FLAG_N, TXFIFO_VAL, TX2FIFO_VAL,
TXFIFO_DO, TX2FIFO_DO,
RXSIZE_FX2, RXFIFO_BUSY, TXBUSY_L, TX2BUSY_L)
 
variable r : regs_type := regs_init;
variable n : regs_type := regs_init;
 
variable ififo_ce : slbit := '0';
variable ififo : slv2 := "00";
 
variable irxfifo_ena : slbit := '0';
variable itxfifo_hold : slbit := '0';
variable itx2fifo_hold : slbit := '0';
 
variable islrd : slbit := '0';
variable islwr : slbit := '0';
variable isloe : slbit := '0';
variable ipktend : slbit := '0';
 
variable idata_cei : slbit := '0';
variable idata_ceo : slbit := '0';
variable idata_oe : slbit := '0';
variable idata_do : slv8 := (others=>'0');
 
variable slrxok : slbit := '0';
variable sltxok : slbit := '0';
variable sltx2ok : slbit := '0';
variable pipeok : slbit := '0';
 
variable cc_clr : slbit := '0';
variable cc_cnt : slbit := '0';
variable cc_done : slbit := '0';
begin
 
r := R_REGS;
n := R_REGS;
 
ififo_ce := '0';
ififo := "00";
 
irxfifo_ena := '0';
itxfifo_hold := '1';
itx2fifo_hold := '1';
islrd := '0';
islwr := '0';
isloe := '0';
ipktend := '0';
 
idata_cei := '0';
idata_ceo := '0';
idata_oe := '0';
idata_do := TXFIFO_DO;
 
slrxok := FX2_FLAG_N(c_flag_rx_ef); -- empty flag is act.low!
sltxok := FX2_FLAG_N(c_flag_tx_ff); -- full flag is act.low!
sltx2ok := FX2_FLAG_N(c_flag_tx2_ff); -- full flag is act.low!
pipeok := FX2_FLAG_N(c_flag_prog); -- almost flag is act.low!
 
cc_clr := '0';
cc_cnt := '0';
if unsigned(r.ccnt) = 0 then
cc_done := '1';
else
cc_done := '0';
end if;
n.rxpipe1 := '0';
 
case r.state is
when s_idle => -- s_idle:
if slrxok='1' and RXFIFO_BUSY='0' then
ififo_ce := '1';
ififo := c_rxfifo;
n.state := s_rxprep1;
elsif sltxok='1' and (TXFIFO_VAL='1' or r.pepend='1')then
ififo_ce := '1';
ififo := c_txfifo;
n.state := s_txprep1;
elsif sltx2ok='1' and (TX2FIFO_VAL='1' or r.pe2pend='1')then
ififo_ce := '1';
ififo := c_tx2fifo;
n.state := s_tx2prep1;
end if;
 
when s_rxprep0 => -- s_rxprep0: switch to rx-fifo
ififo_ce := '1';
ififo := c_rxfifo;
n.state := s_rxprep1;
 
when s_rxprep1 => -- s_rxprep1: fifo addr setup
cc_clr := '1';
n.state := s_rxprep2;
 
when s_rxprep2 => -- s_rxprep2: wait for flags
isloe := '1';
n.state := s_rxdisp;
 
when s_rxdisp => -- s_rxdisp: read, dispatch
isloe := '1';
-- if chunk done and tx or pe pending and possible
if cc_done='1' and sltxok='1' and (TXFIFO_VAL='1' or r.pepend='1') then
if r.rxpipe1='1' or r.rxpipe2='1' then -- rx pipe busy ?
n.state := s_rxdisp; -- wait
else
n.state := s_txprep0; -- otherwise switch to tx flow
end if;
-- if chunk done and tx2 or pe2 pending and possible
elsif cc_done='1' and sltx2ok='1' and (TX2FIFO_VAL='1' or r.pe2pend='1')
then
if r.rxpipe1='1' or r.rxpipe2='1' then -- rx pipe busy ?
n.state := s_rxdisp; -- wait
else
n.state := s_tx2prep0;
end if;
-- if more rx to do and possible
elsif slrxok='1' and unsigned(RXSIZE_FX2)>3 then -- !thres must be >3!
islrd := '1';
cc_cnt := '1';
n.rxpipe1 := '1';
if pipeok='1' then
n.state := s_rxdisp; -- 1 cycle read
--n.state := s_rxprep2; -- 2 cycle read
else
n.state := s_rxpipe;
end if;
-- otherwise back to idle
else
if r.rxpipe1='1' or r.rxpipe2='1' then -- rx pipe busy ?
n.state := s_rxdisp; -- wait
else
n.state := s_idle; -- to idle
end if;
end if;
 
when s_rxpipe => -- s_rxpipe: read, pipe wait
isloe := '1';
n.state := s_rxprep2;
 
when s_txprep0 => -- s_txprep0: switch to tx-fifo
ififo_ce := '1';
ififo := c_txfifo;
n.state := s_txprep1;
 
when s_txprep1 => -- s_txprep1: fifo addr setup
cc_clr := '1';
n.state := s_txprep2;
 
when s_txprep2 => -- s_txprep2: wait for flags
n.state := s_txdisp;
 
when s_txdisp => -- s_txdisp: write, dispatch
-- if chunk done and tx2 or pe2 pending and possible
if cc_done='1' and sltx2ok='1' and (TX2FIFO_VAL='1' or r.pe2pend='1')
then
n.state := s_tx2prep0;
-- if chunk done and rx pending and possible
elsif cc_done='1' and slrxok='1' and RXFIFO_BUSY='0' then
n.state := s_rxprep0;
-- if pktend to do and possible
elsif sltxok = '1' and r.pepend = '1' then
ipktend := '1';
n.pepend := '0';
n.state := s_idle;
-- if more tx to do and possible
elsif sltxok = '1' and TXFIFO_VAL = '1' then
cc_cnt := '1'; -- inc chunk count
n.pepend := '0'; -- cancel pe (avoid back-2-back tx+pe)
itxfifo_hold := '0';
idata_do := TXFIFO_DO;
idata_ceo := '1';
idata_oe := '1';
islwr := '1';
if pipeok = '1' then -- if not almost full
n.state := s_txdisp; -- stream
else
n.state := s_txprep1; -- wait for full flag
end if;
-- otherwise back to idle
else
n.state := s_idle;
end if;
when s_tx2prep0 => -- s_tx2prep0: switch to tx2-fifo
ififo_ce := '1';
ififo := c_tx2fifo;
n.state := s_tx2prep1;
 
when s_tx2prep1 => -- s_tx2prep1: fifo addr setup
cc_clr := '1';
n.state := s_tx2prep2;
 
when s_tx2prep2 => -- s_tx2prep2: wait for flags
n.state := s_tx2disp;
 
when s_tx2disp => -- s_tx2disp: write, dispatch
-- if chunk done and rx pending and possible
if cc_done='1' and slrxok='1' and RXFIFO_BUSY='0' then
n.state := s_rxprep0;
-- if chunk done and tx or pe pending and possible
elsif cc_done='1' and sltxok='1' and (TXFIFO_VAL='1' or r.pepend='1')
then
n.state := s_txprep0;
-- if pktend 2 to do and possible
elsif sltx2ok = '1' and r.pe2pend = '1' then
ipktend := '1';
n.pe2pend := '0';
n.state := s_idle;
-- if more tx2 to do and possible
elsif sltx2ok = '1' and TX2FIFO_VAL = '1' then
cc_cnt := '1'; -- inc chunk count
n.pe2pend := '0'; -- cancel pe (avoid back-2-back tx+pe)
itx2fifo_hold := '0';
idata_do := TX2FIFO_DO;
idata_ceo := '1';
idata_oe := '1';
islwr := '1';
if pipeok = '1' then -- if not almost full
n.state := s_tx2disp; -- stream
else
n.state := s_tx2prep1; -- wait for full flag
end if;
-- otherwise back to idle
else
n.state := s_idle;
end if;
when others => null;
end case;
 
-- rx pipe handling
idata_cei := r.rxpipe1;
n.rxpipe2 := r.rxpipe1;
irxfifo_ena := r.rxpipe2;
-- chunk counter handling
if cc_clr = '1' then
n.ccnt := (others=>'1');
elsif cc_cnt='1' and unsigned(r.ccnt) > 0 then
n.ccnt := slv(unsigned(r.ccnt) - 1);
end if;
-- pktend time-out handling:
-- if tx fifo is non-empty, set counter to max
-- if tx fifo is empty, count down every usec
-- on 1->0 transition queue pktend request
if TXFIFO_VAL = '1' then
n.petocnt := (others=>'1');
else
if unsigned(r.petocnt) /= 0 then
n.petocnt := slv(unsigned(r.petocnt) - 1);
if unsigned(r.petocnt) = 1 then
n.pepend := '1';
end if;
end if;
end if;
if TX2FIFO_VAL = '1' then
n.pe2tocnt := (others=>'1');
else
if unsigned(r.pe2tocnt) /= 0 then
n.pe2tocnt := slv(unsigned(r.pe2tocnt) - 1);
if unsigned(r.pe2tocnt) = 1 then
n.pe2pend := '1';
end if;
end if;
end if;
 
n.moni_ep4_sel := '0';
n.moni_ep6_sel := '0';
n.moni_ep8_sel := '0';
if r.state = s_rxdisp or r.state = s_rxpipe then
n.moni_ep4_sel := '1';
n.moni_ep4_pf := not FX2_FLAG_N(c_flag_prog);
elsif r.state = s_txdisp then
n.moni_ep6_sel := '1';
n.moni_ep6_pf := not FX2_FLAG_N(c_flag_prog);
elsif r.state = s_tx2disp then
n.moni_ep8_sel := '1';
n.moni_ep8_pf := not FX2_FLAG_N(c_flag_prog);
end if;
 
N_REGS <= n;
 
FX2_FIFO_CE <= ififo_ce;
FX2_FIFO <= ififo;
 
FX2_SLRD_N <= not islrd;
FX2_SLWR_N <= not islwr;
FX2_SLOE_N <= not isloe;
FX2_PKTEND_N <= not ipktend;
 
FX2_DATA_CEI <= idata_cei;
FX2_DATA_CEO <= idata_ceo;
FX2_DATA_OE <= idata_oe;
FX2_DATA_DO <= idata_do;
 
RXFIFO_ENA <= irxfifo_ena;
TXFIFO_HOLD <= itxfifo_hold;
TX2FIFO_HOLD <= itx2fifo_hold;
end process proc_next;
 
proc_moni: process (CLK)
begin
 
if rising_edge(CLK) then
if RESET = '1' then
R_MONI_C <= fx2ctl_moni_init;
R_MONI_S <= fx2ctl_moni_init;
else
R_MONI_C <= fx2ctl_moni_init;
R_MONI_C.fifo_ep4 <= R_REGS.moni_ep4_sel;
R_MONI_C.fifo_ep6 <= R_REGS.moni_ep6_sel;
R_MONI_C.fifo_ep8 <= R_REGS.moni_ep8_sel;
R_MONI_C.flag_ep4_empty <= not FX2_FLAG_N(c_flag_rx_ef);
R_MONI_C.flag_ep4_almost <= R_REGS.moni_ep4_pf;
R_MONI_C.flag_ep6_full <= not FX2_FLAG_N(c_flag_tx_ff);
R_MONI_C.flag_ep6_almost <= R_REGS.moni_ep6_pf;
R_MONI_C.flag_ep8_full <= not FX2_FLAG_N(c_flag_tx2_ff);
R_MONI_C.flag_ep8_almost <= R_REGS.moni_ep8_pf;
R_MONI_C.slrd <= not FX2_SLRD_N;
R_MONI_C.slwr <= not FX2_SLWR_N;
R_MONI_C.pktend <= not FX2_PKTEND_N;
R_MONI_S <= R_MONI_C;
end if;
end if;
 
end process proc_moni;
 
proc_almost: process (RXSIZE_USR, TXSIZE_USR, TX2SIZE_USR)
begin
 
-- rxsize_usr is the number of bytes to read
-- txsize_usr is the number of bytes to write
if unsigned(RXSIZE_USR) <= RXAEMPTY_THRES then
RXAEMPTY <= '1';
else
RXAEMPTY <= '0';
end if;
 
if unsigned(TXSIZE_USR) <= TXAFULL_THRES then
TXAFULL <= '1';
else
TXAFULL <= '0';
end if;
 
if unsigned(TX2SIZE_USR) <= TX2AFULL_THRES then
TX2AFULL <= '1';
else
TX2AFULL <= '0';
end if;
 
end process proc_almost;
 
TXBUSY <= TXBUSY_L;
TX2BUSY <= TX2BUSY_L;
 
MONI <= R_MONI_S;
end syn;
/tb/fx2_2fifo_core.vhd
0,0 → 1,277
-- $Id: fx2_2fifo_core.vhd 469 2013-01-05 12:29:44Z mueller $
--
-- Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: fx2_2fifo_core - sim
-- Description: Cypress EZ-USB FX2 (2 fifo core model)
--
-- Dependencies: memlib/fifo_2c_dram
-- Test bench: -
-- Target Devices: generic
-- Tool versions: xst 13.3; ghdl 0.29
-- Revision History:
-- Date Rev Version Comment
-- 2013-01-04 469 1.0 Initial version
------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
use std.textio.all;
 
use work.slvtypes.all;
use work.simbus.all;
use work.fx2lib.all;
use work.memlib.all;
 
entity fx2_2fifo_core is -- EZ-USB FX2 (2 fifo core model)
port (
CLK : in slbit; -- uplink clock
RESET : in slbit; -- reset
RXDATA : in slv8; -- rx data (ext->fx2)
RXENA : in slbit; -- rx enable
RXBUSY : out slbit; -- rx busy
TXDATA : out slv8; -- tx data (fx2->ext)
TXVAL : out slbit; -- tx valid
IFCLK : out slbit; -- fx2 interface clock
FIFO : in slv2; -- fx2 fifo address
FLAG : out slv4; -- fx2 fifo flags
SLRD_N : in slbit; -- fx2 read enable (act.low)
SLWR_N : in slbit; -- fx2 write enable (act.low)
SLOE_N : in slbit; -- fx2 output enable (act.low)
PKTEND_N : in slbit; -- fx2 packet end (act.low)
DATA : inout slv8 -- fx2 data lines
);
end fx2_2fifo_core;
 
 
architecture sim of fx2_2fifo_core is
constant c_rxfifo : slv2 := c_fifo_ep4;
constant c_txfifo : slv2 := c_fifo_ep6;
 
constant c_flag_prog : integer := 0;
constant c_flag_tx_ff : integer := 1;
constant c_flag_rx_ef : integer := 2;
constant c_flag_tx2_ff : integer := 3;
 
constant bufsize : positive := 1024;
constant datzero : slv(DATA'range) := (others=>'0');
type buf_type is array (0 to bufsize-1) of slv(DATA'range);
 
signal CLK30 : slbit := '0';
 
signal RXFIFO_DO : slv8 := (others=>'0');
signal RXFIFO_VAL : slbit := '0';
signal RXFIFO_HOLD : slbit := '0';
signal TXFIFO_DI : slv8 := (others=>'0');
signal TXFIFO_ENA : slbit := '0';
signal TXFIFO_BUSY : slbit := '0';
 
signal R_FLAG : slv4 := (others=>'0');
signal R_DATA : slv8 := (others=>'0');
 
-- added for debug purposes
signal R_rxbuf_rind : natural := 0;
signal R_rxbuf_wind : natural := 0;
signal R_rxbuf_nbyt : natural := 0;
signal R_txbuf_rind : natural := 0;
signal R_txbuf_wind : natural := 0;
signal R_txbuf_nbyt : natural := 0;
begin
 
RXFIFO : fifo_2c_dram
generic map (
AWIDTH => 5,
DWIDTH => 8)
port map (
CLKW => CLK,
CLKR => CLK30,
RESETW => '0',
RESETR => '0',
DI => RXDATA,
ENA => RXENA,
BUSY => RXBUSY,
DO => RXFIFO_DO,
VAL => RXFIFO_VAL,
HOLD => RXFIFO_HOLD,
SIZEW => open,
SIZER => open
);
 
TXFIFO : fifo_2c_dram
generic map (
AWIDTH => 5,
DWIDTH => 8)
port map (
CLKW => CLK30,
CLKR => CLK,
RESETW => '0',
RESETR => '0',
DI => TXFIFO_DI,
ENA => TXFIFO_ENA,
BUSY => TXFIFO_BUSY,
DO => TXDATA,
VAL => TXVAL,
HOLD => '0',
SIZEW => open,
SIZER => open
);
 
proc_ifclk: process
constant offset : time := 200 ns;
constant halfperiod_7 : time := 16700 ps;
constant halfperiod_6 : time := 16600 ps;
begin
 
CLK30 <= '0';
wait for offset;
 
clk_loop: loop
CLK30 <= '1';
wait for halfperiod_7;
CLK30 <= '0';
wait for halfperiod_7;
CLK30 <= '1';
wait for halfperiod_6;
CLK30 <= '0';
wait for halfperiod_7;
CLK30 <= '1';
wait for halfperiod_7;
CLK30 <= '0';
wait for halfperiod_6;
exit clk_loop when to_x01(SB_CLKSTOP) = '1';
end loop;
wait; -- endless wait, simulator will stop
end process proc_ifclk;
 
proc_state: process (CLK30)
variable rxbuf : buf_type := (others=>datzero);
variable rxbuf_rind : natural := 0;
variable rxbuf_wind : natural := 0;
variable rxbuf_nbyt : natural := 0;
 
variable txbuf : buf_type := (others=>datzero);
variable txbuf_rind : natural := 0;
variable txbuf_wind : natural := 0;
variable txbuf_nbyt : natural := 0;
 
variable oline : line;
 
begin
 
if rising_edge(CLK30) then
 
RXFIFO_HOLD <= '0';
TXFIFO_ENA <= '0';
 
-- rxfifo -> rxbuf
if RXFIFO_VAL = '1' then
if rxbuf_nbyt < bufsize then
rxbuf(rxbuf_wind) := RXFIFO_DO;
rxbuf_wind := (rxbuf_wind + 1) mod bufsize;
rxbuf_nbyt := rxbuf_nbyt + 1;
else
RXFIFO_HOLD <= '1';
end if;
end if;
 
-- txbuf -> txfifo
if txbuf_nbyt>0 and TXFIFO_BUSY='0' then
TXFIFO_DI <= txbuf(txbuf_rind);
TXFIFO_ENA <= '1';
txbuf_rind := (txbuf_rind + 1) mod bufsize;
txbuf_nbyt := txbuf_nbyt - 1;
end if;
 
-- slrd cycle: rxbuf -> data
if SLRD_N = '0' then
if rxbuf_nbyt > 0 then
rxbuf_rind := (rxbuf_rind + 1) mod bufsize;
rxbuf_nbyt := rxbuf_nbyt - 1;
else
write(oline, string'("fx2_2fifo_core: SLRD_N=0 when rxbuf empty"));
writeline(output, oline);
end if;
end if;
R_DATA <= rxbuf(rxbuf_rind);
-- slwr cycle: data -> txbuf
if SLWR_N = '0' then
if txbuf_nbyt < bufsize then
txbuf(txbuf_wind) := DATA;
txbuf_wind := (txbuf_wind + 1) mod bufsize;
txbuf_nbyt := txbuf_nbyt + 1;
else
write(oline, string'("fx2_2fifo_core: SLWR_N=0 when txbuf full"));
writeline(output, oline);
end if;
end if;
 
-- prepare flags (note that FLAGs are act.low!)
R_FLAG <= (others=>'1');
-- FLAGA = indexed, PF
-- rx endpoint -> PF 'almost empty' at 3 bytes to go
if FIFO = c_rxfifo then
if rxbuf_nbyt < 4 then
R_FLAG(0) <= '0';
end if;
-- tx endpoint -> PF 'almost full' at 3 bytes to go
elsif FIFO = c_txfifo then
if txbuf_nbyt > bufsize-4 then
R_FLAG(0) <= '0';
end if;
end if;
 
-- FLAGB = EP6 FF
if txbuf_nbyt = bufsize then
R_FLAG(1) <= '0';
end if;
 
-- FLAGC = EP4 EF
if rxbuf_nbyt = 0 then
R_FLAG(2) <= '0';
end if;
-- FLAGD = EP8 FF
R_FLAG(3) <= '1';
 
-- added for debug purposes
R_rxbuf_rind <= rxbuf_rind;
R_rxbuf_wind <= rxbuf_wind;
R_rxbuf_nbyt <= rxbuf_nbyt;
R_txbuf_rind <= txbuf_rind;
R_txbuf_wind <= txbuf_wind;
R_txbuf_nbyt <= txbuf_nbyt;
end if;
end process proc_state;
 
IFCLK <= CLK30;
FLAG <= R_FLAG;
 
proc_data: process (SLOE_N, R_DATA)
begin
if SLOE_N = '1' then
DATA <= (others=>'Z');
else
DATA <= R_DATA;
end if;
end process proc_data;
end sim;
/tb/fx2_2fifo_core.vbom
0,0 → 1,9
# libs
../../../vlib/slvtypes.vhd
../../../vlib/simlib/simlib.vhd
../fx2lib.vhd
../../../vlib/memlib/memlib.vhd
# components
../../../vlib/memlib/fifo_2c_dram.vbom
# design
fx2_2fifo_core.vhd
/tb
tb Property changes : Added: svn:ignore ## -0,0 +1,32 ## +*.dep_ghdl +*.dep_isim +*.dep_xst +work-obj93.cf +*.vcd +*.ghw +*.sav +*.tmp +*.exe +ise +xflow.his +*.ngc +*.ncd +*.pcf +*.bit +*.msk +isim +isim.log +isim.wdb +fuse.log +*_[sft]sim.vhd +*_tsim.sdf +*_xst.log +*_tra.log +*_twr.log +*_map.log +*_par.log +*_pad.log +*_bgn.log +*_svn.log +*_sum.log +*_[dsft]sim.log Index: fx2_2fifoctl_ic.vbom =================================================================== --- fx2_2fifoctl_ic.vbom (nonexistent) +++ fx2_2fifoctl_ic.vbom (revision 24) @@ -0,0 +1,13 @@ +# libs +../../vlib/slvtypes.vhd +../../vlib/xlib/xlib.vhd +../../vlib/memlib/memlib.vhd +fx2lib.vhd +# components +../../vlib/xlib/iob_reg_o.vbom +../../vlib/xlib/iob_reg_i_gen.vbom +../../vlib/xlib/iob_reg_o_gen.vbom +../../vlib/xlib/iob_reg_io_gen.vbom +../../vlib/memlib/fifo_2c_dram.vbom +# design +fx2_2fifoctl_ic.vhd Index: fx2_3fifoctl_ic.vbom =================================================================== --- fx2_3fifoctl_ic.vbom (nonexistent) +++ fx2_3fifoctl_ic.vbom (revision 24) @@ -0,0 +1,13 @@ +# libs +../../vlib/slvtypes.vhd +../../vlib/xlib/xlib.vhd +../../vlib/memlib/memlib.vhd +fx2lib.vhd +# components +../../vlib/xlib/iob_reg_o.vbom +../../vlib/xlib/iob_reg_i_gen.vbom +../../vlib/xlib/iob_reg_o_gen.vbom +../../vlib/xlib/iob_reg_io_gen.vbom +../../vlib/memlib/fifo_2c_dram.vbom +# design +fx2_3fifoctl_ic.vhd Index: fx2lib.vhd =================================================================== --- fx2lib.vhd (nonexistent) +++ fx2lib.vhd (revision 24) @@ -0,0 +1,172 @@ +-- $Id: fx2lib.vhd 453 2012-01-15 17:51:18Z mueller $ +-- +-- Copyright 2011-2012 by Walter F.J. Mueller +-- +-- This program is free software; you may redistribute and/or modify it under +-- the terms of the GNU General Public License as published by the Free +-- Software Foundation, either version 2, or at your option any later version. +-- +-- This program is distributed in the hope that it will be useful, but +-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY +-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-- for complete details. +-- +------------------------------------------------------------------------------ +-- Package Name: fx2lib +-- Description: Cypress ez-usb fx2 support +-- +-- Dependencies: - +-- Tool versions: xst 12.1, 13.1, 13.3; ghdl 0.26-0.29 +-- +-- Revision History: +-- Date Rev Version Comment +-- 2012-01-14 453 1.3 use afull/aempty logic instead of exporting size +-- 2012-01-03 449 1.2.1 reorganize fx2ctl_moni; hardcode ep's +-- 2012-01-01 448 1.2 add fx2_2fifoctl_ic +-- 2011-12-25 445 1.1 change pktend iface in fx2_2fifoctl_as +-- 2011-07-17 394 1.0.1 add c_fifo_epx and fx2ctl_moni_type +-- 2011-07-07 389 1.0 Initial version +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; + +use work.slvtypes.all; + +package fx2lib is + + constant c_fifo_ep2 : slv2 := "00"; -- fifo address: end point 2 + constant c_fifo_ep4 : slv2 := "01"; -- fifo address: end point 4 + constant c_fifo_ep6 : slv2 := "10"; -- fifo address: end point 6 + constant c_fifo_ep8 : slv2 := "11"; -- fifo address: end point 8 + + type fx2ctl_moni_type is record -- fx2ctl monitor port + fifo_ep4 : slbit; -- fifo 1 (ep4) active; + fifo_ep6 : slbit; -- fifo 2 (ep6) active; + fifo_ep8 : slbit; -- fifo 3 (ep8) active; + flag_ep4_empty : slbit; -- ep4 empty flag (latched); + flag_ep4_almost : slbit; -- ep4 almost empty flag (latched); + flag_ep6_full : slbit; -- ep6 full flag (latched); + flag_ep6_almost : slbit; -- ep6 almost full flag (latched); + flag_ep8_full : slbit; -- ep8 full flag (latched); + flag_ep8_almost : slbit; -- ep8 almost full flag (latched); + slrd : slbit; -- read strobe + slwr : slbit; -- write strobe + pktend : slbit; -- pktend strobe + end record fx2ctl_moni_type; + + constant fx2ctl_moni_init : fx2ctl_moni_type := ( + '0','0','0', -- fifo_ep[468] + '0','0', -- flag_ep4_(empty|almost) + '0','0', -- flag_ep6_(full|almost) + '0','0', -- flag_ep8_(full|almost) + '0','0','0' -- slrd, slwr, pktend + ); + + +-- ------------------------------------- +component fx2_2fifoctl_as is -- EZ-USB FX2 driver (2 fifo; async) + generic ( + RXFAWIDTH : positive := 5; -- receive fifo address width + TXFAWIDTH : positive := 5; -- transmit fifo address width + PETOWIDTH : positive := 7; -- packet end time-out counter width + CCWIDTH : positive := 5; -- chunk counter width + RXAEMPTY_THRES : natural := 1; -- threshold for rx aempty flag + TXAFULL_THRES : natural := 1; -- threshold for tx afull flag + RDPWLDELAY : positive := 5; -- slrd low delay in clock cycles + RDPWHDELAY : positive := 5; -- slrd high delay in clock cycles + WRPWLDELAY : positive := 5; -- slwr low delay in clock cycles + WRPWHDELAY : positive := 7; -- slwr high delay in clock cycles + FLAGDELAY : positive := 2); -- flag delay in clock cycles + port ( + CLK : in slbit; -- clock + CE_USEC : in slbit; -- 1 usec clock enable + RESET : in slbit := '0'; -- reset + RXDATA : out slv8; -- receive data out + RXVAL : out slbit; -- receive data valid + RXHOLD : in slbit; -- receive data hold + RXAEMPTY : out slbit; -- receive almost empty flag + TXDATA : in slv8; -- transmit data in + TXENA : in slbit; -- transmit data enable + TXBUSY : out slbit; -- transmit data busy + TXAFULL : out slbit; -- transmit almost full flag + MONI : out fx2ctl_moni_type; -- monitor port data + I_FX2_IFCLK : in slbit; -- fx2: interface clock + O_FX2_FIFO : out slv2; -- fx2: fifo address + I_FX2_FLAG : in slv4; -- fx2: fifo flags + O_FX2_SLRD_N : out slbit; -- fx2: read enable (act.low) + O_FX2_SLWR_N : out slbit; -- fx2: write enable (act.low) + O_FX2_SLOE_N : out slbit; -- fx2: output enable (act.low) + O_FX2_PKTEND_N : out slbit; -- fx2: packet end (act.low) + IO_FX2_DATA : inout slv8 -- fx2: data lines + ); +end component; + +component fx2_2fifoctl_ic is -- EZ-USB FX2 driver (2 fifo; int clk) + generic ( + RXFAWIDTH : positive := 5; -- receive fifo address width + TXFAWIDTH : positive := 5; -- transmit fifo address width + PETOWIDTH : positive := 7; -- packet end time-out counter width + CCWIDTH : positive := 5; -- chunk counter width + RXAEMPTY_THRES : natural := 1; -- threshold for rx aempty flag + TXAFULL_THRES : natural := 1); -- threshold for tx afull flag + port ( + CLK : in slbit; -- clock + RESET : in slbit := '0'; -- reset + RXDATA : out slv8; -- receive data out + RXVAL : out slbit; -- receive data valid + RXHOLD : in slbit; -- receive data hold + RXAEMPTY : out slbit; -- receive almost empty flag + TXDATA : in slv8; -- transmit data in + TXENA : in slbit; -- transmit data enable + TXBUSY : out slbit; -- transmit data busy + TXAFULL : out slbit; -- transmit almost full flag + MONI : out fx2ctl_moni_type; -- monitor port data + I_FX2_IFCLK : in slbit; -- fx2: interface clock + O_FX2_FIFO : out slv2; -- fx2: fifo address + I_FX2_FLAG : in slv4; -- fx2: fifo flags + O_FX2_SLRD_N : out slbit; -- fx2: read enable (act.low) + O_FX2_SLWR_N : out slbit; -- fx2: write enable (act.low) + O_FX2_SLOE_N : out slbit; -- fx2: output enable (act.low) + O_FX2_PKTEND_N : out slbit; -- fx2: packet end (act.low) + IO_FX2_DATA : inout slv8 -- fx2: data lines + ); +end component; + +component fx2_3fifoctl_ic is -- EZ-USB FX2 driver (3 fifo; int clk) + generic ( + RXFAWIDTH : positive := 5; -- receive fifo address width + TXFAWIDTH : positive := 5; -- transmit fifo address width + PETOWIDTH : positive := 7; -- packet end time-out counter width + CCWIDTH : positive := 5; -- chunk counter width + RXAEMPTY_THRES : natural := 1; -- threshold for rx aempty flag + TXAFULL_THRES : natural := 1; -- threshold for tx afull flag + TX2AFULL_THRES : natural := 1); -- threshold for tx2 afull flag + port ( + CLK : in slbit; -- clock + RESET : in slbit := '0'; -- reset + RXDATA : out slv8; -- receive data out + RXVAL : out slbit; -- receive data valid + RXHOLD : in slbit; -- receive data hold + RXAEMPTY : out slbit; -- receive almost empty flag + TXDATA : in slv8; -- transmit 1 data in + TXENA : in slbit; -- transmit 1 data enable + TXBUSY : out slbit; -- transmit 1 data busy + TXAFULL : out slbit; -- transmit 1 almost full flag + TX2DATA : in slv8; -- transmit 2 data in + TX2ENA : in slbit; -- transmit 2 data enable + TX2BUSY : out slbit; -- transmit 2 data busy + TX2AFULL : out slbit; -- transmit 2 almost full flag + MONI : out fx2ctl_moni_type; -- monitor port data + I_FX2_IFCLK : in slbit; -- fx2: interface clock + O_FX2_FIFO : out slv2; -- fx2: fifo address + I_FX2_FLAG : in slv4; -- fx2: fifo flags + O_FX2_SLRD_N : out slbit; -- fx2: read enable (act.low) + O_FX2_SLWR_N : out slbit; -- fx2: write enable (act.low) + O_FX2_SLOE_N : out slbit; -- fx2: output enable (act.low) + O_FX2_PKTEND_N : out slbit; -- fx2: packet end (act.low) + IO_FX2_DATA : inout slv8 -- fx2: data lines + ); +end component; + +end package fx2lib; Index: fx2_2fifoctl_as.vhd =================================================================== --- fx2_2fifoctl_as.vhd (nonexistent) +++ fx2_2fifoctl_as.vhd (revision 24) @@ -0,0 +1,647 @@ +-- $Id: fx2_2fifoctl_as.vhd 453 2012-01-15 17:51:18Z mueller $ +-- +-- Copyright 2011-2012 by Walter F.J. Mueller +-- +-- This program is free software; you may redistribute and/or modify it under +-- the terms of the GNU General Public License as published by the Free +-- Software Foundation, either version 2, or at your option any later version. +-- +-- This program is distributed in the hope that it will be useful, but +-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY +-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-- for complete details. +-- +------------------------------------------------------------------------------ +-- Module Name: fx2_2fifoctl_as - syn +-- Description: Cypress EZ-USB FX2 driver (2 fifo; async) +-- +-- Dependencies: vlib/xlib/iob_reg_o +-- vlib/xlib/iob_reg_i_gen +-- vlib/xlib/iob_reg_o_gen +-- vlib/xlib/iob_reg_io_gen +-- memlib/fifo_1c_dram +-- +-- Test bench: - +-- Target Devices: generic +-- Tool versions: xst 12.1, 13.1, 13.3; ghdl 0.26-0.29 +-- +-- Synthesized (xst): +-- Date Rev ise Target flop lutl lutm slic t peri +-- 2012-01-14 453 13.3 O76x xc3s1200e-4 65 153 64 133 s 7.2 +-- 2012-01-03 449 13.3 O76x xc3s1200e-4 67 149 64 133 s 7.2 +-- 2011-12-25 445 13.3 O76x xc3s1200e-4 61 147 64 127 s 7.2 +-- 2011-12-25 444 13.3 O76x xc3s1200e-4 54 140 64 123 s 7.2 +-- 2011-07-07 389 12.1 M53d xc3s1200e-4 45 132 64 109 s 7.9 +-- +-- Revision History: +-- Date Rev Version Comment +-- 2012-01-14 453 1.3 common DELAY for PE and WR; use aempty/afull logic +-- 2012-01-04 450 1.2.2 use new FLAG layout (EF,FF now fixed) +-- 2012-01-03 449 1.2.1 use new fx2ctl_moni layout; hardcode ep's +-- 2011-12-25 445 1.2 change pktend handling, now timer based +-- 2011-11-25 433 1.1.1 now numeric_std clean +-- 2011-07-30 400 1.1 capture rx data in 2nd last s_rdpwh cycle +-- 2011-07-24 389 1.0.2 use FX2_FLAG_N to signal that flags are act.low +-- 2011-07-17 394 1.0.1 (RX|TX)FIFOEP now generics; add MONI port +-- 2011-07-08 390 1.0 Initial version +-- +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.slvtypes.all; +use work.xlib.all; +use work.memlib.all; +use work.fx2lib.all; + +entity fx2_2fifoctl_as is -- EZ-USB FX2 driver (2 fifo; async) + generic ( + RXFAWIDTH : positive := 5; -- receive fifo address width + TXFAWIDTH : positive := 5; -- transmit fifo address width + PETOWIDTH : positive := 7; -- packet end time-out counter width + CCWIDTH : positive := 5; -- chunk counter width + RXAEMPTY_THRES : natural := 1; -- threshold for rx aempty flag + TXAFULL_THRES : natural := 1; -- threshold for tx afull flag + RDPWLDELAY : positive := 5; -- slrd low delay in clock cycles + RDPWHDELAY : positive := 5; -- slrd high delay in clock cycles + WRPWLDELAY : positive := 5; -- slwr low delay in clock cycles + WRPWHDELAY : positive := 7; -- slwr high delay in clock cycles + FLAGDELAY : positive := 2); -- flag delay in clock cycles + port ( + CLK : in slbit; -- clock + CE_USEC : in slbit; -- 1 usec clock enable + RESET : in slbit := '0'; -- reset + RXDATA : out slv8; -- receive data out + RXVAL : out slbit; -- receive data valid + RXHOLD : in slbit; -- receive data hold + RXAEMPTY : out slbit; -- receive almost empty flag + TXDATA : in slv8; -- transmit data in + TXENA : in slbit; -- transmit data enable + TXBUSY : out slbit; -- transmit data busy + TXAFULL : out slbit; -- transmit almost full flag + MONI : out fx2ctl_moni_type; -- monitor port data + I_FX2_IFCLK : in slbit; -- fx2: interface clock + O_FX2_FIFO : out slv2; -- fx2: fifo address + I_FX2_FLAG : in slv4; -- fx2: fifo flags + O_FX2_SLRD_N : out slbit; -- fx2: read enable (act.low) + O_FX2_SLWR_N : out slbit; -- fx2: write enable (act.low) + O_FX2_SLOE_N : out slbit; -- fx2: output enable (act.low) + O_FX2_PKTEND_N : out slbit; -- fx2: packet end (act.low) + IO_FX2_DATA : inout slv8 -- fx2: data lines + ); +end fx2_2fifoctl_as; + + +architecture syn of fx2_2fifoctl_as is + + constant c_rxfifo : slv2 := c_fifo_ep4; + constant c_txfifo : slv2 := c_fifo_ep6; + + constant c_flag_prog : integer := 0; + constant c_flag_tx_ff : integer := 1; + constant c_flag_rx_ef : integer := 2; + constant c_flag_tx2_ff : integer := 3; + + type state_type is ( + s_init, -- s_init: init state + s_rdprep, -- s_rdprep: prepare read + s_rdwait, -- s_rdwait: wait for data + s_rdpwl, -- s_rdpwl: read, strobe low + s_rdpwh, -- s_rdpwh: read, strobe high + s_wrprep, -- s_wrprep: prepare write + s_wrpwl, -- s_wrpwl: write, strobe low + s_wrpwh, -- s_wrpwh: write, strobe high + s_peprep, -- s_peprep: prepare pktend + s_pepwl, -- s_pepwl: pktend, strobe low + s_pepwh -- s_pepwh: pktend, strobe high + ); + + type regs_type is record + state : state_type; -- state + petocnt : slv(PETOWIDTH-1 downto 0); -- pktend time out counter + pepend : slbit; -- pktend pending + dlycnt : slv4; -- wait delay counter + moni_ep4_sel : slbit; -- ep4 (rx) select + moni_ep6_sel : slbit; -- ep6 (tx) select + moni_ep4_pf : slbit; -- ep4 (rx) prog flag + moni_ep6_pf : slbit; -- ep6 (rx) prog flag + end record regs_type; + + constant petocnt_init : slv(PETOWIDTH-1 downto 0) := (others=>'0'); + + constant regs_init : regs_type := ( + s_init, -- state + petocnt_init, -- petocnt + '0', -- pepend + (others=>'0'), -- cntdly + '0','0', -- moni_ep(4|6)_sel + '0','0' -- moni_ep(4|6)_pf + ); + + signal R_REGS : regs_type := regs_init; -- state registers + signal N_REGS : regs_type := regs_init; -- next value state regs + + signal FX2_FIFO : slv2 := (others=>'0'); + signal FX2_FIFO_CE : slbit := '0'; + signal FX2_FLAG_N : slv4 := (others=>'0'); + signal FX2_SLRD_N : slbit := '1'; + signal FX2_SLWR_N : slbit := '1'; + signal FX2_SLOE_N : slbit := '1'; + signal FX2_PKTEND_N : slbit := '1'; + signal FX2_DATA_CEI : slbit := '0'; + signal FX2_DATA_CEO : slbit := '0'; + signal FX2_DATA_OE : slbit := '0'; + + signal RXFIFO_DI : slv8 := (others=>'0'); + signal RXFIFO_ENA : slbit := '0'; + signal RXFIFO_BUSY : slbit := '0'; + signal RXSIZE : slv(RXFAWIDTH downto 0) := (others=>'0'); + signal TXFIFO_DO : slv8 := (others=>'0'); + signal TXFIFO_VAL : slbit := '0'; + signal TXFIFO_HOLD : slbit := '0'; + signal TXSIZE : slv(TXFAWIDTH downto 0) := (others=>'0'); + + signal TXBUSY_L : slbit := '0'; + +begin + + assert RDPWLDELAY<=2**R_REGS.dlycnt'length and + RDPWHDELAY<=2**R_REGS.dlycnt'length and RDPWHDELAY>=2 and + WRPWLDELAY<=2**R_REGS.dlycnt'length and + WRPWHDELAY<=2**R_REGS.dlycnt'length and + FLAGDELAY<=2**R_REGS.dlycnt'length + report "assert(*DELAY <= 2**dlycnt'length and RDPWHDELAY >=2)" + severity failure; + + assert RXAEMPTY_THRES<=2**RXFAWIDTH and + TXAFULL_THRES<=2**TXFAWIDTH + report "assert((RXAEMPTY|TXAFULL)_THRES <= 2**(RX|TX)FAWIDTH)" + severity failure; + + IOB_FX2_FIFO : iob_reg_o_gen + generic map ( + DWIDTH => 2, + INIT => '0') + port map ( + CLK => CLK, + CE => FX2_FIFO_CE, + DO => FX2_FIFO, + PAD => O_FX2_FIFO + ); + + IOB_FX2_FLAG : iob_reg_i_gen + generic map ( + DWIDTH => 4, + INIT => '0') + port map ( + CLK => CLK, + CE => '1', + DI => FX2_FLAG_N, + PAD => I_FX2_FLAG + ); + + IOB_FX2_SLRD : iob_reg_o + generic map ( + INIT => '1') + port map ( + CLK => CLK, + CE => '1', + DO => FX2_SLRD_N, + PAD => O_FX2_SLRD_N + ); + + IOB_FX2_SLWR : iob_reg_o + generic map ( + INIT => '1') + port map ( + CLK => CLK, + CE => '1', + DO => FX2_SLWR_N, + PAD => O_FX2_SLWR_N + ); + + IOB_FX2_SLOE : iob_reg_o + generic map ( + INIT => '1') + port map ( + CLK => CLK, + CE => '1', + DO => FX2_SLOE_N, + PAD => O_FX2_SLOE_N + ); + + IOB_FX2_PKTEND : iob_reg_o + generic map ( + INIT => '1') + port map ( + CLK => CLK, + CE => '1', + DO => FX2_PKTEND_N, + PAD => O_FX2_PKTEND_N + ); + + IOB_FX2_DATA : iob_reg_io_gen + generic map ( + DWIDTH => 8, + PULL => "KEEP") + port map ( + CLK => CLK, + CEI => FX2_DATA_CEI, + CEO => FX2_DATA_CEO, + OE => FX2_DATA_OE, + DI => RXFIFO_DI, -- input data (read from pad) + DO => TXFIFO_DO, -- output data (write to pad) + PAD => IO_FX2_DATA + ); + + RXFIFO : fifo_1c_dram -- input fifo, 1 clock, dram based + generic map ( + AWIDTH => RXFAWIDTH, + DWIDTH => 8) + port map ( + CLK => CLK, + RESET => RESET, + DI => RXFIFO_DI, + ENA => RXFIFO_ENA, + BUSY => RXFIFO_BUSY, + DO => RXDATA, + VAL => RXVAL, + HOLD => RXHOLD, + SIZE => RXSIZE + ); + + TXFIFO : fifo_1c_dram -- output fifo, 1 clock, dram based + generic map ( + AWIDTH => TXFAWIDTH, + DWIDTH => 8) + port map ( + CLK => CLK, + RESET => RESET, + DI => TXDATA, + ENA => TXENA, + BUSY => TXBUSY_L, + DO => TXFIFO_DO, + VAL => TXFIFO_VAL, + HOLD => TXFIFO_HOLD, + SIZE => TXSIZE + ); + + proc_regs: process (CLK) + begin + + if rising_edge(CLK) then + if RESET = '1' then + R_REGS <= regs_init; + else + R_REGS <= N_REGS; + end if; + end if; + + end process proc_regs; + + proc_next: process (R_REGS, CE_USEC, + FX2_FLAG_N, TXFIFO_VAL, RXFIFO_BUSY, TXBUSY_L) + + variable r : regs_type := regs_init; + variable n : regs_type := regs_init; + + variable idly_ld : slbit := '0'; + variable idly_val : slv(r.dlycnt'range) := (others=>'0'); + variable idly_end : slbit := '0'; + variable idly_end1 : slbit := '0'; + + variable iflag_rdok : slbit := '0'; + variable iflag_wrok : slbit := '0'; + + variable ififo_ce : slbit := '0'; + variable ififo : slv2 := "00"; + + variable irxfifo_ena : slbit := '0'; + variable itxfifo_hold : slbit := '0'; + + variable islrd : slbit := '0'; + variable islwr : slbit := '0'; + variable isloe : slbit := '0'; + variable ipktend : slbit := '0'; + + variable idata_cei : slbit := '0'; + variable idata_ceo : slbit := '0'; + variable idata_oe : slbit := '0'; + + variable imoni : fx2ctl_moni_type := fx2ctl_moni_init; + + procedure go_rdprep(nstate : out state_type; + idly_ld : out slbit; + idly_val : out slv4; + ififo_ce : out slbit; + ififo : out slv2) is + begin + idly_ld := '1'; + idly_val := slv(to_unsigned(FLAGDELAY-1, idly_val'length)); + ififo_ce := '1'; + ififo := c_rxfifo; + nstate := s_rdprep; + end procedure go_rdprep; + + procedure go_wrprep(nstate : out state_type; + idly_ld : out slbit; + idly_val : out slv4; + ififo_ce : out slbit; + ififo : out slv2) is + begin + idly_ld := '1'; + idly_val := slv(to_unsigned(FLAGDELAY-1, idly_val'length)); + ififo_ce := '1'; + ififo := c_txfifo; + nstate := s_wrprep; + end procedure go_wrprep; + + procedure go_peprep(nstate : out state_type; + idly_ld : out slbit; + idly_val : out slv4; + ififo_ce : out slbit; + ififo : out slv2) is + begin + idly_ld := '1'; + idly_val := slv(to_unsigned(FLAGDELAY-1, idly_val'length)); + ififo_ce := '1'; + ififo := c_txfifo; + nstate := s_peprep; + end procedure go_peprep; + + procedure go_rdpwl(nstate : out state_type; + idly_ld : out slbit; + idly_val : out slv4; + islrd : out slbit) is + begin + idly_ld := '1'; + idly_val := slv(to_unsigned(RDPWLDELAY-1, n.dlycnt'length)); + islrd := '1'; + nstate := s_rdpwl; + end procedure go_rdpwl; + + procedure go_wrpwl(nstate : out state_type; + idly_ld : out slbit; + idly_val : out slv4; + islwr : out slbit) is + begin + idly_ld := '1'; + idly_val := slv(to_unsigned(WRPWLDELAY-1, n.dlycnt'length)); + islwr := '1'; + nstate := s_wrpwl; + end procedure go_wrpwl; + + procedure go_pepwl(nstate : out state_type; + idly_ld : out slbit; + idly_val : out slv4; + ipktend : out slbit) is + begin + idly_ld := '1'; + idly_val := slv(to_unsigned(WRPWLDELAY-1, n.dlycnt'length)); + ipktend := '1'; + nstate := s_pepwl; + end procedure go_pepwl; + + begin + + r := R_REGS; + n := R_REGS; + + ififo_ce := '0'; + ififo := "00"; + + irxfifo_ena := '0'; + itxfifo_hold := '1'; + + islrd := '0'; + islwr := '0'; + isloe := '0'; + ipktend := '0'; + + idata_cei := '0'; + idata_ceo := '0'; + idata_oe := '0'; + + imoni := fx2ctl_moni_init; + + iflag_rdok := FX2_FLAG_N(c_flag_rx_ef); -- empty flag is act.low! + iflag_wrok := FX2_FLAG_N(c_flag_tx_ff); -- full flag is act.low! + + idly_ld := '0'; + idly_val := (others=>'0'); + idly_end := '1'; + idly_end1 := '0'; + if unsigned(r.dlycnt) /= 0 then + idly_end := '0'; + end if; + if unsigned(r.dlycnt) = 1 then + idly_end1 := '1'; + end if; + + case r.state is + when s_init => -- s_init: + go_rdprep(n.state, idly_ld, idly_val, ififo_ce, ififo); + + when s_rdprep => -- s_rdprep: prepare read + if idly_end = '1' then + n.state := s_rdwait; + end if; + + when s_rdwait => -- s_rdwait: wait for data + if r.pepend='1' and TXFIFO_VAL='0' then + go_peprep(n.state, idly_ld, idly_val, ififo_ce, ififo); + + elsif iflag_rdok='1' and + (RXFIFO_BUSY='0' and TXBUSY_L='0') then + go_rdpwl(n.state, idly_ld, idly_val, islrd); + + elsif TXFIFO_VAL = '1' then + go_wrprep(n.state, idly_ld, idly_val, ififo_ce, ififo); + end if; + + when s_rdpwl => -- s_rdpwl: read, strobe low + idata_cei := '1'; + isloe := '1'; + if idly_end = '1' then + idly_ld := '1'; + idly_val := slv(to_unsigned(RDPWHDELAY-1, n.dlycnt'length)); + n.state := s_rdpwh; + else + islrd := '1'; + n.state := s_rdpwl; + end if; + + -- Note: data is sampled and written into rxfifo in 2nd last cycle in the + -- last cycle the rxfifo busy reflects therefore last written byte + -- and safely indicates whether another byte will fit. + when s_rdpwh => -- s_rdpwh: read, strobe high + idata_cei := '1'; + isloe := '1'; + if idly_end1 = '1' then -- 2nd last cycle + irxfifo_ena := '1'; -- capture rxdata + end if; + if idly_end = '1' then -- last cycle + if iflag_rdok='1' and + (RXFIFO_BUSY='0' and TXBUSY_L='0') then + go_rdpwl(n.state, idly_ld, idly_val, islrd); + + elsif TXFIFO_VAL = '1' then + go_wrprep(n.state, idly_ld, idly_val, ififo_ce, ififo); + + else + n.state := s_rdwait; + end if; + end if; + + when s_wrprep => -- s_wrprep: prepare write + if idly_end = '1' then + if iflag_wrok = '1' then + go_wrpwl(n.state, idly_ld, idly_val, islwr); + else + go_rdprep(n.state, idly_ld, idly_val, ififo_ce, ififo); + end if; + end if; + + when s_wrpwl => -- s_wrpwl: write, strobe low + idata_ceo := '1'; + idata_oe := '1'; + if idly_end = '1' then + idata_ceo := '0'; + itxfifo_hold := '0'; + idly_ld := '1'; + idly_val := slv(to_unsigned(WRPWHDELAY-1, n.dlycnt'length)); + n.state := s_wrpwh; + else + islwr := '1'; + n.state := s_wrpwl; + end if; + + when s_wrpwh => -- s_wrpwh: write, strobe high + idata_oe := '1'; + if idly_end = '1' then + if iflag_wrok='1' and TXFIFO_VAL='1' then + go_wrpwl(n.state, idly_ld, idly_val, islwr); + elsif iflag_wrok='1' and r.pepend='1' and TXFIFO_VAL='0' then + go_pepwl(n.state, idly_ld, idly_val, ipktend); + else + go_rdprep(n.state, idly_ld, idly_val, ififo_ce, ififo); + end if; + end if; + + when s_peprep => -- s_peprep: prepare pktend + if idly_end = '1' then + if iflag_wrok = '1' then + go_pepwl(n.state, idly_ld, idly_val, ipktend); + else + go_rdprep(n.state, idly_ld, idly_val, ififo_ce, ififo); + end if; + end if; + + when s_pepwl => -- s_pepwl: pktend, strobe low + if idly_end = '1' then + idly_ld := '1'; + idly_val := slv(to_unsigned(WRPWHDELAY-1, n.dlycnt'length)); + n.state := s_pepwh; + else + ipktend := '1'; + n.state := s_pepwl; + end if; + + when s_pepwh => -- s_pepwh: pktend, strobe high + if idly_end = '1' then + n.pepend := '0'; + go_rdprep(n.state, idly_ld, idly_val, ififo_ce, ififo); + end if; + + when others => null; + end case; + + if idly_ld = '1' then + n.dlycnt := idly_val; + elsif idly_end = '0' then + n.dlycnt := slv(unsigned(r.dlycnt) - 1); + end if; + + -- pktend time-out handling: + -- if tx fifo is non-empty, set counter to max + -- if tx fifo is empty, count down every usec + -- on 1->0 transition queue pktend request + if TXFIFO_VAL = '1' then + n.petocnt := (others=>'1'); + else + if CE_USEC = '1' and unsigned(r.petocnt) /= 0 then + n.petocnt := slv(unsigned(r.petocnt) - 1); + if unsigned(r.petocnt) = 1 then + n.pepend := '1'; + end if; + end if; + end if; + + n.moni_ep4_sel := '0'; + n.moni_ep6_sel := '0'; + if r.state = s_wrprep or r.state = s_wrpwl or r.state = s_wrpwh or + r.state = s_peprep or r.state = s_pepwl or r.state = s_pepwh then + n.moni_ep6_sel := '1'; + n.moni_ep6_pf := not FX2_FLAG_N(c_flag_prog); + else + n.moni_ep4_sel := '1'; + n.moni_ep4_pf := not FX2_FLAG_N(c_flag_prog); + end if; + + imoni.fifo_ep4 := r.moni_ep4_sel; + imoni.fifo_ep6 := r.moni_ep6_sel; + imoni.flag_ep4_empty := not FX2_FLAG_N(c_flag_rx_ef); + imoni.flag_ep4_almost := r.moni_ep4_pf; + imoni.flag_ep6_full := not FX2_FLAG_N(c_flag_tx_ff); + imoni.flag_ep6_almost := r.moni_ep6_pf; + imoni.slrd := islrd; + imoni.slwr := islwr; + imoni.pktend := ipktend; + + N_REGS <= n; + + FX2_FIFO_CE <= ififo_ce; + FX2_FIFO <= ififo; + + FX2_SLRD_N <= not islrd; + FX2_SLWR_N <= not islwr; + FX2_SLOE_N <= not isloe; + FX2_PKTEND_N <= not ipktend; + + FX2_DATA_CEI <= idata_cei; + FX2_DATA_CEO <= idata_ceo; + FX2_DATA_OE <= idata_oe; + + RXFIFO_ENA <= irxfifo_ena; + TXFIFO_HOLD <= itxfifo_hold; + + MONI <= imoni; + + end process proc_next; + + proc_almost: process (RXSIZE, TXSIZE) + begin + + -- (rx|tx)size is the number of bytes in fifo + -- --> rxsize is number of bytes which can be read + -- --> 2**txfawidth-txsize is is number of bytes which can be written + + if unsigned(RXSIZE) <= RXAEMPTY_THRES then + RXAEMPTY <= '1'; + else + RXAEMPTY <= '0'; + end if; + + if unsigned(TXSIZE) >= 2**TXFAWIDTH-TXAFULL_THRES then + TXAFULL <= '1'; + else + TXAFULL <= '0'; + end if; + + end process proc_almost; + + TXBUSY <= TXBUSY_L; + +end syn; Index: fx2_2fifoctl_as.vbom =================================================================== --- fx2_2fifoctl_as.vbom (nonexistent) +++ fx2_2fifoctl_as.vbom (revision 24) @@ -0,0 +1,13 @@ +# libs +../../vlib/slvtypes.vhd +../../vlib/xlib/xlib.vhd +../../vlib/memlib/memlib.vhd +fx2lib.vhd +# components +../../vlib/xlib/iob_reg_o.vbom +../../vlib/xlib/iob_reg_i_gen.vbom +../../vlib/xlib/iob_reg_o_gen.vbom +../../vlib/xlib/iob_reg_io_gen.vbom +../../vlib/memlib/fifo_1c_dram.vbom +# design +fx2_2fifoctl_as.vhd Index: . =================================================================== --- . (nonexistent) +++ . (revision 24)
. Property changes : Added: svn:ignore ## -0,0 +1,32 ## +*.dep_ghdl +*.dep_isim +*.dep_xst +work-obj93.cf +*.vcd +*.ghw +*.sav +*.tmp +*.exe +ise +xflow.his +*.ngc +*.ncd +*.pcf +*.bit +*.msk +isim +isim.log +isim.wdb +fuse.log +*_[sft]sim.vhd +*_tsim.sdf +*_xst.log +*_tra.log +*_twr.log +*_map.log +*_par.log +*_pad.log +*_bgn.log +*_svn.log +*_sum.log +*_[dsft]sim.log

powered by: WebSVN 2.1.0

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