Skip to content
Snippets Groups Projects
Commit db6019d6 authored by dam1n19's avatar dam1n19
Browse files

Started Moving IP into Repo

parent e6060212
No related branches found
No related tags found
No related merge requests found
//-----------------------------------------------------------------------------
// NanoSoC ASCII Debug Protocol Controller
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Flynn (d.w.flynn@soton.ac.uk)
//
// Copyright � 2021-2, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
// TODO: DM - I think this file is redundant if we move to nanosoc_manager_adp
module nanosoc_stream_adp_io #(
parameter PROMPT_CHAR = "]"
)(
// Ports of Axi Slave Bus Interface com_rx
input wire ahb_hclk,
input wire ahb_hresetn,
output wire com_rx_tready,
input wire [7:0] com_rx_tdata,
input wire com_rx_tvalid,
// Ports of Axi Master Bus Interface com_tx
output wire com_tx_tvalid,
output wire [7:0] com_tx_tdata,
input wire com_tx_tready,
// Ports of Axi Slave Bus Interface stdio_rx
output wire stdio_rx_tready,
input wire [7:0] stdio_rx_tdata,
input wire stdio_rx_tvalid,
// Ports of Axi Master Bus Interface stdio_tx
output wire stdio_tx_tvalid,
output wire [7:0] stdio_tx_tdata,
input wire stdio_tx_tready,
output wire [7 : 0] gpo8,
input wire [7 : 0] gpi8,
output wire [31:0] ahb_haddr,
output wire [ 2:0] ahb_hburst,
output wire ahb_hmastlock,
output wire [ 3:0] ahb_hprot,
output wire [ 2:0] ahb_hsize,
output wire [ 1:0] ahb_htrans,
output wire [31:0] ahb_hwdata,
output wire ahb_hwrite,
input wire [31:0] ahb_hrdata,
input wire ahb_hready,
input wire ahb_hresp
);
nanosoc_adp_control #(
.PROMPT_CHAR (PROMPT_CHAR)
) u_adp_control (
.HCLK (ahb_hclk ),
.HRESETn (ahb_hresetn ),
.HADDR32_o (ahb_haddr ),
.HBURST3_o (ahb_hburst ),
.HMASTLOCK_o (ahb_hmastlock ),
.HPROT4_o (ahb_hprot ),
.HSIZE3_o (ahb_hsize ),
.HTRANS2_o (ahb_htrans ),
.HWDATA32_o (ahb_hwdata ),
.HWRITE_o (ahb_hwrite ),
.HRDATA32_i (ahb_hrdata ),
.HREADY_i (ahb_hready ),
.HRESP_i (ahb_hresp ),
.GPO8_o (gpo8 ),
.GPI8_i (gpi8 ),
.COMRX_TREADY_o(com_rx_tready),
.COMRX_TDATA_i(com_rx_tdata),
.COMRX_TVALID_i(com_rx_tvalid),
.STDRX_TREADY_o(stdio_rx_tready),
.STDRX_TDATA_i(stdio_rx_tdata),
.STDRX_TVALID_i(stdio_rx_tvalid),
.COMTX_TVALID_o(com_tx_tvalid),
.COMTX_TDATA_o(com_tx_tdata),
.COMTX_TREADY_i(com_tx_tready),
.STDTX_TVALID_o(stdio_tx_tvalid),
.STDTX_TDATA_o(stdio_tx_tdata),
.STDTX_TREADY_i(stdio_tx_tready)
);
endmodule
This diff is collapsed.
//-----------------------------------------------------------------------------
// SoCShute Top-level FT1248-AHB Debug Controller
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Mapstone (d.a.mapstone@soton.ac.uk)
//
// Copyright � 2021-3, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
module socshute_ahb #(
parameter PROMPT_CHAR = "]"
)(
// AHB-lite Master Interface
input wire HCLK,
input wire HRESETn,
output wire [31:0] HADDR32_o,
output wire [ 2:0] HBURST3_o,
output wire HMASTLOCK_o,
output wire [ 3:0] HPROT4_o,
output wire [ 2:0] HSIZE3_o,
output wire [ 1:0] HTRANS2_o,
output wire [31:0] HWDATA32_o,
output wire HWRITE_o,
input wire [31:0] HRDATA32_i,
input wire HREADY_i,
input wire HRESP_i,
// APB Slave Interface
input wire PCLK, // Clock
input wire PCLKG, // Gated Clock
input wire PRESETn, // Reset
input wire PSEL, // Device select
input wire [11:2] PADDR, // Address
input wire PENABLE, // Transfer control
input wire PWRITE, // Write control
input wire [31:0] PWDATA, // Write data
output wire [31:0] PRDATA, // Read data
output wire PREADY, // Device ready
output wire PSLVERR, // Device error response
// GPIO interface
output wire [ 7:0] GPO8_o,
input wire [ 7:0] GPI8_i
);
// COMIO interface
wire [ 7:0] COMRX_TDATA_i;
wire COMRX_TVALID_i;
wire COMRX_TREADY_o;
wire [ 7:0] COMTX_TDATA_o;
wire COMTX_TVALID_o;
wire COMTX_TREADY_i;
// STDIO interface
wire [ 7:0] STDRX_TDATA_i;
wire STDRX_TVALID_i;
wire STDRX_TREADY_o;
wire [ 7:0] STDTX_TDATA_o;
wire STDTX_TVALID_o;
wire STDTX_TREADY_i;
// Instantiation of USRT Device
socshute_apb_usrt u_apb_usrt_com (
.PCLK (PCLK), // Peripheral clock
.PCLKG (PCLKG), // Gated PCLK for bus
.PRESETn (PRESETn), // Reset
.PSEL (PSEL), // APB interface inputs
.PADDR (PADDR),
.PENABLE (PENABLE),
.PWRITE (PWRITE),
.PWDATA (PWDATA),
.PRDATA (PRDATA), // APB interface outputs
.PREADY (PREADY),
.PSLVERR (PSLVERR),
.ECOREVNUM (4'h0), // Engineering-change-order revision bits
.TX_VALID_o (stdio_rx_valid),
.TX_DATA8_o (stdio_rx_data8),
.TX_READY_i (stdio_rx_ready),
.RX_VALID_i (stdio_tx_valid),
.RX_DATA8_i (stdio_tx_data8),
.RX_READY_o (stdio_tx_ready),
.TXINT ( ), // Transmit Interrupt
.RXINT ( ), // Receive Interrupt
.TXOVRINT ( ), // Transmit Overrun Interrupt
.RXOVRINT ( ), // Receive Overrun Interrupt
.UARTINT ( ) // Combined Interrupt
);
// Instantiation of FT1248 Bus Master
// Instantiation of ADP AHB Controller
endmodule
\ No newline at end of file
This diff is collapsed.
//-----------------------------------------------------------------------------
// SoCShute FTDI FT1248 Interface to AXI-Stream Controller
// 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)
//-----------------------------------------------------------------------------
module socshute_ft1248_stream #(
parameter integer FT1248_WIDTH = 1, // FTDI Interface 1,2,4 width supported
parameter integer FT1248_CLKON = 1 // FTDI clock always on - else quiet when no access
)(
// IO pad interface - to FT232R configured in 1/2/4/8 mode
output wire ft_clk_o, // SCLK
output wire ft_ssn_o, // SS_N
input wire ft_miso_i, // MISO
output wire [FT1248_WIDTH-1:0] ft_miosio_o, // MIOSIO tristate output when enabled
output wire [FT1248_WIDTH-1:0] ft_miosio_e, // MIOSIO tristate output enable (active hi)
output wire [FT1248_WIDTH-1:0] ft_miosio_z, // MIOSIO tristate output enable (active lo)
input wire [FT1248_WIDTH-1:0] ft_miosio_i, // MIOSIO tristate input
input wire [7:0] ft_clkdiv, // divider prescaler to ensure SCLK <1MHz
input wire clk,
input wire resetn,
// Ports of Axi Master Bus Interface TXD - To ADP Controller
output wire txd_tvalid,
output wire [7:0] txd_tdata,
output wire txd_tlast,
input wire txd_tready,
// Ports of Axi Slave Bus Interface RXD - To
output wire rxd_tready,
input wire [7:0] rxd_tdata,
input wire rxd_tlast,
input wire rxd_tvalid
);
//----------------------------------------------
//-- State Machine encoding
//----------------------------------------------
// Explicit FSM state bit assignment
// bit [0] SCLK
// bit [1] MIO_OE
// bit [2] CMD/W
// bit [3] DAT/R
// bit [4] SSEL
localparam FT_0_IDLE = 5'b00000;
localparam FT_1_IDLE = 5'b00001;
localparam FT_ZCMD_CLKLO = 5'b10100;
localparam FT_CMD_CLKHI = 5'b10111;
localparam FT_CMD_CLKLO = 5'b10110;
localparam FT_ZBT_CLKHI = 5'b10001;
localparam FT_ZBT_CLKLO = 5'b10000;
localparam FT_WD_CLKHI = 5'b11111;
localparam FT_WD_CLKLO = 5'b11110;
localparam FT_ZWD_CLKLO = 5'b11100;
localparam FT_RD_CLKHI = 5'b11001;
localparam FT_RD_CLKLO = 5'b11000;
reg [4:0] ft_state;
// 9- bit shift register to support 8-bit data + 1 sequence control flag
// write data uses bits[7:0], with bit[8] set to flag length for serialized transfers
// read data uses bits[8:1], with bit[0] set to flag continuation for serialized transfers
reg [8:0] ft_reg;
//----------------------------------------------
//-- IO PAD control, parameterized on WIDTH param
//----------------------------------------------
wire bwid8 = (FT1248_WIDTH==8);
wire bwid4 = (FT1248_WIDTH==4);
wire bwid2 = (FT1248_WIDTH==2);
wire bwid1 = (FT1248_WIDTH==1);
wire [7:0] ft_rdmasked;
generate
if (FT1248_WIDTH == 8) begin
assign ft_rdmasked[7:1] = ft_miosio_i[7:1];
assign ft_miosio_o[7:1] = ft_reg[7:1];
assign ft_miosio_e[7:1] = {7{ft_state[1]}};
assign ft_miosio_z[7:1] = ~{7{ft_state[1]}};
end
endgenerate
generate
if (FT1248_WIDTH == 4) begin
assign ft_rdmasked[7:1] = {4'b1111, ft_miosio_i[3:1]};
assign ft_miosio_o[3:1] = ft_reg[3:1];
assign ft_miosio_e[3:1] = {3{ft_state[1]}};
assign ft_miosio_z[3:1] = ~{3{ft_state[1]}};
end
endgenerate
generate
if (FT1248_WIDTH == 2) begin
assign ft_rdmasked[7:1] = {6'b111111, ft_miosio_i[1]};
assign ft_miosio_o[1] = ft_reg[1];
assign ft_miosio_e[1] = ft_state[1];
assign ft_miosio_z[1] = ~ft_state[1];
end
endgenerate
generate
if (FT1248_WIDTH == 1) begin
assign ft_rdmasked[7:1] = 7'b1111111;
end
endgenerate
assign ft_rdmasked[0] = ft_miosio_i[0];
assign ft_miosio_o[0] = ft_reg[0];
assign ft_miosio_e[0] = ft_state[1];
assign ft_miosio_z[0] = ~ft_state[1];
assign ft_clk_o = ft_state[0];
assign ft_ssn_o = !ft_state[4];
// diagnostic decodes
//wire ft_cmd = !ft_state[3] & ft_state[2];
//wire ft_dwr = ft_state[3] & ft_state[2];
//wire ft_drd = ft_state[3] & !ft_state[2];
//----------------------------------------------
//-- Internal clock prescaler
//----------------------------------------------
// clock prescaler, ft_clken enables serial IO engine clocking
reg [7:0] ft_clkcnt_r;
reg ft_clken;
always @(posedge clk or negedge resetn )
begin
if (!resetn) begin
ft_clkcnt_r <= 0;
ft_clken <= 0;
end
else begin
ft_clken <= (ft_clkcnt_r == ft_clkdiv);
ft_clkcnt_r <= (ft_clkcnt_r == ft_clkdiv) ? 0 : (ft_clkcnt_r +1);
end
end
//----------------------------------------------
//-- Internal "synchronizers" (dual stage)
//----------------------------------------------
// synchronizers for channel ready flags when idle
// (treat these signals as synchronous during transfer sequencing)
reg ft_miso_i_sync;
reg ft_miosio_i0_sync;
reg ft_miso_i_sync_1;
reg ft_miosio_i0_sync_1;
always @(posedge clk or negedge resetn )
begin
if (!resetn) begin
ft_miso_i_sync_1 <= 1;
ft_miosio_i0_sync_1 <= 1;
ft_miso_i_sync <= 1;
ft_miosio_i0_sync <= 1;
end
else begin
ft_miso_i_sync_1 <= ft_miso_i;
ft_miosio_i0_sync_1 <= ft_miosio_i[0];
ft_miso_i_sync <= ft_miso_i_sync_1;
ft_miosio_i0_sync <= ft_miosio_i0_sync_1;
end
end
//----------------------------------------------
//-- AXI Stream interface handshakes
//----------------------------------------------
reg ft_txf; // FTDI Transmit channel Full
reg ft_rxe; // FTDO Receive channel Empty
reg ft_wcyc; // read access committed
reg ft_nak; // check for NAK terminate
// TX stream delivers valid FT1248 read data transfer
// 8-bit write port with extra top-bit used as valid qualifer
reg [8:0] txdata;
assign txd_tdata = txdata[7:0];
assign txd_tvalid = txdata[8];
// activate if RX channel data and the stream buffer is not full
wire ft_rxreq = !ft_rxe & !txdata[8];
// RX stream handshakes on valid FT1248 write data transfer
reg rxdone;
reg rxrdy;
assign rxd_tready = rxdone;
// activate if TX channel not full and and the stream buffer data valid
wire ft_txreq = !ft_txf & rxd_tvalid; // & !rxdone; // FTDI TX data ready and rxstream ready
// FTDI1248 commands
wire [3:0] wcmd = 4'b0000; // write request
wire [3:0] rcmd = 4'b0001; // read request
wire [3:0] fcmd = 4'b0100; // write flush request
//wire [3:0] rcmd = 4'b1000; // read request BE bit-pattern
//wire [3:0] fcmd = 4'b0010; // write flush request BE bit-pattern
// and full FT1248 command bit patterns (using top-bits for shift sequencing)
wire [8:0] wcmdpatt = {2'b11, wcmd[0], wcmd[1], 1'b0, wcmd[2], 1'b0, 1'b0, wcmd[3]};
wire [8:0] rcmdpatt = {2'b11, rcmd[0], rcmd[1], 1'b0, rcmd[2], 1'b0, 1'b0, rcmd[3]};
reg ssn_del;
always @(posedge clk or negedge resetn)
if (!resetn)
ssn_del <= 1'b1;
else if (ft_clken)
ssn_del <= ft_ssn_o;
wire ssn_start = ft_ssn_o & ssn_del;
// FTDI1248 state machine
always @(posedge clk or negedge resetn)
if (!resetn) begin
ft_state <= FT_0_IDLE;
ft_reg <= 0;
txdata <= 0;
rxdone <= 0;
ft_wcyc <= 0;
ft_txf <= 1; // ftdi channel TXE# ('1' full)
ft_rxe <= 1; // ftdi channel RXF# ('1' empty)
ft_nak <= 0;
end else begin
ft_txf <= (ft_state==FT_0_IDLE) ? (ft_miosio_i[0] | ft_miosio_i0_sync) : 1'b1; //ft_txf & !( ft_wcyc &(ft_state==FT_ZBT_CLKHI) & ft_miso_i);
ft_rxe <= (ft_state==FT_0_IDLE) ? (ft_miso_i | ft_miso_i_sync) : 1'b1; //ft_rxe & !(!ft_wcyc & (ft_state==FT_ZBT_CLKHI) & ft_miso_i);
txdata[8] <= txdata[8] & !txd_tready; // tx_valid handshake
rxdone <= (ft_clken & (ft_state==FT_ZWD_CLKLO) & !ft_nak) | (rxdone & !rxd_tvalid); // hold until acknowledged
if (ft_clken)
case (ft_state)
FT_0_IDLE: begin // RX req priority
if (ssn_start & ft_rxreq) begin ft_reg <= rcmdpatt; ft_state <= FT_ZCMD_CLKLO; end
else if (ssn_start & ft_txreq) begin ft_reg <= wcmdpatt; ft_state <= FT_ZCMD_CLKLO; ft_wcyc <= 1; end
else ft_state <= (!ft_txf | !ft_rxe | (FT1248_CLKON!=0)) ? FT_1_IDLE : FT_0_IDLE;
end
FT_1_IDLE:
ft_state <= FT_0_IDLE;
FT_ZCMD_CLKLO:
ft_state <= FT_CMD_CLKHI;
FT_CMD_CLKHI:
ft_state <= FT_CMD_CLKLO;
FT_CMD_CLKLO: // 2, 4 or 7 shifts
if (bwid8) begin ft_reg <= FT_ZBT_CLKHI; end
else if (bwid4) begin ft_reg <= {4'b0000,ft_reg[8:4]}; ft_state <= (|ft_reg[8:5]) ? FT_CMD_CLKHI : FT_ZBT_CLKHI; end
else if (bwid2) begin ft_reg <= { 2'b00,ft_reg[8:2]}; ft_state <= (|ft_reg[8:3]) ? FT_CMD_CLKHI : FT_ZBT_CLKHI; end
else begin ft_reg <= { 1'b0,ft_reg[8:1]}; ft_state <= (|ft_reg[8:3]) ? FT_CMD_CLKHI : FT_ZBT_CLKHI; end
FT_ZBT_CLKHI:
ft_state <= FT_ZBT_CLKLO;
FT_ZBT_CLKLO:
if (ft_wcyc) begin ft_reg <= {1'b1,rxd_tdata}; ft_state <= FT_WD_CLKHI; end
else begin ft_reg <= 9'b011111111; ft_state <= FT_RD_CLKHI; end
FT_WD_CLKHI:
if (ft_miso_i & ft_reg[8]) begin ft_nak <= 1'b1; ft_state <= FT_ZWD_CLKLO; end // NAK terminate on first cycle
else if (bwid8) ft_state <= (ft_reg[8]) ? FT_WD_CLKLO : FT_ZWD_CLKLO; // special case repeat on write data
else if (bwid4) ft_state <= (|ft_reg[8:5]) ? FT_WD_CLKLO : FT_ZWD_CLKLO;
else if (bwid2) ft_state <= (|ft_reg[8:3]) ? FT_WD_CLKLO : FT_ZWD_CLKLO;
else ft_state <= (|ft_reg[8:2]) ? FT_WD_CLKLO : FT_ZWD_CLKLO;
FT_WD_CLKLO:
if (bwid8) begin ft_reg <= { 1'b0,ft_reg[7:0]}; ft_state <= FT_WD_CLKHI; end // clear top flag
else if (bwid4) begin ft_reg <= {4'b0000,ft_reg[8:4]}; ft_state <= FT_WD_CLKHI; end // shift 4 bits right
else if (bwid2) begin ft_reg <= { 2'b00,ft_reg[8:2]}; ft_state <= FT_WD_CLKHI; end // shift 2 bits right
else begin ft_reg <= { 1'b0,ft_reg[8:1]}; ft_state <= FT_WD_CLKHI; end // shift 1 bit right
FT_ZWD_CLKLO:
if (ft_nak) begin ft_nak<= 1'b0; ft_state <= FT_0_IDLE; ft_wcyc <= 1'b0; end // terminate without TX handshake
else begin ft_state <= FT_0_IDLE; ft_wcyc <= 1'b0; end
FT_RD_CLKHI: // capture iodata pins end of CLKHI phase
if (ft_miso_i & (&ft_reg[7:0])) begin ft_nak <= 1'b1; ft_state <= FT_RD_CLKLO; end // NAK terminate on first cycle
else if (bwid8) begin ft_reg <= (ft_reg[0]) ? {ft_rdmasked[7:0],1'b1} : {ft_reg[8:1],1'b0}; ft_state <= FT_RD_CLKLO; end // 8-bit read twice
else if (bwid4) begin ft_reg <= {ft_rdmasked[3:0],ft_reg[8:4]}; ft_state <= FT_RD_CLKLO; end
else if (bwid2) begin ft_reg <= {ft_rdmasked[1:0],ft_reg[8:2]}; ft_state <= FT_RD_CLKLO; end
else begin ft_reg <= {ft_rdmasked[ 0],ft_reg[8:1]}; ft_state <= FT_RD_CLKLO; end
FT_RD_CLKLO:
if (ft_nak) begin ft_nak<= 1'b0; ft_state <= FT_0_IDLE; txdata <= 9'b0; end // terminate without TX handshake
else if (ft_reg[0]) begin ft_state <= FT_RD_CLKHI; ft_reg[0] <= !(bwid8); end // loop until all 8 bits shifted in (or 8-bit read repeated)
else begin ft_state <= FT_0_IDLE; txdata <= {1'b1,ft_reg[8:1]}; end
default:
ft_state <= FT_0_IDLE;
endcase
end
endmodule
`timescale 1 ns / 1 ps
module axi_stream_io_v1_0 #
(
// Users to add parameters here
// User parameters ends
// Do not modify the parameters beyond this line
// Parameters of Axi Slave Bus Interface axi
parameter integer C_axi_DATA_WIDTH = 32,
parameter integer C_axi_ADDR_WIDTH = 4,
// Parameters of Axi Master Bus Interface tx
parameter integer C_tx_TDATA_WIDTH = 8,
parameter integer C_tx_START_COUNT = 3,
// Parameters of Axi Slave Bus Interface rx
parameter integer C_rx_TDATA_WIDTH = 8
)
(
// Users to add ports here
// User ports ends
// Do not modify the ports beyond this line
// Ports of Axi Slave Bus Interface axi
input wire axi_aclk,
input wire axi_aresetn,
input wire [C_axi_ADDR_WIDTH-1 : 0] axi_awaddr,
input wire [2 : 0] axi_awprot,
input wire axi_awvalid,
output wire axi_awready,
input wire [C_axi_DATA_WIDTH-1 : 0] axi_wdata,
input wire [(C_axi_DATA_WIDTH/8)-1 : 0] axi_wstrb,
input wire axi_wvalid,
output wire axi_wready,
output wire [1 : 0] axi_bresp,
output wire axi_bvalid,
input wire axi_bready,
input wire [C_axi_ADDR_WIDTH-1 : 0] axi_araddr,
input wire [2 : 0] axi_arprot,
input wire axi_arvalid,
output wire axi_arready,
output wire [C_axi_DATA_WIDTH-1 : 0] axi_rdata,
output wire [1 : 0] axi_rresp,
output wire axi_rvalid,
input wire axi_rready,
output wire interrupt,
// Ports of Axi Master Bus Interface tx
output wire tx_tvalid,
output wire [C_tx_TDATA_WIDTH-1 : 0] tx_tdata,
output wire [(C_tx_TDATA_WIDTH/8)-1 : 0] tx_tstrb,
output wire tx_tlast,
input wire tx_tready,
// Ports of Axi Slave Bus Interface rx
output wire rx_tready,
input wire [C_rx_TDATA_WIDTH-1 : 0] rx_tdata,
input wire [(C_rx_TDATA_WIDTH/8)-1 : 0] rx_tstrb,
input wire rx_tlast,
input wire rx_tvalid
);
// Instantiation of Axi Bus Interface axi
iostream_v1_0_axi # (
.C_S_AXI_DATA_WIDTH(C_axi_DATA_WIDTH),
.C_S_AXI_ADDR_WIDTH(C_axi_ADDR_WIDTH)
) iostream_v1_0_axi_inst (
.S_AXI_ACLK(axi_aclk),
.S_AXI_ARESETN(axi_aresetn),
.tx_tvalid(tx_tvalid),
.tx_tdata(tx_tdata),
// output wire [0 : 0] tx_tstrb,
// output wire tx_tlast,
.tx_tready(tx_tready),
.rx_tvalid(rx_tvalid),
.rx_tdata(rx_tdata),
// input wire [0 : 0] tx_tstrb,
// input wire tx_tlast,
.tx_tready(rx_tready),
.interrupt(interrupt),
.S_AXI_AWADDR(axi_awaddr),
.S_AXI_AWPROT(axi_awprot),
.S_AXI_AWVALID(axi_awvalid),
.S_AXI_AWREADY(axi_awready),
.S_AXI_WDATA(axi_wdata),
.S_AXI_WSTRB(axi_wstrb),
.S_AXI_WVALID(axi_wvalid),
.S_AXI_WREADY(axi_wready),
.S_AXI_BRESP(axi_bresp),
.S_AXI_BVALID(axi_bvalid),
.S_AXI_BREADY(axi_bready),
.S_AXI_ARADDR(axi_araddr),
.S_AXI_ARPROT(axi_arprot),
.S_AXI_ARVALID(axi_arvalid),
.S_AXI_ARREADY(axi_arready),
.S_AXI_RDATA(axi_rdata),
.S_AXI_RRESP(axi_rresp),
.S_AXI_RVALID(axi_rvalid),
.S_AXI_RREADY(axi_rready)
);
assign tx_tstrb[0:0] = tx_tvalid;
assign tx_tlast = 1'b0;
// Add user logic here
// User logic ends
endmodule
`timescale 1 ns / 1 ps
module axi_stream_io_v1_0_axi_s #
(
// Users to add parameters here
// User parameters ends
// Do not modify the parameters beyond this line
// Width of S_AXI data bus
parameter integer C_S_AXI_DATA_WIDTH = 32,
// Width of S_AXI address bus
parameter integer C_S_AXI_ADDR_WIDTH = 4
)
(
// Users to add ports here
output wire interrupt,
// Ports of Axi Master Bus Interface tx
// input wire tx_aclk,
// input wire tx_aresetn,
output wire tx_tvalid,
output wire [7 : 0] tx_tdata,
// output wire [0 : 0] tx_tstrb,
// output wire tx_tlast,
input wire tx_tready,
// Ports of Axi Slave Bus Interface rx
// input wire rx_aclk,
// input wire rx_aresetn,
output wire rx_tready,
input wire [7 : 0] rx_tdata,
// input wire [0 : 0] rx_tstrb,
// input wire rx_tlast,
input wire rx_tvalid,
// User ports ends
// Do not modify the ports beyond this line
// Global Clock Signal
input wire S_AXI_ACLK,
// Global Reset Signal. This Signal is Active LOW
input wire S_AXI_ARESETN,
// Write address (issued by master, acceped by Slave)
input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
// Write channel Protection type. This signal indicates the
// privilege and security level of the transaction, and whether
// the transaction is a data access or an instruction access.
input wire [2 : 0] S_AXI_AWPROT,
// Write address valid. This signal indicates that the master signaling
// valid write address and control information.
input wire S_AXI_AWVALID,
// Write address ready. This signal indicates that the slave is ready
// to accept an address and associated control signals.
output wire S_AXI_AWREADY,
// Write data (issued by master, acceped by Slave)
input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,
// Write strobes. This signal indicates which byte lanes hold
// valid data. There is one write strobe bit for each eight
// bits of the write data bus.
input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
// Write valid. This signal indicates that valid write
// data and strobes are available.
input wire S_AXI_WVALID,
// Write ready. This signal indicates that the slave
// can accept the write data.
output wire S_AXI_WREADY,
// Write response. This signal indicates the status
// of the write transaction.
output wire [1 : 0] S_AXI_BRESP,
// Write response valid. This signal indicates that the channel
// is signaling a valid write response.
output wire S_AXI_BVALID,
// Response ready. This signal indicates that the master
// can accept a write response.
input wire S_AXI_BREADY,
// Read address (issued by master, acceped by Slave)
input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
// Protection type. This signal indicates the privilege
// and security level of the transaction, and whether the
// transaction is a data access or an instruction access.
input wire [2 : 0] S_AXI_ARPROT,
// Read address valid. This signal indicates that the channel
// is signaling valid read address and control information.
input wire S_AXI_ARVALID,
// Read address ready. This signal indicates that the slave is
// ready to accept an address and associated control signals.
output wire S_AXI_ARREADY,
// Read data (issued by slave)
output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,
// Read response. This signal indicates the status of the
// read transfer.
output wire [1 : 0] S_AXI_RRESP,
// Read valid. This signal indicates that the channel is
// signaling the required read data.
output wire S_AXI_RVALID,
// Read ready. This signal indicates that the master can
// accept the read data and response information.
input wire S_AXI_RREADY
);
// AXI4LITE signals
reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr;
reg axi_awready;
reg axi_wready;
reg [1 : 0] axi_bresp;
reg axi_bvalid;
reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr;
reg axi_arready;
reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata;
reg [1 : 0] axi_rresp;
reg axi_rvalid;
// Example-specific design signals
// local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
// ADDR_LSB is used for addressing 32/64 bit registers/memories
// ADDR_LSB = 2 for 32 bits (n downto 2)
// ADDR_LSB = 3 for 64 bits (n downto 3)
localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
localparam integer OPT_MEM_ADDR_BITS = 1;
//----------------------------------------------
//-- Signals for user logic register space example
//------------------------------------------------
//-- Number of Slave Registers 4
reg [8:0] tx_reg; // TX data
reg [8:0] rx_reg; // RX data
reg [7:0] ctrl_reg; // ctrl
wire slv_reg_rden;
wire slv_reg_wren;
reg [7:0] reg_data_out;
integer byte_index;
reg aw_en;
wire tx_req = tx_reg[8]; // request to transmit
wire tx_ack = tx_tready; // acknowledge when stream ready
wire tx_rdy = !tx_reg[8];
wire rx_req = rx_tvalid; // request to receive
wire rx_ack = !rx_reg[8];
wire rx_rdy = rx_reg[8];
//assign rx_reg[7:0] <= rx_tdata;
// I/O Connections assignments
assign interrupt = ctrl_reg[4] & (!tx_req | rx_req);
// TX stream interface
assign tx_tdata = tx_reg[7:0];
assign tx_tvalid = tx_req;
// RX stream interface
assign rx_tready = rx_ack;
//AXI Slave
assign S_AXI_AWREADY = axi_awready;
assign S_AXI_WREADY = axi_wready;
assign S_AXI_BRESP = axi_bresp;
assign S_AXI_BVALID = axi_bvalid;
assign S_AXI_ARREADY = axi_arready;
assign S_AXI_RDATA = axi_rdata;
assign S_AXI_RRESP = axi_rresp;
assign S_AXI_RVALID = axi_rvalid;
// Implement axi_awready generation
// axi_awready is asserted for one S_AXI_ACLK clock cycle when both
// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
// de-asserted when reset is low.
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_awready <= 1'b0;
aw_en <= 1'b1;
end
else
begin
if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
begin
// slave is ready to accept write address when
// there is a valid write address and write data
// on the write address and data bus. This design
// expects no outstanding transactions.
axi_awready <= 1'b1;
aw_en <= 1'b0;
end
else if (S_AXI_BREADY && axi_bvalid)
begin
aw_en <= 1'b1;
axi_awready <= 1'b0;
end
else
begin
axi_awready <= 1'b0;
end
end
end
// Implement axi_awaddr latching
// This process is used to latch the address when both
// S_AXI_AWVALID and S_AXI_WVALID are valid.
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_awaddr <= 0;
end
else
begin
if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
begin
// Write Address latching
axi_awaddr <= S_AXI_AWADDR;
end
end
end
// Implement axi_wready generation
// axi_wready is asserted for one S_AXI_ACLK clock cycle when both
// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is
// de-asserted when reset is low.
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_wready <= 1'b0;
end
else
begin
if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en )
begin
// slave is ready to accept write data when
// there is a valid write address and write data
// on the write address and data bus. This design
// expects no outstanding transactions.
axi_wready <= 1'b1;
end
else
begin
axi_wready <= 1'b0;
end
end
end
// Implement memory mapped register select and write logic generation
// The write data is accepted and written to memory mapped registers when
// axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
// select byte enables of slave registers while writing.
// These registers are cleared when reset (active low) is applied.
// Slave register write enable is asserted when valid address and data are available
// and the slave is ready to accept the write address and write data.
assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
rx_reg <= 0;
else if ((ctrl_reg[1] == 1'b1))
rx_reg <= 0;
else if (slv_reg_wren && (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] == 2'h0))
rx_reg[8:0] <= {1'b1, S_AXI_WDATA[7:0]};
else if (slv_reg_rden && (axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] == 2'h0))
rx_reg[8] <= 1'b0;
else if (rx_req & rx_ack) // check precedence (rx_req)
rx_reg[8:0] <= {1'b1, rx_tdata[7:0]};
end
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
tx_reg <= 0;
else if ((ctrl_reg[0] == 1'b1))
tx_reg <= 0;
else if (slv_reg_wren && (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] == 2'h1))
tx_reg[8:0] <= {1'b1, S_AXI_WDATA[7:0]};
else if (tx_req & tx_ack)
tx_reg[8] <= 1'b0;
end
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
ctrl_reg <= 8'b00000100;
else if (slv_reg_wren && (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] == 2'h3))
ctrl_reg[7:0] <= S_AXI_WDATA[7:0];
end
// Implement write response logic generation
// The write response and response valid signals are asserted by the slave
// when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.
// This marks the acceptance of address and indicates the status of
// write transaction.
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_bvalid <= 0;
axi_bresp <= 2'b0;
end
else
begin
if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)
begin
// indicates a valid write response is available
axi_bvalid <= 1'b1;
axi_bresp <= 2'b0; // 'OKAY' response
end // work error responses in future
else
begin
if (S_AXI_BREADY && axi_bvalid)
//check if bready is asserted while bvalid is high)
//(there is a possibility that bready is always asserted high)
begin
axi_bvalid <= 1'b0;
end
end
end
end
// Implement axi_arready generation
// axi_arready is asserted for one S_AXI_ACLK clock cycle when
// S_AXI_ARVALID is asserted. axi_awready is
// de-asserted when reset (active low) is asserted.
// The read address is also latched when S_AXI_ARVALID is
// asserted. axi_araddr is reset to zero on reset assertion.
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_arready <= 1'b0;
axi_araddr <= 32'b0;
end
else
begin
if (~axi_arready && S_AXI_ARVALID)
begin
// indicates that the slave has acceped the valid read address
axi_arready <= 1'b1;
// Read address latching
axi_araddr <= S_AXI_ARADDR;
end
else
begin
axi_arready <= 1'b0;
end
end
end
// Implement axi_arvalid generation
// axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both
// S_AXI_ARVALID and axi_arready are asserted. The slave registers
// data are available on the axi_rdata bus at this instance. The
// assertion of axi_rvalid marks the validity of read data on the
// bus and axi_rresp indicates the status of read transaction.axi_rvalid
// is deasserted on reset (active low). axi_rresp and axi_rdata are
// cleared to zero on reset (active low).
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_rvalid <= 0;
axi_rresp <= 0;
end
else
begin
if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)
begin
// Valid read data is available at the read data bus
axi_rvalid <= 1'b1;
axi_rresp <= 2'b0; // 'OKAY' response
end
else if (axi_rvalid && S_AXI_RREADY)
begin
// Read data is accepted by the master
axi_rvalid <= 1'b0;
end
end
end
// Implement memory mapped register select and read logic generation
// Slave register read enable is asserted when valid address is available
// and the slave is ready to accept the read address.
assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
always @(*)
begin
// Address decoding for reading registers
case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
2'h0 : reg_data_out <= rx_reg[7:0];
2'h1 : reg_data_out <= tx_reg[7:0];
2'h2 : reg_data_out <= {3'b000, ctrl_reg[4], !tx_rdy, tx_rdy, rx_rdy, rx_rdy};
2'h3 : reg_data_out <= ctrl_reg;
default : reg_data_out <= 0;
endcase
end
// Output register or memory read data
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_rdata <= 0;
end
else
begin
// When there is a valid read address (S_AXI_ARVALID) with
// acceptance of read address by the slave (axi_arready),
// output the read dada
if (slv_reg_rden)
begin
axi_rdata <= {24'h000000, reg_data_out}; // register read data
end
end
end
// Add user logic here
// User logic ends
endmodule
//-----------------------------------------------------------------------------
// NanoSoC FT1248 ADP UART 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 ft232h_ft1248_x1 #(
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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment