//-----------------------------------------------------------------------------
// customised example Cortex-M0 controller UART with file logging
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Flynn (d.w.flynn@soton.ac.uk)
//
// Copyright © 2022, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Abstract : FT1248 1-bit data off-chip interface (emulate FT232H device)
// and allows cmsdk_uart_capture testbench models to log ADP ip, op streams
//-----------------------------------------------------------------------------
module cmsdk_ft1248x1_adpio
#(parameter ADPFILENAME = "adp.cmd",
parameter VERBOSE = 0)
(
input wire ft_clk_i, // SCLK
input wire ft_ssn_i, // SS_N
output wire ft_miso_o, // MISO
inout wire ft_miosio_io, // MIOSIO tristate output when enabled
output wire FTDI_CLK2UART_o, // Clock (baud rate)
output wire FTDI_OP2UART_o, // Received data to UART capture
output wire FTDI_IP2UART_o // Transmitted data to UART capture
);
//----------------------------------------------
//-- File I/O
//----------------------------------------------
integer fdcmd; // channel descriptor for cmd file input
integer ch;
`define EOF -1
reg ft_rxreq;
wire ft_rxack;
reg [7:0] ft_adpbyte;
initial
begin
ft_rxreq <= 0;
$timeformat(-9, 0, " ns", 14);
fdcmd= $fopen(ADPFILENAME,"r");
if (fdcmd == 0)
$write("** FT1248x1 : no command file **\n");
else begin
ch = $fgetc(fdcmd);
while (ch != `EOF) begin
ft_adpbyte <= (ch & 8'hff);
ft_rxreq <= 1'b1;
while (ft_ssn_i == 1'b0)
@(posedge ft_ssn_i);
@(posedge ft_rxack);
ft_rxreq <=0;
@(negedge ft_rxack);
ch = $fgetc(fdcmd);
end
end
$fclose(fdcmd);
ft_rxreq <= 0;
end
//----------------------------------------------
//-- State Machine
//----------------------------------------------
wire ft_miosio_i;
wire ft_miosio_o;
wire ft_miosio_z;
// tri-state pad control for MIOSIO
assign ft_miosio_io = (ft_miosio_z) ? 1'bz : ft_miosio_o;
// add notinal delay on inout to ensure last "half-bit" on FT1248TXD is sampled before tri-stated
assign #1 ft_miosio_i = ft_miosio_io;
reg [4:0] ft_state; // 17-state for bit-serial
wire [5:0] ft_nextstate = ft_state + 5'b00001;
always @(posedge ft_clk_i or posedge ft_ssn_i)
if (ft_ssn_i)
ft_state <= 5'b11111;
else // loop if multi-data
// ft_state <= (ft_state == 5'b01111) ? 5'b01000 : ft_nextstate;
ft_state <= ft_nextstate;
// 16: bus turnaround (or bit[5])
// 0 for CMD3
// 3 for CMD2
// 5 for CMD1
// 6 for CMD0
// 7 for cmd turnaround
// 8 for data bit0
// 9 for data bit1
// 10 for data bit2
// 11 for data bit3
// 12 for data bit4
// 13 for data bit5
// 14 for data bit6
// 15 for data bit7
// ft_miso_o reflects RXE when deselected
assign ft_miso_o = (ft_ssn_i) ? !ft_rxreq : (ft_state == 5'b00111);
// capture CMD on falling edge of clock (mid-data)
// - valid sample ready after 7th edge (ready RX or TX data phase functionality)
reg [7:0] ft_cmd;
always @(negedge ft_clk_i or posedge ft_ssn_i)
if (ft_ssn_i)
ft_cmd <= 8'b00000001;
else // shift in data
ft_cmd <= (!ft_state[3] & !ft_nextstate[3]) ? {ft_cmd[6:0],ft_miosio_i} : ft_cmd;
wire ft_cmd_valid = ft_cmd[7];
wire ft_cmd_rxd = ft_cmd[7] & !ft_cmd[6] & !ft_cmd[3] & !ft_cmd[1] & ft_cmd[0];
wire ft_cmd_txd = ft_cmd[7] & !ft_cmd[6] & !ft_cmd[3] & !ft_cmd[1] & !ft_cmd[0];
// tristate enable for miosio (deselected status or serialized data for read command)
wire ft_miosio_e = ft_ssn_i | (ft_cmd_rxd & !ft_state[4] & ft_state[3]);
assign ft_miosio_z = !ft_miosio_e;
// serial data formatted with start bit for UART capture (on rising uart-clock)
assign FTDI_CLK2UART_o = !ft_clk_i;
// suitable for CMSDK UART capture IO
// inject a start bit low else mark high
assign FTDI_OP2UART_o = (ft_cmd_txd & (ft_state[4:3]) == 2'b01) ? ft_miosio_i : !(ft_cmd_txd & (ft_state == 5'b00111));
assign FTDI_IP2UART_o = (ft_cmd_rxd & (ft_state[4:3]) == 2'b01) ? ft_miosio_io : !(ft_cmd_rxd & (ft_state == 5'b00111));
// capture RXD on falling edge of clock
reg [8:0] ft_rxd;
always @(negedge ft_clk_i or posedge ft_ssn_i)
if (ft_ssn_i)
ft_rxd <= 9'b111111111;
else if (ft_cmd_txd & !(ft_miosio_i & (&ft_rxd[8:0]))) //only on valid start-bit
ft_rxd <= {ft_miosio_i, ft_rxd[8:1]};
// shift TXD on rising edge of clock
reg [8:0] ft_txd;
always @(posedge ft_clk_i or posedge ft_ssn_i)
if (ft_ssn_i)
ft_txd <= {1'b1,ft_adpbyte};
else if (ft_rxreq & ft_cmd_rxd & (ft_state[4:3] == 2'b01)) //valid TX shift
ft_txd <= {1'b0,ft_txd[8:1]};
assign ft_rxack = (ft_cmd_rxd & (ft_state==5'b01111));
// ft_miso_o reflects TXF when deselected (never full for simulation output)
assign ft_miosio_o = (ft_ssn_i) ? 1'b0 : ft_txd[0];
endmodule
This page: |
Created: | Mon Jul 4 11:27:23 2022 |
|
From: |
../verilog/cmsdk_ft1248x1_adpio.v |