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

Subversion Repositories ezusb_io

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /ezusb_io
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/ezusb_io.v
0,0 → 1,213
/*!
memfifo -- implementation of EZ-USB slave FIFO's (input and output) a FIFO using the DDR3 SDRAM for ZTEX USB-FPGA Modules 2.13
Copyright (C) 2009-2014 ZTEX GmbH.
http://www.ztex.de
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as
published by the Free Software Foundation.
 
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 more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, see http://www.gnu.org/licenses/.
!*/
/*
Implements the EZ-USB Slave FIFO interface for both
directions. It also includes an scheduler (required if both
directions are used at the same time) and short packets (PKTEND).
*/
module ezusb_io #(
parameter CLKBUF_TYPE = "", // selects the clock preparation method (buffering, filtering, ...)
// "SPARTAN6" for Xilinx Spartan 6,
// "SERIES7" for Xilinx Series 7,
// all other values: no clock preparation
parameter OUTEP = 2, // EP for FPGA -> EZ-USB transfers
parameter INEP = 6 // EP for EZ-USB -> FPGA transfers
) (
output ifclk, // buffered output of the interface clock
// this is the clock for the user logic
input reset, // asynchronous reset input
output reset_out, // synchronous reset output
// FPGA pins that are connected directly to EZ-USB.
input ifclk_in, // interface clock IFCLK
inout [15:0] fd, // 16 bit data bus
output reg SLWR, PKTEND, // SLWR (slave write) and PKTEND (packet end) flags
output SLRD, SLOE, // SLRD (slave read) and SLOE (slave output enable) flags
output [1:0] FIFOADDR, // FIFOADDR pins select the endpoint
input EMPTY_FLAG, FULL_FLAG, // EMPTY and FULL flag of the slave FIFO interface
// Signals for FPGA -> EZ-USB transfer. The are controlled by user logic.
input [15:0] DI, // data written to EZ-USB
input DI_valid, // 1 indicates valid data; DI and DI_valid must be hold if DI_ready is 0
output DI_ready, // 1 if new data are accepted
input DI_enable, // setting to 0 disables FPGA -> EZ-USB transfers
input [15:0] pktend_timeout, // timeout in multiples of 65536 clocks before a short packet committed
// setting to 0 disables this feature
// Signals for EZ-USB -> FPGA transfer. They are controlled by user logic.
output reg [15:0] DO, // data read from EZ-USB
output reg DO_valid, // 1 indicates valid data
input DO_ready, // setting to 1 enables writing new data to DO in next clock
// DO and DO_valid are hold if DO_ready is 0
// set to 0 to disable data reads
// debug output
output [3:0] status
);
 
wire locked;
 
generate
if ( CLKBUF_TYPE == "SPARTAN6")
begin
IBUFG ifclkin_buf (
.I(ifclk_in),
.O(ifclk)
);
assign locked = 1'b1;
end else if ( CLKBUF_TYPE == "SERIES7")
begin
wire ifclk_inbuf, ifclk_fbin, ifclk_fbout, ifclk_out;
IBUFG ifclkin_buf (
.I(ifclk_in),
.O(ifclk_inbuf)
);
 
BUFG ifclk_fb_buf (
.I(ifclk_fbout),
.O(ifclk_fbin)
);
BUFG ifclk_out_buf (
.I(ifclk_out),
.O(ifclk)
);
 
MMCME2_BASE #(
.BANDWIDTH("OPTIMIZED"),
.CLKFBOUT_MULT_F(20.0),
.CLKFBOUT_PHASE(0.0),
.CLKIN1_PERIOD(0.0),
.CLKOUT0_DIVIDE_F(20.0),
.CLKOUT1_DIVIDE(1),
.CLKOUT2_DIVIDE(1),
.CLKOUT3_DIVIDE(1),
.CLKOUT4_DIVIDE(1),
.CLKOUT5_DIVIDE(1),
.CLKOUT0_DUTY_CYCLE(0.5),
.CLKOUT1_DUTY_CYCLE(0.5),
.CLKOUT2_DUTY_CYCLE(0.5),
.CLKOUT3_DUTY_CYCLE(0.5),
.CLKOUT4_DUTY_CYCLE(0.5),
.CLKOUT5_DUTY_CYCLE(0.5),
.CLKOUT0_PHASE(0.0),
.CLKOUT1_PHASE(0.0),
.CLKOUT2_PHASE(0.0),
.CLKOUT3_PHASE(0.0),
.CLKOUT4_PHASE(0.0),
.CLKOUT5_PHASE(0.0),
.CLKOUT4_CASCADE("FALSE"),
.DIVCLK_DIVIDE(1),
.REF_JITTER1(0.0),
.STARTUP_WAIT("FALSE")
) isclk_mmcm_inst (
.CLKOUT0(ifclk_out),
.CLKFBOUT(ifclk_fbout),
.CLKIN1(ifclk_inbuf),
.PWRDWN(1'b0),
.RST(reset),
.CLKFBIN(ifclk_fbin),
.LOCKED(locked)
);
end else
begin
assign ifclk = ifclk_in;
assign locked = 1'b1;
end
endgenerate
 
reg reset_ifclk = 1;
reg if_out, if_in;
reg [4:0] if_out_buf;
reg [15:0] fd_buf;
reg resend;
reg SLRD_buf, pktend_req, pktend_en;
reg [31:0] pktend_cnt;
 
// FPGA <-> EZ-USB signals
assign SLOE = if_out;
// assign FIFOADDR[0] = 1'b0;
// assign FIFOADDR[1] = !if_out;
assign FIFOADDR = if_out ? OUTEP/2-1 : INEP/2-1;
assign fd = if_out ? fd_buf : {16{1'bz}};
assign SLRD = SLRD_buf || !DO_ready;
 
assign status = { !SLRD_buf, !SLWR, resend, if_out };
 
assign DI_ready = !reset_ifclk && FULL_FLAG && if_out & if_out_buf[4] && !resend;
assign reset_out = reset || reset_ifclk;
always @ (posedge ifclk)
begin
reset_ifclk <= reset || !locked;
// FPGA -> EZ-USB
if ( reset_ifclk )
begin
SLWR <= 1'b1;
if_out <= DI_enable; // direction of EZ-USB interface: 1 means FPGA writes / EZ_USB reads
resend <= 1'b0;
SLRD_buf <= 1'b1;
end else if ( FULL_FLAG && if_out && if_out_buf[4] && ( resend || DI_valid) ) // FPGA -> EZ-USB
begin
SLWR <= 1'b0;
SLRD_buf <= 1'b1;
resend <= 1'b0;
if ( !resend ) fd_buf <= DI;
end else if ( EMPTY_FLAG && !if_out && !if_out_buf[4] && DO_ready ) // EZ-USB -> FPGA
begin
SLWR <= 1'b1;
DO <= fd;
SLRD_buf <= 1'b0;
end else if (if_out == if_out_buf[4])
begin
if ( !SLWR && !FULL_FLAG ) resend <= 1'b1; // FLAGS are received two clocks after data. If FULL_FLAG was asserted last data was ignored and has to be re-sent.
SLRD_buf <= 1'b1;
SLWR <= 1'b1;
if_out <= DI_enable && (!DO_ready || !EMPTY_FLAG);
end
if_out_buf <= reset_ifclk ? {5{!DI_enable}} : { if_out_buf[3:0], if_out };
if ( DO_ready ) DO_valid <= !if_out && !if_out_buf[4] && EMPTY_FLAG && !SLRD_buf; // assertion of SLRD_buf takes two clocks to take effect
// PKTEND processing
if ( reset_ifclk || DI_valid )
begin
pktend_req <= 1'b0;
pktend_en <= !reset_ifclk;
pktend_cnt <= 32'd0;
PKTEND <= 1'b1;
end else
begin
pktend_req <= pktend_req || ( pktend_en && (pktend_timeout != 16'd0) && (pktend_timeout == pktend_cnt[31:16]) );
pktend_cnt <= pktend_cnt + 1;
if ( pktend_req && if_out && if_out_buf[4] )
begin
PKTEND <= 1'b0;
pktend_req <= 1'b0;
pktend_en <= 1'b0;
end else
begin
PKTEND <= 1'b1;
pktend_req <= pktend_req || ( pktend_en && (pktend_timeout != 16'd0) && (pktend_timeout == pktend_cnt[31:16]) );
end
end
end
 
endmodule
 
/trunk/ezusb_io_component.vhdl
0,0 → 1,236
component ezusb_io
generic (
OUTEP : INTEGER := 2; -- EP for FPGA -> EZ-USB transfers
INEP : INTEGER := 6; -- EP for EZ-USB -> FPGA transfers
CLKBUF_TYPE : STRING := "" -- selects the clock preparation method (buffering, filtering, ...)
-- "SPARTAN6" for Xilinx Spartan 6,
-- all other values: no clock preparation
); -- "SERIES7" for Xilinx Series 7,
port (
ifclk : out std_logic; -- buffered output of the interface clock
reset : in std_logic; -- asynchronous reset input
reset_out : out std_logic; -- synchronous reset output
 
-- FPGA pins that are connected directly to EZ-USB.
ifclk_in : in std_logic; -- interface clock IFCLK
fd : inout std_logic_vector(15 downto 0); -- 16 bit data bus
SLWR : out std_logic; -- SLWR (slave write) flag
PKTEND : out std_logic; -- PKTEND (packet end) flag
SLRD : out std_logic; -- SLRD (slave read) flag
SLOE : out std_logic; -- SLOE (slave output enable) flag
FIFOADDR : out std_logic_vector(1 downto 0); -- FIFOADDR pins select the endpoint
EMPTY_FLAG : in std_logic; -- EMPTY flag of the slave FIFO interface
FULL_FLAG : in std_logic; -- FULL flag of the slave FIFO interface
 
-- Signals for FPGA -> EZ-USB transfer. The are controlled by user logic.
DI : in std_logic_vector(15 downto 0); -- data written to EZ-USB
DI_valid : in std_logic; -- 1 indicates valid data; DI and DI_valid must be hold if DI_ready is 0
DI_ready : out std_logic; -- 1 if new data are accepted
DI_enable : in std_logic; -- setting to 0 disables FPGA -> EZ-USB transfers
pktend_timeout : in std_logic_vector(15 downto 0); -- timeout in multiples of 65536 clocks before a short packet committed
-- setting to 0 disables this feature
-- signals for EZ-USB -> FPGA transfer
DO : out std_logic_vector(15 downto 0); -- data read from EZ-USB
DO_valid : out std_logic; -- 1 indicates valid data
DO_ready : in std_logic; -- setting to 1 enables writing new data to DO in next clock
-- DO and DO_valid are hold if DO_ready is 0
-- set to 0 to disable data reads
-- debug output
status : out std_logic_vector(3 downto 0)
);
end component;
 
 
signal reset2 : std_logic;
signal reset_usb : std_logic;
signal ifclk : std_logic;
signal reset_ifclk : std_logic;
signal status : std_logic_vector(9 downto 0);
signal if_status : std_logic_vector(3 downto 0);
signal mode_buf : std_logic_vector(1 downto 0);
-- input fifo
signal DI : std_logic_vector(31 downto 0);
signal FULL : std_logic;
signal WRERR : std_logic;
signal USB_DO_valid : std_logic;
signal DO_ready : std_logic;
signal WREN : std_logic;
signal wrerr_buf : std_logic;
signal USB_DO : std_logic_vector(15 downto 0);
signal in_data : std_logic_vector(31 downto 0);
signal wr_cnt : std_logic_vector(3 downto 0);
signal test_cnt : std_logic_vector(6 downto 0);
signal test_cs : std_logic_vector(13 downto 0);
signal in_valid : std_logic;
signal test_sync : std_logic;
signal clk_div : std_logic_vector(1 downto 0);
 
-- output fifo
signal DO : std_logic_vector(31 downto 0);
signal EMPTY : std_logic;
signal RDERR : std_logic;
signal USB_DI_ready : std_logic;
signal RDEN : std_logic;
signal rderr_buf : std_logic;
signal USB_DI_valid : std_logic;
signal rd_buf : std_logic_vector(31 downto 0);
signal rd_cnt : std_logic;
 
 
begin
bram_fifo_inst : bram_fifo
port map (
reset => reset2,
-- input fifo interface, see "7 Series Memory Resources" user guide (ug743)
DI => DI,
FULL => FULL, -- 1-bit output: Full flag
WRERR => WRERR, -- 1-bit output: Write error
WREN => WREN, -- 1-bit input: Write enable
WRCLK => ifclk, -- 1-bit input: Rising edge write clock.
-- output fifo interface, see "7 Series Memory Resources" user guide (ug743)
DO => DO,
EMPTY => EMPTY, -- 1-bit output: Empty flag
RDERR => RDERR, -- 1-bit output: Read error
RDCLK => ifclk, -- 1-bit input: Read clock
RDEN => RDEN -- 1-bit input: Read enable
);
 
ezusb_io_inst : ezusb_io
generic map (
OUTEP => 2, -- EP for FPGA -> EZ-USB transfers
INEP => 6 -- EP for EZ-USB -> FPGA transfers
)
port map (
ifclk => ifclk,
reset => reset, -- asynchronous reset input
reset_out => reset_usb, -- synchronous reset output
-- pins
ifclk_in => ifclk_in,
fd => fd,
SLWR => SLWR,
SLRD => SLRD,
SLOE => SLOE,
PKTEND => PKTEND,
FIFOADDR(0)=> FIFOADDR0,
FIFOADDR(1)=> FIFOADDR1,
EMPTY_FLAG => FLAGA,
FULL_FLAG => FLAGB,
-- signals for FPGA -> EZ-USB transfer
DI => rd_buf(15 downto 0), -- data written to EZ-USB
DI_valid => USB_DI_valid, -- 1 indicates data valid; DI and DI_valid must be hold if DI_ready is 0
DI_ready => USB_DI_ready, -- 1 if new data are accepted
DI_enable => '1', -- setting to 0 disables FPGA -> EZ-USB transfers
pktend_timeout => conv_std_logic_vector(90,16), -- timeout in multiples of 65536 clocks (approx. 0.1s @ 48 MHz) before a short packet committed
-- setting to 0 disables this feature
-- signals for EZ-USB -> FPGA transfer
DO => USB_DO, -- data read from EZ-USB
DO_valid => USB_DO_valid, -- 1 indicated valid data
DO_ready => DO_ready, -- setting to 1 enables writing new data to DO in next clock; DO and DO_valid are hold if DO_ready is 0
-- debug output
status => if_status
);
 
reset2 <= reset or reset_usb;
DO_ready <= '1' when ( (mode_buf="00") and (reset_ifclk='0') and (FULL='0') ) else '0';
-- debug board LEDs
led1 <= EMPTY & FULL & wrerr_buf & rderr_buf & if_status & FLAGB & FLAGA;
test_sync <= '1' when ( (wr_cnt="1110") or (wr_cnt(0)='1') ) else '0';
 
dpifclk: process
begin
wait until ( ifclk'EVENT and (ifclk = '1') );
 
-- reset
reset_ifclk <= reset or reset_usb;
if ( reset_ifclk = '1' ) then
rderr_buf <= '0';
wrerr_buf <= '0';
else
rderr_buf <= rderr_buf or RDERR;
wrerr_buf <= wrerr_buf or WRERR;
end if;
 
-- FPGA -> EZ-USB FIFO
if ( reset_ifclk = '1' ) then
rd_cnt <= '0';
USB_DI_valid <= '0';
else
if ( USB_DI_ready = '1' ) then
USB_DI_valid <= not EMPTY;
if ( EMPTY = '0' ) then
if ( rd_cnt = '0' ) then
rd_buf <= DO;
else
rd_buf(15 downto 0) <= rd_buf(31 downto 16);
end if;
rd_cnt <= not rd_cnt;
end if;
end if;
end if;
 
if ( (reset_ifclk = '0') and (USB_DI_ready = '1') and (EMPTY = '0') and (rd_cnt = '0')) then
RDEN <= '1';
else
RDEN <= '0';
end if;
-- data source
if ( reset_ifclk = '1' ) then
in_data <= (others => '0');
in_valid <= '0';
wr_cnt <= (others => '0');
test_cnt <=(others => '0');
test_cs <= conv_std_logic_vector(47,14);
WREN <= '0';
clk_div <= "11";
else
if ( FULL = '0' ) then
if ( in_valid = '1' ) then
DI <= in_data;
end if;
if ( mode_buf = "00" ) then
if ( USB_DO_valid = '1' ) then
in_data <= USB_DO & in_data(31 downto 16);
in_valid <= wr_cnt(0);
wr_cnt <= wr_cnt + 1;
else
in_valid <= '0';
end if;
else
if ( clk_div = "00" ) then
if ( ( wr_cnt = "1111" ) ) then
test_cs <= conv_std_logic_vector(47,14);
in_data(30 downto 24) <= test_cs(6 downto 0) xor test_cs(13 downto 7);
else
test_cnt <= test_cnt + conv_std_logic_vector(111,7);
test_cs <= test_cs + ( test_sync & test_cnt );
in_data(30 downto 24 ) <= test_cnt;
end if;
in_data(31) <= test_sync;
in_data(23 downto 0) <= in_data(31 downto 8);
in_valid <= wr_cnt(0) and wr_cnt(1);
wr_cnt <= wr_cnt + 1;
else
in_valid <= '0';
end if;
end if;
if ( (mode_buf = "01") or ( (mode_buf = "11") and (SW8='1') ) ) then
clk_div <= "00";
else
clk_div <= clk_div + 1;
end if;
end if;
end if;
if ( (reset_ifclk ='0') and (in_valid = '1') and (FULL='0') ) then
WREN <='1';
else
WREN <='0';
end if;
mode_buf <= mode;
end process dpifclk;
 
end RTL;
 

powered by: WebSVN 2.1.0

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