Line 1... |
Line 1... |
/*
|
/*!
|
* Если error срабатывает на последнем байте пакета, то он не будет отправлен, пока
|
* \brief UsB FT232H core module
|
* не придет следующий пакет
|
* \version 1.8
|
*/
|
*/
|
|
|
|
|
module usb_ft232h (
|
module usb_ft232h (
|
//Avalon-MM Slave
|
|
clk_i,
|
clk_i,
|
reset_i,
|
reset_i,
|
|
|
|
//Avalon-MM Slave
|
address_i,
|
address_i,
|
read_i,
|
read_i,
|
readdata_o,
|
readdata_o,
|
|
readdatavalid_o,
|
write_i,
|
write_i,
|
writedata_i,
|
writedata_i,
|
|
waitrequest_o,
|
|
|
//FT232H
|
//FT232H
|
usb_clk_i,
|
usb_clk_i,
|
usb_data_io,
|
usb_data_io,
|
usb_rxf_n_i,
|
usb_rxf_n_i,
|
Line 22... |
Line 25... |
usb_rd_n_o,
|
usb_rd_n_o,
|
usb_wr_n_o,
|
usb_wr_n_o,
|
usb_oe_n_o
|
usb_oe_n_o
|
);
|
);
|
|
|
parameter TX_FIFO_DEPTH = 512;
|
|
|
parameter TX_FIFO_NUMWORDS = 512;
|
parameter TX_FIFO_WIDTHU = 9;
|
parameter TX_FIFO_WIDTHU = 9;
|
parameter RX_FIFO_DEPTH = 512;
|
parameter RX_FIFO_NUMWORDS = 512;
|
parameter RX_FIFO_WIDTHU = 9;
|
parameter RX_FIFO_WIDTHU = 9;
|
|
parameter FIFOS_DELAYPIPE = 11;
|
|
|
|
parameter USB_READ_LATENCY = 1;
|
|
parameter USB_WRITE_LATENCY = 1;
|
|
|
|
parameter AVALON_CMD_LATENCY = 1;
|
|
parameter AVALON_READ_LATENCY = 1;
|
|
parameter AVALON_WRITE_LATENCY = 1;
|
|
|
localparam WRDATA_ADDR = 4'd0;
|
|
localparam RDDATA_ADDR = 4'd1;
|
|
localparam TXSTATUSL_ADDR = 4'd2;
|
|
localparam TXSTATUSH_ADDR = 4'd3;
|
|
localparam RXSTATUSL_ADDR = 4'd4;
|
|
localparam RXSTATUSH_ADDR = 4'd5;
|
|
|
|
|
|
input logic clk_i;
|
input logic clk_i;
|
input logic reset_i;
|
input logic reset_i;
|
input logic [3:0] address_i;
|
input logic [2:0] address_i;
|
input logic read_i;
|
input logic read_i;
|
output logic [7:0] readdata_o;
|
output logic [7:0] readdata_o;
|
|
output logic readdatavalid_o;
|
input logic write_i;
|
input logic write_i;
|
input logic [7:0] writedata_i;
|
input logic [7:0] writedata_i;
|
|
output logic waitrequest_o;
|
|
|
input logic usb_clk_i;
|
input logic usb_clk_i;
|
inout logic [7:0] usb_data_io;
|
inout wire [7:0] usb_data_io;
|
input logic usb_rxf_n_i;
|
input logic usb_rxf_n_i;
|
input logic usb_txe_n_i;
|
input logic usb_txe_n_i;
|
output logic usb_rd_n_o;
|
output logic usb_rd_n_o;
|
output logic usb_wr_n_o;
|
output logic usb_wr_n_o;
|
output logic usb_oe_n_o;
|
output logic usb_oe_n_o;
|
|
|
|
|
|
|
reg error;
|
|
reg rxerror;
|
|
reg [7:0] rxerrdata;
|
|
logic [15:0] txstatus;
|
|
logic [15:0] rxstatus;
|
|
|
|
reg read_pipe;
|
|
reg read_pipe2;
|
|
|
|
reg adr_data;
|
|
reg adr_txsl;
|
|
reg adr_txsh;
|
|
reg adr_rxsl;
|
|
reg adr_rxsh;
|
|
|
|
|
|
logic [7:0] txf_wrdata;
|
logic [7:0] txf_wrdata;
|
logic txf_wrclk;
|
logic txf_wrclk;
|
logic txf_wrreq;
|
logic txf_wrreq;
|
logic txf_wrfull;
|
logic txf_wrfull;
|
logic [TX_FIFO_WIDTHU-1:0] txf_wrusedw;
|
logic [TX_FIFO_WIDTHU-1:0] txf_wrusedw;
|
|
|
logic txf_rdclk;
|
logic txf_rdclk;
|
logic txf_rdreq;
|
logic txf_rdreq;
|
logic [7:0] txf_rddata;
|
logic [7:0] txf_rddata;
|
logic txf_rdempty;
|
logic txf_rdempty;
|
|
|
logic [7:0] rxf_wrdata;
|
logic [7:0] rxf_wrdata;
|
logic rxf_wrclk;
|
logic rxf_wrclk;
|
logic rxf_wrreq;
|
logic rxf_wrreq;
|
logic rxf_wrfull;
|
logic rxf_wrfull;
|
|
|
logic [RX_FIFO_WIDTHU-1:0] rxf_rdusedw;
|
logic [RX_FIFO_WIDTHU-1:0] rxf_rdusedw;
|
logic rxf_rdclk;
|
logic rxf_rdclk;
|
logic rxf_rdreq;
|
logic rxf_rdreq;
|
logic [7:0] rxf_rddata;
|
logic [7:0] rxf_rddata;
|
logic rxf_rdempty;
|
logic rxf_rdempty;
|
logic rxf_rdfull;
|
logic rxf_rdfull;
|
|
|
|
|
assign usb_data_io = ( usb_oe_n_o ) ? ( txf_rddata ) : ( {8{1'bZ}} );
|
|
|
|
assign rxf_wrclk = ~usb_clk_i;
|
|
assign txf_rdclk = usb_clk_i;
|
ft232h_fifos_interface ffi (
|
assign rxf_rdclk = clk_i;
|
.reset_i (reset_i),
|
assign txf_wrclk = ~clk_i;
|
// FT232H
|
|
.usb_clk_i (usb_clk_i),
|
assign txstatus[15] = ~txf_wrfull; //can write
|
.usb_data_io (usb_data_io),
|
assign txstatus[14:TX_FIFO_WIDTHU+1] = 0;
|
.usb_rxf_n_i (usb_rxf_n_i),
|
assign txstatus[TX_FIFO_WIDTHU] = txf_wrfull;
|
.usb_txe_n_i (usb_txe_n_i),
|
assign txstatus[TX_FIFO_WIDTHU-1:0] = ( txf_wrfull ? {TX_FIFO_WIDTHU{1'b0}} : txf_wrusedw );
|
.usb_rd_n_o (usb_rd_n_o),
|
|
.usb_wr_n_o (usb_wr_n_o),
|
assign rxstatus[15] = ~rxf_rdempty; //can read
|
.usb_oe_n_o (usb_oe_n_o),
|
assign rxstatus[14:RX_FIFO_WIDTHU+1] = 0;
|
// RX FIFO
|
assign rxstatus[RX_FIFO_WIDTHU] = rxf_rdfull;
|
.rxf_wrclk_o (rxf_wrclk),
|
assign rxstatus[RX_FIFO_WIDTHU-1:0] = ( rxf_rdempty ? {RX_FIFO_WIDTHU{1'b0}} : rxf_rdusedw );
|
.rxf_wrfull_i (rxf_wrfull),
|
|
.rxf_wrreq_o (rxf_wrreq),
|
|
.rxf_wrdata_o (rxf_wrdata),
|
|
// TX FIFO
|
|
.txf_rdclk_o (txf_rdclk),
|
|
.txf_rdempty_i (txf_rdempty),
|
|
.txf_rdreq_o (txf_rdreq),
|
|
.txf_rddata_i (txf_rddata)
|
|
);
|
|
defparam
|
|
ffi.READ_LATENCY = USB_READ_LATENCY,
|
|
ffi.WRITE_LATENCY = USB_WRITE_LATENCY;
|
|
|
|
|
|
|
dcfifo txfifo (
|
dcfifo txfifo (
|
.aclr ( reset_i ),
|
.aclr ( reset_i ),
|
.data ( txf_wrdata ),
|
.data ( txf_wrdata ),
|
Line 126... |
Line 131... |
.rdfull (),
|
.rdfull (),
|
.rdusedw (),
|
.rdusedw (),
|
.wrempty ());
|
.wrempty ());
|
defparam
|
defparam
|
txfifo.intended_device_family = "Cyclone IV E",
|
txfifo.intended_device_family = "Cyclone IV E",
|
txfifo.lpm_numwords = TX_FIFO_DEPTH,
|
txfifo.lpm_numwords = TX_FIFO_NUMWORDS,
|
txfifo.lpm_showahead = "OFF",
|
txfifo.lpm_showahead = "OFF",
|
txfifo.lpm_type = "dcfifo",
|
txfifo.lpm_type = "dcfifo",
|
txfifo.lpm_width = 8,
|
txfifo.lpm_width = 8,
|
txfifo.lpm_widthu = TX_FIFO_WIDTHU,
|
txfifo.lpm_widthu = TX_FIFO_WIDTHU,
|
txfifo.overflow_checking = "ON",
|
txfifo.overflow_checking = "ON",
|
txfifo.rdsync_delaypipe = 11,
|
txfifo.rdsync_delaypipe = FIFOS_DELAYPIPE,
|
txfifo.read_aclr_synch = "ON",
|
txfifo.read_aclr_synch = "ON",
|
txfifo.underflow_checking = "ON",
|
txfifo.underflow_checking = "ON",
|
txfifo.use_eab = "ON",
|
txfifo.use_eab = "ON",
|
txfifo.write_aclr_synch = "ON",
|
txfifo.write_aclr_synch = "ON",
|
txfifo.wrsync_delaypipe = 11;
|
txfifo.wrsync_delaypipe = FIFOS_DELAYPIPE;
|
|
|
|
|
dcfifo rxfifo (
|
dcfifo rxfifo (
|
.aclr ( reset_i ),
|
.aclr ( reset_i ),
|
.data ( rxf_wrdata ),
|
.data ( rxf_wrdata ),
|
Line 157... |
Line 162... |
.rdfull ( rxf_rdfull ),
|
.rdfull ( rxf_rdfull ),
|
.rdusedw ( rxf_rdusedw ),
|
.rdusedw ( rxf_rdusedw ),
|
.wrempty ());
|
.wrempty ());
|
defparam
|
defparam
|
rxfifo.intended_device_family = "Cyclone IV E",
|
rxfifo.intended_device_family = "Cyclone IV E",
|
rxfifo.lpm_numwords = RX_FIFO_DEPTH,
|
rxfifo.lpm_numwords = RX_FIFO_NUMWORDS,
|
rxfifo.lpm_showahead = "OFF",
|
rxfifo.lpm_showahead = "OFF",
|
rxfifo.lpm_type = "dcfifo",
|
rxfifo.lpm_type = "dcfifo",
|
rxfifo.lpm_width = 8,
|
rxfifo.lpm_width = 8,
|
rxfifo.lpm_widthu = RX_FIFO_WIDTHU,
|
rxfifo.lpm_widthu = RX_FIFO_WIDTHU,
|
rxfifo.overflow_checking = "ON",
|
rxfifo.overflow_checking = "ON",
|
rxfifo.rdsync_delaypipe = 11,
|
rxfifo.rdsync_delaypipe = FIFOS_DELAYPIPE,
|
rxfifo.read_aclr_synch = "ON",
|
rxfifo.read_aclr_synch = "ON",
|
rxfifo.underflow_checking = "ON",
|
rxfifo.underflow_checking = "ON",
|
rxfifo.use_eab = "ON",
|
rxfifo.use_eab = "ON",
|
rxfifo.write_aclr_synch = "ON",
|
rxfifo.write_aclr_synch = "ON",
|
rxfifo.wrsync_delaypipe = 11;
|
rxfifo.wrsync_delaypipe = FIFOS_DELAYPIPE;
|
|
|
|
|
|
|
/* read usb data to rx fifo */
|
usb_fifos_avalon_mm_interface ufai (
|
always_ff @( negedge rxf_wrclk or posedge reset_i )
|
.reset_i (reset_i),
|
begin
|
.clk_i (clk_i),
|
if( reset_i )
|
// Avalon-MM
|
begin
|
.address_i (address_i),
|
rxf_wrreq <= 1'b0;
|
.read_i (read_i),
|
rxf_wrdata <= 8'b0;
|
.readdata_o (readdata_o),
|
rxerror <= 1'b0;
|
.readdatavalid_o (readdatavalid_o),
|
rxerrdata <= 8'b0;
|
.write_i (write_i),
|
end
|
.writedata_i (writedata_i),
|
else
|
.waitrequest_o (waitrequest_o),
|
begin
|
// RX FIFO
|
if( ~usb_rd_n_o & rxf_wrfull )
|
.rxf_rdclk_o (rxf_rdclk),
|
begin
|
.rxf_rdempty_i (rxf_rdempty),
|
rxerror <= 1'b1;
|
.rxf_rdfull_i (rxf_rdfull),
|
rxerrdata <= usb_data_io;
|
.rxf_rdreq_o (rxf_rdreq),
|
end
|
.rxf_rddata_i (rxf_rddata),
|
|
.rxf_rdusedw_i (rxf_rdusedw),
|
if( ~rxf_wrfull & ((~usb_rd_n_o & ~usb_rxf_n_i) | rxerror) )
|
// TX FIFO
|
begin
|
.txf_wrclk_o (txf_wrclk),
|
rxf_wrreq <= 1'b1;
|
.txf_wrfull_i (txf_wrfull),
|
if( rxerror )
|
.txf_wrreq_o (txf_wrreq),
|
begin
|
.txf_wrdata_o (txf_wrdata),
|
rxerror <= 1'b0;
|
.txf_wrusedw_i (txf_wrusedw)
|
rxf_wrdata <= rxerrdata;
|
);
|
end
|
defparam
|
else
|
ufai.TX_FIFO_WIDTHU = TX_FIFO_WIDTHU,
|
rxf_wrdata <= usb_data_io;
|
ufai.RX_FIFO_WIDTHU = RX_FIFO_WIDTHU,
|
end
|
ufai.CMD_LATENCY = AVALON_CMD_LATENCY,
|
else
|
ufai.READ_LATENCY = AVALON_READ_LATENCY,
|
begin
|
ufai.WRITE_LATENCY = AVALON_WRITE_LATENCY;
|
rxf_wrreq <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
always_ff @( posedge usb_clk_i or posedge reset_i )
|
|
begin
|
|
if( reset_i )
|
|
begin
|
|
usb_oe_n_o <= 1'b1;
|
|
usb_rd_n_o <= 1'b1;
|
|
end
|
|
else
|
|
begin
|
|
if( ~usb_rxf_n_i & ~rxf_wrfull & ( usb_txe_n_i | ( ~txf_rdreq & ~error )) & ~rxerror )
|
|
begin
|
|
usb_oe_n_o <= 1'b0;
|
|
if( ~usb_oe_n_o )
|
|
usb_rd_n_o <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
usb_oe_n_o <= 1'b1;
|
|
usb_rd_n_o <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
|
|
/*---------------------------------*/
|
|
|
|
/* write tx fifo data to usb */
|
|
always_ff @( negedge txf_rdclk or posedge reset_i )
|
|
begin
|
|
if( reset_i )
|
|
begin
|
|
txf_rdreq <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
if( ~usb_txe_n_i & ~txf_rdempty & ~error & usb_oe_n_o )
|
|
begin
|
|
txf_rdreq <= 1'b1;
|
|
end
|
|
else
|
|
txf_rdreq <= 1'b0;
|
|
end
|
|
end
|
|
always_ff @( posedge usb_clk_i or posedge reset_i )
|
|
begin
|
|
if( reset_i )
|
|
begin
|
|
usb_wr_n_o <= 1'b1;
|
|
error <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
if( usb_txe_n_i & ~usb_wr_n_o )
|
|
begin
|
|
error <= 1'b1;
|
|
end
|
|
|
|
if( ~usb_txe_n_i & ( txf_rdreq | error ) & usb_oe_n_o )
|
|
begin
|
|
usb_wr_n_o <= 1'b0;
|
|
if( error )
|
|
error <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
usb_wr_n_o <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
/*-----------------------------*/
|
|
|
|
|
|
/* avalon data to tx fifo*/
|
|
always_ff @( negedge txf_wrclk or posedge reset_i )
|
|
begin
|
|
if( reset_i )
|
|
begin
|
|
txf_wrreq <= 1'b0;
|
|
txf_wrdata <= 8'b0;
|
|
end
|
|
else
|
|
begin
|
|
if( write_i & ( address_i == WRDATA_ADDR ) & ~txf_wrfull )
|
|
begin
|
|
txf_wrreq <= 1'b1;
|
|
txf_wrdata <= writedata_i;
|
|
end
|
|
else
|
|
begin
|
|
txf_wrreq <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
/*------------------------------------*/
|
|
|
|
/* rx fifo data to avalon */
|
|
always_ff @( posedge clk_i or posedge reset_i )
|
|
begin
|
|
if( reset_i )
|
|
begin
|
|
adr_data <= 1'b0;
|
|
adr_txsl <= 1'b0;
|
|
adr_txsh <= 1'b0;
|
|
adr_rxsl <= 1'b0;
|
|
adr_rxsh <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
if( read_i )
|
|
begin
|
|
if( address_i == RDDATA_ADDR )
|
|
adr_data <= 1'b1;
|
|
else
|
|
adr_data <= 1'b0;
|
|
|
|
if( address_i == TXSTATUSL_ADDR )
|
|
adr_txsl <= 1'b1;
|
|
else
|
|
adr_txsl <= 1'b0;
|
|
|
|
if( address_i == TXSTATUSH_ADDR )
|
|
adr_txsh <= 1'b1;
|
|
else
|
|
adr_txsh <= 1'b0;
|
|
|
|
if( address_i == RXSTATUSL_ADDR )
|
|
adr_rxsl <= 1'b1;
|
|
else
|
|
adr_rxsl <= 1'b0;
|
|
|
|
if( address_i == RXSTATUSH_ADDR )
|
|
adr_rxsh <= 1'b1;
|
|
else
|
|
adr_rxsh <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
|
|
always_ff @( posedge clk_i or posedge reset_i )
|
|
begin
|
|
if( reset_i )
|
|
begin
|
|
read_pipe <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
if( read_i )
|
|
read_pipe <= 1'b1;
|
|
else
|
|
read_pipe <= 1'b0;
|
|
end
|
|
end
|
|
|
|
always_ff @( negedge rxf_rdclk or posedge reset_i )
|
|
begin
|
|
if( reset_i )
|
|
begin
|
|
rxf_rdreq <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
if( read_pipe & adr_data & ~rxf_rdempty )
|
|
rxf_rdreq <= 1'b1;
|
|
else
|
|
rxf_rdreq <= 1'b0;
|
|
end
|
|
end
|
|
|
|
always_ff @( posedge clk_i or posedge reset_i )
|
|
begin
|
|
if( reset_i )
|
|
begin
|
|
read_pipe2 <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
if( read_pipe )
|
|
read_pipe2 <= 1'b1;
|
|
else
|
|
read_pipe2 <= 1'b0;
|
|
end
|
|
end
|
|
|
|
always_ff @( posedge clk_i or posedge reset_i )
|
|
begin
|
|
if( reset_i )
|
|
begin
|
|
readdata_o <= 8'b0;
|
|
end
|
|
else
|
|
begin
|
|
if( read_pipe2 )
|
|
begin
|
|
if( adr_data )
|
|
readdata_o <= rxf_rddata;
|
|
else if( adr_txsl )
|
|
readdata_o <= txstatus[7:0];
|
|
else if( adr_txsh )
|
|
readdata_o <= txstatus[15:8];
|
|
else if( adr_rxsl )
|
|
readdata_o <= rxstatus[7:0];
|
|
else if( adr_rxsh )
|
|
readdata_o <= rxstatus[15:8];
|
|
else
|
|
readdata_o <= 8'b0;
|
|
end
|
|
end
|
|
end
|
|
/*------------------------------------*/
|
|
|
|
|
|
endmodule
|
endmodule
|