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/trunk
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/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 |
|
/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; |
|