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

Subversion Repositories ftdi_wb_bridge

[/] [ftdi_wb_bridge/] [trunk/] [rtl/] [ftdi_sync.v] - Rev 2

Compare with Previous | Blame | View Log

//-----------------------------------------------------------------
//                 FTDI Asynchronous FIFO Interface
//                              V0.1
//                        Ultra-Embedded.com
//                          Copyright 2015
//
//                 Email: admin@ultra-embedded.com
//
//                         License: GPL
// If you would like a version with a more permissive license for
// use in closed source commercial applications please contact me
// for details.
//-----------------------------------------------------------------
//
// This file is open source HDL; you can redistribute it and/or 
// modify it under the terms of the GNU General Public License as 
// published by the Free Software Foundation; either version 2 of 
// the License, or (at your option) any later version.
//
// This file 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 file; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module: ftdi_sync - Async FT245 FIFO interface
//-----------------------------------------------------------------
module ftdi_sync
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
#(
    parameter       CLK_DIV = 0    // 0 - X
)
 
//-----------------------------------------------------------------
// Ports
//-----------------------------------------------------------------
(
    input           clk_i,
    input           rst_i,
 
    // FTDI (async FIFO interface)
    input           ftdi_rxf_i,
    input           ftdi_txe_i,
    output          ftdi_siwua_o,
    output reg      ftdi_wr_o,
    output reg      ftdi_rd_o,
    inout [7:0]     ftdi_d_io,
 
    // Synchronous Interface
    output [7:0]    data_o,
    input [7:0]     data_i,
    input           wr_i,
    input           rd_i,
    output          wr_accept_o,
    output reg      rd_ready_o
);
 
//-----------------------------------------------------------------
// Defines / Local params
//-----------------------------------------------------------------
localparam STATE_W           = 2;
localparam STATE_IDLE        = 2'd0;
localparam STATE_TX_SETUP    = 2'd1;
localparam STATE_TX          = 2'd2;
localparam STATE_RX          = 2'd3;
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
 
// Xilinx placement pragmas:
//synthesis attribute IOB of tx_data_q is "TRUE"
//synthesis attribute IOB of ftdi_rd_o is "TRUE"
//synthesis attribute IOB of ftdi_wr_o is "TRUE"
 
// Current state
reg [STATE_W-1:0]      state_q;
 
reg                    tx_ready_q;
 
reg                    ftdi_rxf_ms_q;
reg                    ftdi_txe_ms_q;
reg                    ftdi_rxf_q;
reg                    ftdi_txe_q;
 
reg [7:0]              rx_data_q;
reg [7:0]              tx_data_q;
 
//-----------------------------------------------------------------
// Resample async signals
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
begin
    ftdi_rxf_ms_q   <= 1'b1;
    ftdi_txe_ms_q   <= 1'b1;
    ftdi_rxf_q      <= 1'b1;
    ftdi_txe_q      <= 1'b1;
end
else
begin
    ftdi_rxf_q      <= ftdi_rxf_ms_q;
    ftdi_rxf_ms_q   <= ftdi_rxf_i;
 
    ftdi_txe_q      <= ftdi_txe_ms_q;
    ftdi_txe_ms_q   <= ftdi_txe_i;
end
 
//-----------------------------------------------------------------
// Clock divider
//-----------------------------------------------------------------
reg [CLK_DIV:0] clk_div_q;
 
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
    clk_div_q <= {1'b1, {(CLK_DIV){1'b0}}};
else if (CLK_DIV > 0)
    clk_div_q <= {clk_div_q[0], clk_div_q[CLK_DIV:1]};
else
    clk_div_q <= ~clk_div_q;
 
wire clk_en_w = clk_div_q[0];
 
//-----------------------------------------------------------------
// Sample flag
//-----------------------------------------------------------------
// Sample read data when both RD# and RXF# are low
wire rx_sample_w = (state_q == STATE_RX) & clk_en_w;
 
// Target accepts data when WR# and TXE# are low
wire tx_sent_w   = (state_q == STATE_TX) & clk_en_w;
 
wire rx_ready_w = ~ftdi_rxf_q & clk_en_w;
wire tx_space_w = ~ftdi_txe_q & clk_en_w;
 
wire rx_start_w  = (state_q == STATE_IDLE) & rx_ready_w & !rd_ready_o;
wire tx_start_w  = (state_q == STATE_IDLE) & tx_space_w & tx_ready_q;
 
//-----------------------------------------------------------------
// Next State Logic
//-----------------------------------------------------------------
reg [STATE_W-1:0] next_state_r;
always @ *
begin
    next_state_r = state_q;
 
    case (state_q)
    //-----------------------------------------
    // STATE_IDLE
    //-----------------------------------------
    STATE_IDLE :
    begin
        if (rx_start_w)
            next_state_r    = STATE_RX;
        else if (tx_start_w)
            next_state_r    = STATE_TX_SETUP;
    end
    //-----------------------------------------
    // STATE_RX
    //-----------------------------------------
    STATE_RX :
    begin
        if (clk_en_w)
            next_state_r  = STATE_IDLE;
    end
    //-----------------------------------------
    // STATE_TX_SETUP
    //-----------------------------------------
    STATE_TX_SETUP :
    begin
        if (clk_en_w)
            next_state_r  = STATE_TX;
    end
    //-----------------------------------------
    // STATE_TX
    //-----------------------------------------
    STATE_TX :
    begin
        if (clk_en_w)
            next_state_r  = STATE_IDLE;
    end    
    default:
        ;
   endcase
end
 
// Update state
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
    state_q   <= STATE_IDLE;
else
    state_q   <= next_state_r;
 
//-----------------------------------------------------------------
// rd_ready_o
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
    rd_ready_o <= 1'b0;
else if (rx_sample_w)
    rd_ready_o <= 1'b1;
else if (rd_i)
    rd_ready_o <= 1'b0;
 
//-----------------------------------------------------------------
// tx_ready_q
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
    tx_ready_q <= 1'b0;
else if (tx_sent_w)
    tx_ready_q <= 1'b0;
else if (wr_i)
    tx_ready_q <= 1'b1;
 
assign wr_accept_o = !tx_ready_q;
 
//-----------------------------------------------------------------
// RD#
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
    ftdi_rd_o <= 1'b1;
else if (rx_start_w)
    ftdi_rd_o <= 1'b0;
else if (rx_sample_w)
    ftdi_rd_o <= 1'b1;
 
//-----------------------------------------------------------------
// WR#
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
    ftdi_wr_o <= 1'b1;
else if ((state_q == STATE_TX_SETUP) && clk_en_w)
    ftdi_wr_o <= 1'b0;
else if (tx_sent_w)
    ftdi_wr_o <= 1'b1;
 
//-----------------------------------------------------------------
// Rx Data
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
    rx_data_q <= 8'b0;
else if (rx_sample_w)
    rx_data_q <= ftdi_d_io;
 
//-----------------------------------------------------------------
// Tx Data
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
    tx_data_q <= 8'b0;
else if (wr_i && wr_accept_o)
    tx_data_q <= data_i;
 
//-----------------------------------------------------------------
// Outputs
//-----------------------------------------------------------------
 
// Tristate output
assign ftdi_d_io    = (state_q == STATE_TX_SETUP || state_q == STATE_TX) ? tx_data_q : 8'hzz;
assign ftdi_siwua_o = 1'b1;
 
assign data_o       = rx_data_q;
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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