Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • soclabs/socdebug_tech
1 result
Show changes
Commits on Source (1)
Showing
with 1238 additions and 339 deletions
......@@ -10,10 +10,7 @@
//-----------------------------------------------------------------------------
module socdebug_ahb #(
parameter PROMPT_CHAR = "]",
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
parameter [7:0] FT1248_CLKDIV = 8'd03 // Clock Division Ratio
parameter PROMPT_CHAR = "]"
)(
// AHB-lite Master Interface - ADP
input wire HCLK,
......@@ -30,124 +27,29 @@ module socdebug_ahb #(
input wire HREADY_i,
input wire HRESP_i,
// APB Slave Interface - USRT
input wire PCLK, // Clock
input wire PCLKG, // Gated Clock
input wire PRESETn, // Reset
input wire PSEL_i, // Device select
input wire [11:2] PADDR_i, // Address
input wire PENABLE_i, // Transfer control
input wire PWRITE_i, // Write control
input wire [31:0] PWDATA_i, // Write data
output wire [31:0] PRDATA_o, // Read data
output wire PREADY_o, // Device ready
output wire PSLVERR_o, // Device error response
// USRT0 TXD axi byte stream
output wire ADP_RXD_TVALID_o,
output wire [ 7:0] ADP_RXD_TDATA_o ,
input wire ADP_RXD_TREADY_i,
// USRT0 RXD axi byte stream
input wire ADP_TXD_TVALID_i,
input wire [ 7:0] ADP_TXD_TDATA_i ,
output wire ADP_TXD_TREADY_o,
// FT1248 Interace - FT1248
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
// USRT0 TXD axi byte stream
output wire STD_RXD_TVALID_o,
output wire [ 7:0] STD_RXD_TDATA_o ,
input wire STD_RXD_TREADY_i,
// USRT0 RXD axi byte stream
input wire STD_TXD_TVALID_i,
input wire [ 7:0] STD_TXD_TDATA_i ,
output wire STD_TXD_TREADY_o,
// GPIO interface
output wire [7:0] GPO8_o,
input wire [7:0] GPI8_i
);
// FT1248 to ADP Bus
wire FT1248_ADP_TVALID;
wire [ 7:0] FT1248_ADP_TDATA;
wire FT1248_ADP_TREADY;
// ADP to FT1248 Bus
wire ADP_FT1248_TVALID;
wire [ 7:0] ADP_FT1248_TDATA;
wire ADP_FT1248_TREADY;
// USRT to ADP Bus
wire USRT_ADP_TVALID;
wire [ 7:0] USRT_ADP_TDATA;
wire USRT_ADP_TREADY;
// ADP to USRT Bus
wire ADP_USRT_TVALID;
wire [ 7:0] ADP_USRT_TDATA;
wire ADP_USRT_TREADY;
// Clock Divsion Ratio
wire [7:0] FT_CLKDIV;
assign FT_CLKDIV = FT1248_CLKDIV;
// Instantiation of USRT Controller
socdebug_usrt_control u_usrt_control (
// APB Clock and Reset Signals
.PCLK (PCLK),
.PCLKG (PCLKG), // Gated PCLK for bus
.PRESETn (PRESETn),
// APB Interface Signals
.PSEL (PSEL_i),
.PADDR (PADDR_i),
.PENABLE (PENABLE_i),
.PWRITE (PWRITE_i),
.PWDATA (PWDATA_i),
.PRDATA (PRDATA_o),
.PREADY (PREADY_o),
.PSLVERR (PSLVERR_o),
.ECOREVNUM (4'h0),
// ADP Interface - From USRT to ADP
.TX_VALID_o (USRT_ADP_TVALID),
.TX_DATA8_o (USRT_ADP_TDATA),
.TX_READY_i (USRT_ADP_TREADY),
// ADP Interface - From ADP to USRT
.RX_VALID_i (ADP_USRT_TVALID),
.RX_DATA8_i (ADP_USRT_TDATA),
.RX_READY_o (ADP_USRT_TREADY),
// Interrupt Interfaces
.TXINT ( ), // Transmit Interrupt
.RXINT ( ), // Receive Interrupt
.TXOVRINT ( ), // Transmit Overrun Interrupt
.RXOVRINT ( ), // Receive Overrun Interrupt
.UARTINT ( ) // Combined Interrupt
);
// Instantiation of FT1248 Controller
socdebug_ft1248_control #(
.FT1248_WIDTH (FT1248_WIDTH),
.FT1248_CLKON (FT1248_CLKON)
) u_ft1248_control (
.clk (HCLK),
.resetn (HRESETn),
.ft_clkdiv (FT_CLKDIV),
.ft_clk_o (FT_CLK_O),
.ft_ssn_o (FT_SSN_O),
.ft_miso_i (FT_MISO_I),
.ft_miosio_o (FT_MIOSIO_O),
.ft_miosio_e (FT_MIOSIO_E),
.ft_miosio_z (FT_MIOSIO_Z),
.ft_miosio_i (FT_MIOSIO_I),
// ADP Interface - FT1248 to ADP
.txd_tvalid (FT1248_ADP_TVALID),
.txd_tdata (FT1248_ADP_TDATA),
.txd_tready (FT1248_ADP_TREADY),
.txd_tlast ( ),
// ADP Interface - ADP to FT1248
.rxd_tvalid (ADP_FT1248_TVALID),
.rxd_tdata (ADP_FT1248_TDATA),
.rxd_tready (ADP_FT1248_TREADY),
.rxd_tlast (1'b0)
);
// Instantiation of ADP AHB Controller
socdebug_adp_control #(
......@@ -173,25 +75,25 @@ module socdebug_ahb #(
.GPI8_i (GPI8_i),
// USRT Interface - From ADP to USRT
.STDTX_TVALID_o (ADP_USRT_TVALID),
.STDTX_TDATA_o (ADP_USRT_TDATA),
.STDTX_TREADY_i (ADP_USRT_TREADY),
.STDTX_TVALID_o (STD_RXD_TVALID_o),
.STDTX_TDATA_o (STD_RXD_TDATA_o ),
.STDTX_TREADY_i (STD_RXD_TREADY_i),
// USRT Interface - From USRT to ADP
.STDRX_TVALID_i (USRT_ADP_TVALID),
.STDRX_TDATA_i (USRT_ADP_TDATA),
.STDRX_TREADY_o (USRT_ADP_TREADY),
.STDRX_TVALID_i (STD_TXD_TVALID_i),
.STDRX_TDATA_i (STD_TXD_TDATA_i ),
.STDRX_TREADY_o (STD_TXD_TREADY_o),
// FT1248 Interface - From FT1248 to ADP
.COMRX_TVALID_i (FT1248_ADP_TVALID),
.COMRX_TDATA_i (FT1248_ADP_TDATA),
.COMRX_TREADY_o (FT1248_ADP_TREADY),
.COMRX_TVALID_i (ADP_TXD_TVALID_i),
.COMRX_TDATA_i (ADP_TXD_TDATA_i ),
.COMRX_TREADY_o (ADP_TXD_TREADY_o),
// FT1248 Interface - From ADP to FT1248
.COMTX_TVALID_o (ADP_FT1248_TVALID),
.COMTX_TDATA_o (ADP_FT1248_TDATA),
.COMTX_TREADY_i (ADP_FT1248_TREADY)
.COMTX_TVALID_o (ADP_RXD_TVALID_o),
.COMTX_TDATA_o (ADP_RXD_TDATA_o ),
.COMTX_TREADY_i (ADP_RXD_TREADY_i)
);
endmodule
\ No newline at end of file
endmodule
......@@ -39,24 +39,24 @@
// 0x00 R RXD[7:0] Received Data
// W TXD[7:0] Transmit data
// 0x04 RW STAT[3:0]
// [3] RX buffer overrun (write 1 to clear)
// [2] TX buffer overrun (write 1 to clear)
// [3] RX buffer overrun (write 1 to clear) // 0 for USRT
// [2] TX buffer overrun (write 1 to clear) // 0 for USRT
// [1] RX buffer full (Read only)
// [0] TX buffer full (Read only)
// 0x08 RW CTRL[3:0] TxIntEn, RxIntEn, TxEn, RxEn
// [6] High speed test mode Enable
// [5] RX overrun interrupt enable
// [4] TX overrun interrupt enable
// [5] RX overrun interrupt enable // N/A for USRT
// [4] TX overrun interrupt enable // N/A for USRT
// [3] RX Interrupt Enable
// [2] TX Interrupt Enable
// [1] RX Enable
// [0] TX Enable
// 0x0C R/Wc intr_status/INTCLEAR
// [3] RX overrun interrupt
// [2] TX overrun interrupt
// [3] RX overrun interrupt // 0 for USRT
// [2] TX overrun interrupt // 0 for USRT
// [1] RX interrupt
// [0] TX interrupt
// 0x10 RW BAUDDIV[19:0] Baud divider
// 0x10 RW BAUDDIV[19:0] Baud divider // Not Used for USRT
// (minimum value is 16)
// 0x3E0 - 0x3FC ID registers
//-------------------------------------
......@@ -101,13 +101,13 @@ localparam ARM_CMSDK_APB_UART_PID5 = 8'h00;
localparam ARM_CMSDK_APB_UART_PID6 = 8'h00;
localparam ARM_CMSDK_APB_UART_PID7 = 8'h00;
localparam ARM_CMSDK_APB_UART_PID0 = 8'h21;
localparam ARM_CMSDK_APB_UART_PID1 = 8'hB8;
localparam ARM_CMSDK_APB_UART_PID2 = 8'h1B;
localparam ARM_CMSDK_APB_UART_PID1 = 8'hb8;
localparam ARM_CMSDK_APB_UART_PID2 = 8'h1b;
localparam ARM_CMSDK_APB_UART_PID3 = 4'h0;
localparam ARM_CMSDK_APB_UART_CID0 = 8'h0D;
localparam ARM_CMSDK_APB_UART_CID1 = 8'hF0;
localparam ARM_CMSDK_APB_UART_CID0 = 8'h0d;
localparam ARM_CMSDK_APB_UART_CID1 = 8'hf0;
localparam ARM_CMSDK_APB_UART_CID2 = 8'h05;
localparam ARM_CMSDK_APB_UART_CID3 = 8'hB1;
localparam ARM_CMSDK_APB_UART_CID3 = 8'hb1;
// original external IOs
wire RXD = 1'b1; // Serial input
......@@ -315,8 +315,6 @@ assign write_enable10 = write_enable & (PADDR[11:2] == 10'h004);
end
end
// Register read data
always @(posedge PCLKG or negedge PRESETn)
begin
......@@ -411,7 +409,7 @@ assign write_enable10 = write_enable & (PADDR[11:2] == 10'h004);
begin
if (~PRESETn)
tx_buf_full <= 1'b0;
else if (write_enable00) // | tx_buf_clear)
else if (write_enable00 & reg_ctrl[0]) // | tx_buf_clear)
tx_buf_full <= write_enable00;
else if (tx_buf_full & TX_READY_i) // AXI stream ack
tx_buf_full <= 0;
......@@ -419,159 +417,21 @@ assign write_enable10 = write_enable & (PADDR[11:2] == 10'h004);
assign TX_VALID_o = tx_buf_full;
// Increment TickCounter
assign nxt_tx_tick_cnt = ((tx_state==4'h1) & reg_baud_tick) ? {5{1'b0}} :
tx_tick_cnt + {{3{1'b0}},reg_baud_tick};
// Registering TickCounter
always @(posedge PCLK or negedge PRESETn)
begin
if (~PRESETn)
tx_tick_cnt <= {4{1'b0}};
else if (reg_baud_tick)
tx_tick_cnt <= nxt_tx_tick_cnt[3:0];
end
// Increment state (except Idle(0) and Wait for Tick(1))
assign tx_state_inc = (((&tx_tick_cnt)|(tx_state==4'h1)) & reg_baud_tick)|reg_ctrl[6];
// state increment every cycle of high speed test mode is enabled
// Clear buffer full status when data is load into shift register
assign tx_buf_clear = ((tx_state==4'h0) & tx_buf_full) |
((tx_state==4'hB) & tx_buf_full & tx_state_inc);
// tx_state machine
// 0 = Idle, 1 = Wait for Tick,
// 2 = Start bit, 3 = D0 .... 10 = D7
// 11 = Stop bit
always @(tx_state or tx_buf_full or tx_state_inc or reg_ctrl)
begin
case (tx_state)
0: begin
nxt_tx_state = (tx_buf_full & reg_ctrl[0]) ? 5'h01 : 5'h00; // New data is written to buffer
end
1, // State 1 : Wait for next Tick
2,3,4,5,6,7,8,9,10: begin // State 2-10: Start bit, D0 - D7
nxt_tx_state = tx_state + {3'b000,tx_state_inc};
end
11: begin // Stop bit , goto next start bit or Idle
nxt_tx_state = (tx_state_inc) ? ( tx_buf_full ? 5'h02:5'h00) : {1'b0, tx_state};
end
default:
nxt_tx_state = {5{1'bx}};
endcase
end
assign tx_state_update = tx_state_inc | ((tx_state==4'h0) & tx_buf_full & reg_ctrl[0]) | (tx_state>4'd11);
// Registering outputs
always @(posedge PCLK or negedge PRESETn)
begin
if (~PRESETn)
tx_state <= {4{1'b0}};
else if (tx_state_update)
tx_state <= nxt_tx_state[3:0];
end
// Load/shift TX register
assign tx_buf_ctrl_load = (((tx_state==4'h0) & tx_buf_full) |
((tx_state==4'hB) & tx_buf_full & tx_state_inc));
assign tx_buf_ctrl_shift = ((tx_state>4'h2) & tx_state_inc);
assign nxt_tx_shift_buf = tx_buf_ctrl_load ? reg_tx_buf[7:0] : {1'b1,tx_shift_buf[7:1]};
// Registering TX shift register
always @(posedge PCLK or negedge PRESETn)
begin
if (~PRESETn)
tx_shift_buf <= {8{1'b0}};
else if (tx_buf_ctrl_shift | tx_buf_ctrl_load)
tx_shift_buf <= nxt_tx_shift_buf;
end
// Data output
assign nxt_txd = (tx_state==4'h2) ? 1'b0 :
(tx_state>4'h2) ? tx_shift_buf[0] : 1'b1;
assign update_reg_txd = (nxt_txd != reg_txd);
// Registering outputs
always @(posedge PCLK or negedge PRESETn)
begin
if (~PRESETn)
reg_txd <= 1'b1;
else if (update_reg_txd)
reg_txd <= nxt_txd;
end
// Generate TX overrun error status
assign tx_overrun = tx_buf_full & (~tx_buf_clear) & write_enable00;
/// assign tx_overrun = tx_buf_full & (~tx_buf_clear) & write_enable00;
assign tx_overrun = tx_buf_full & write_enable00;
// Connect to external
assign TXD = reg_txd;
assign TXEN = reg_ctrl[0];
// --------------------------------------------
// Receive synchronizer and low pass filter
// Doubling Flip-flop synxt_rx_tick_cntnchroniser
always @(posedge PCLK or negedge PRESETn)
begin
if (~PRESETn)
begin
rxd_sync_1 <= 1'b1;
rxd_sync_2 <= 1'b1;
end
else if (reg_ctrl[1]) // Turn off synchronizer if receive is not enabled
begin
rxd_sync_1 <= RXD;
rxd_sync_2 <= rxd_sync_1;
end
end
// Averaging low pass filter
assign nxt_rxd_lpf = {rxd_lpf[1:0], rxd_sync_2};
// Registering stage for low pass filter
always @(posedge PCLK or negedge PRESETn)
begin
if (~PRESETn)
rxd_lpf <= 3'b111;
else if (reg_baud_tick)
rxd_lpf <= nxt_rxd_lpf;
end
// Averaging values
assign rx_shift_in = (rxd_lpf[1] & rxd_lpf[0]) |
(rxd_lpf[1] & rxd_lpf[2]) |
(rxd_lpf[0] & rxd_lpf[2]);
// --------------------------------------------
// Receive
assign RX_READY_o = !rx_buf_full;
// Increment TickCounter
assign nxt_rx_tick_cnt = ((rx_state==4'h0) & (~rx_shift_in)) ? 5'h08 :
rx_tick_cnt + {{3{1'b0}},reg_baud_tick};
assign update_rx_tick_cnt = ((rx_state==4'h0) & (~rx_shift_in)) | reg_baud_tick;
// Registering other register
always @(posedge PCLK or negedge PRESETn)
begin
if (~PRESETn)
rx_tick_cnt <= {4{1'b0}};
else if (update_rx_tick_cnt)
rx_tick_cnt <= nxt_rx_tick_cnt[3:0];
end
// Increment state
assign rx_state_inc = ((&rx_tick_cnt) & reg_baud_tick);
// Buffer full status
assign nxt_rx_buf_full = rxbuf_sample | (rx_buf_full & (~rx_data_read));
// Sample shift register when D7 is sampled
/// assign rxbuf_sample = ((rx_state==4'h9) & rx_state_inc);
assign rxbuf_sample = RX_VALID_i & !rx_buf_full;
// Reading receive buffer (Set at 1st cycle of APB transfer
......@@ -580,81 +440,33 @@ assign RX_READY_o = !rx_buf_full;
// Generate RX overrun error status
assign rx_overrun = rx_buf_full & rxbuf_sample & (~rx_data_read);
// rx_state machine
// 0 = Idle, 1 = Start of Start bit detected
// 2 = Sample Start bit, 3 = D0 .... 10 = D7
// 11 = Stop bit
// 11, 12, 13, 14, 15: illegal/unused states
always @(rx_state or rx_shift_in or rx_state_inc or reg_ctrl)
begin
case (rx_state)
0: begin
nxt_rx_state = ((~rx_shift_in) & reg_ctrl[1]) ? 5'h01 : 5'h00; // Wait for Start bit
end
1, // State 1 : Wait for middle of start bit
2,3,4,5,6,7,8,9: begin // State 2-9: D0 - D7
nxt_rx_state = rx_state + {3'b000,rx_state_inc};
end
10: begin // Stop bit , goto back to Idle
nxt_rx_state = (rx_state_inc) ? 5'h00 : 5'h0A;
end
default:
nxt_rx_state = {5{1'bx}};
endcase
end
assign rx_state_update = rx_state_inc | ((~rx_shift_in) & reg_ctrl[1]);
// Registering rx_state
always @(posedge PCLK or negedge PRESETn)
begin
if (~PRESETn)
rx_state <= {4{1'b0}};
else if (rx_state_update)
rx_state <= nxt_rx_state[3:0];
end
// Buffer full status
always @(posedge PCLK or negedge PRESETn)
begin
if (~PRESETn)
rx_buf_full <= 1'b0;
else if (rxbuf_sample | rx_data_read)
else if ( reg_ctrl[1] & (rxbuf_sample | rx_data_read))
rx_buf_full <= nxt_rx_buf_full;
end
// Sample receive buffer
/// assign nxt_rx_buf = {rx_shift_in, rx_shift_buf};
assign nxt_rx_buf = RX_DATA8_i[7:0];
assign RX_READY_o = !rx_buf_full;
// Registering receive data buffer
always @(posedge PCLK or negedge PRESETn)
begin
if (~PRESETn)
reg_rx_buf <= {8{1'b0}};
else if (rxbuf_sample)
reg_rx_buf <= nxt_rx_buf;
reg_rx_buf <= RX_DATA8_i[7:0];
end
// Shift register
assign nxt_rx_shift_buf= {rx_shift_in, rx_shift_buf[6:1]};
// Registering shift buffer
always @(posedge PCLK or negedge PRESETn)
begin
if (~PRESETn)
rx_shift_buf <= {7{1'b0}};
else if (rx_state_inc)
rx_shift_buf <= nxt_rx_shift_buf;
end
// --------------------------------------------
// Interrupts
// Set by event
assign intr_stat_set[1] = reg_ctrl[3] & rxbuf_sample; // A new receive data is sampled
assign intr_stat_set[0] = reg_ctrl[2] & reg_ctrl[0] & tx_buf_full & tx_buf_clear;
// Falling edge of buffer full
/// assign intr_stat_set[1] = reg_ctrl[3] & rxbuf_sample; // A new receive data is sampled
assign intr_stat_set[1] = reg_ctrl[3] & reg_ctrl[1] & rxbuf_sample; // A new receive data is sampled
/// assign intr_stat_set[0] = reg_ctrl[2] & reg_ctrl[0] & tx_buf_full; // & tx_buf_clear;
assign intr_stat_set[0] = reg_ctrl[2] & reg_ctrl[0] & tx_buf_full & TX_READY_i; // Falling edge of buffer full
// Clear by write to IntClear register
assign intr_stat_clear[1:0] = {2{write_enable0c}} & PWDATA[1:0];
......
File added
//-----------------------------------------------------------------------------
// 8-bit extio transfer over 4-bit data plane - target
//
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Flynn (d.w.flynn@soton.ac.uk)
//
// Copyright (c) 2024, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Abstract : target FSM wrapped with synchronizers
//-----------------------------------------------------------------------------
module extio8x4_axis_target
(
input wire clk,
input wire resetn,
input wire testmode,
// RX 4-channel AXIS interface
output wire axis_rx0_tready,
input wire axis_rx0_tvalid,
input wire [7:0] axis_rx0_tdata8,
output wire axis_rx1_tready,
input wire axis_rx1_tvalid,
input wire [7:0] axis_rx1_tdata8,
input wire axis_tx0_tready,
output wire axis_tx0_tvalid,
output wire [7:0] axis_tx0_tdata8,
input wire axis_tx1_tready,
output wire axis_tx1_tvalid,
output wire [7:0] axis_tx1_tdata8,
// external io interface
input wire [3:0] iodata4_i,
output wire [3:0] iodata4_o,
output wire [3:0] iodata4_e,
output wire [3:0] iodata4_t,
input wire ioreq1_a,
input wire ioreq2_a,
output wire ioack_o
);
wire ioreq1_s;
wire ioreq2_s;
extio8x4_sync u_extio8x4_sync_ioreq1
(
.clk(clk),
.resetn(resetn),
.testmode(testmode),
.sig_a(ioreq1_a),
.sig_s(ioreq1_s)
);
extio8x4_sync u_extio8x4_sync_ioreq2
(
.clk(clk),
.resetn(resetn),
.testmode(testmode),
.sig_a(ioreq2_a),
.sig_s(ioreq2_s)
);
extio8x4_tfsm u_extio8x4_tfsm
(
.clk ( clk ),
.resetn ( resetn ),
// RX 4-channel AXIS interface
.axis_rx0_tready ( axis_rx0_tready ),
.axis_rx0_tvalid ( axis_rx0_tvalid ),
.axis_rx0_tdata8 ( axis_rx0_tdata8 ),
.axis_rx1_tready ( axis_rx1_tready ),
.axis_rx1_tvalid ( axis_rx1_tvalid ),
.axis_rx1_tdata8 ( axis_rx1_tdata8 ),
.axis_tx0_tready ( axis_tx0_tready ),
.axis_tx0_tvalid ( axis_tx0_tvalid ),
.axis_tx0_tdata8 ( axis_tx0_tdata8 ),
.axis_tx1_tready ( axis_tx1_tready ),
.axis_tx1_tvalid ( axis_tx1_tvalid ),
.axis_tx1_tdata8 ( axis_tx1_tdata8 ),
// external io interface
.iodata4_i ( iodata4_i ),
.iodata4_o ( iodata4_o ),
.iodata4_e ( iodata4_e ),
.iodata4_t ( iodata4_t ),
.ioreq1_s ( ioreq1_s ),
.ioreq2_s ( ioreq2_s ),
.ioack_o ( ioack_o )
);
endmodule
/*
extio8x4_axis_target u_extio8x4_axis_target
(
.clk ( clk ),
.resetn ( resetn ),
.testmode ( testmode ),
// RX 4-channel AXIS interface
.axis_rx0_tready ( axis_rx0_tready ),
.axis_rx0_tvalid ( axis_rx0_tvalid ),
.axis_rx0_tdata8 ( axis_rx0_tdata8 ),
.axis_rx1_tready ( axis_rx1_tready ),
.axis_rx1_tvalid ( axis_rx1_tvalid ),
.axis_rx1_tdata8 ( axis_rx1_tdata8 ),
.axis_tx0_tready ( axis_tx0_tready ),
.axis_tx0_tvalid ( axis_tx0_tvalid ),
.axis_tx0_tdata8 ( axis_tx0_tdata8 ),
.axis_tx1_tready ( axis_tx1_tready ),
.axis_tx1_tvalid ( axis_tx1_tvalid ),
.axis_tx1_tdata8 ( axis_tx1_tdata8 ),
// external io interface
.iodata4_i ( iodata4_i ),
.iodata4_o ( iodata4_o ),
.iodata4_e ( iodata4_e ),
.iodata4_t ( iodata4_t ),
.ioreq1_a ( ioreq1_i ),
.ioreq2_a ( ioreq2_i ),
.ioack_o ( ioack_o )
);
*/
//-----------------------------------------------------------------------------
// 8-bit extio transfer over 4-bit data plane - initiator
//
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Flynn (d.w.flynn@soton.ac.uk)
//
// Copyright (c) 2024, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
module extio8x4_sync
(
input wire clk,
input wire resetn,
input wire testmode,
input wire sig_a,
output wire sig_s
);
reg [2:1] sig_r;
always @(posedge clk or negedge resetn)
begin
if (!resetn)
sig_r <= 2'b00; // default
else
sig_r <= {sig_r[1], sig_a}; // shift left
end
assign sig_s = (testmode) ? sig_a : sig_r[2];
endmodule
/*
extio8x4_sync, u_extio8x4_sync_1
(
.clk(clk),
.resetn(resetn),
.testmode(testmode),
.sig_a(sig_i),
.sig_s(sig_s)
);
*/
//-----------------------------------------------------------------------------
// 8-bit extio transfer over 4-bit data plane - target
//
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Flynn (d.w.flynn@soton.ac.uk)
//
// Copyright (c) 2024, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Abstract : Initiator state machine and sequencer
//-----------------------------------------------------------------------------
module extio8x4_tfsm
(
input wire clk,
input wire resetn,
// RX 4-channel AXIS interface
output wire axis_rx0_tready,
input wire axis_rx0_tvalid,
input wire [7:0] axis_rx0_tdata8,
output wire axis_rx1_tready,
input wire axis_rx1_tvalid,
input wire [7:0] axis_rx1_tdata8,
input wire axis_tx0_tready,
output wire axis_tx0_tvalid,
output wire [7:0] axis_tx0_tdata8,
input wire axis_tx1_tready,
output wire axis_tx1_tvalid,
output wire [7:0] axis_tx1_tdata8,
// external io interface
input wire [3:0] iodata4_i,
output wire [3:0] iodata4_o,
output wire [3:0] iodata4_e,
output wire [3:0] iodata4_t,
input wire ioreq1_s,
input wire ioreq2_s,
output wire ioack_o
);
// axis request per channel to FSM, hold until ack
wire rx0_axis_req;
wire rx1_axis_req;
wire tx0_axis_req;
wire tx1_axis_req;
// axis request acknowledge per channel, from FSM, 1-cycle pulse
wire rx0_axis_ack;
wire rx1_axis_ack;
wire tx0_axis_ack;
wire tx1_axis_ack;
reg req_rx0;
reg req_rx1;
reg req_tx0;
reg req_tx1;
// data ports
wire [7:0] tx_axis_rdata8;
wire [7:0] rx0_axis_wdata8;
wire [7:0] rx1_axis_wdata8;
wire ack_nxt = ioreq1_s ^ ioreq2_s;
reg ack;
always @(posedge clk or negedge resetn)
begin
if (!resetn)
ack <= 1'b0;
else
ack <= ack_nxt;
end
wire ack_change = ack ^ ack_nxt;
// state[0] = ACK
// state[1] = CTL4_EN
// state[2] = RD4H_EN
// state[3] = RD4L_EN
// state[4] = STAT_EN
// state[5] = WD4H_EN
// state[6] = WD4L_EN
localparam STAT = 8'b0_001_000_0;
localparam RXC1 = 8'b0_000_001_1;
localparam RXDH = 8'b0_000_010_0;
localparam RXDL = 8'b0_000_100_1;
localparam RXDZ = 8'b0_000_000_0;
localparam STAZ = 8'b0_001_000_1;
localparam TXCZ = 8'b1_000_000_0;
localparam TXDH = 8'b1_010_000_1;
localparam TXDL = 8'b1_100_000_0;
reg [7:0] fsm_state;
reg [7:0] nxt_fsm_state;
// ifsm next-state seqeuncer
always @(*)
case (fsm_state)
STAT: nxt_fsm_state = ( ioreq1_s) ? RXC1 : STAT;
RXC1: nxt_fsm_state = (!ioreq2_s) ? RXC1 : (iodata4_i[0]) ? TXCZ : RXDH;
RXDH: nxt_fsm_state = ( ioreq2_s) ? RXDH : RXDL;
RXDL: nxt_fsm_state = (!ioreq2_s) ? RXDL : RXDZ;
RXDZ: nxt_fsm_state = ( ioreq2_s) ? RXDZ : STAZ;
STAZ: nxt_fsm_state = ( ioreq1_s) ? STAZ : STAT;
TXCZ: nxt_fsm_state = ( ioreq2_s) ? TXCZ : TXDH;
TXDH: nxt_fsm_state = (!ioreq2_s) ? TXDH : TXDL;
TXDL: nxt_fsm_state = ( ioreq2_s) ? TXDL : STAZ;
default: nxt_fsm_state = STAT;
endcase
// state update
always @(posedge clk or negedge resetn)
begin
if (!resetn) begin
fsm_state <= STAT;
end else
fsm_state <= nxt_fsm_state;
end
assign ioack_o = fsm_state[0];
// 3 input sample enable
wire cmd_state = fsm_state[1];
wire rdh_state = fsm_state[2];
wire rdl_state = fsm_state[3];
// 3 output enable
wire fif_state = fsm_state[4];
wire wdh_state = fsm_state[5];
wire wdl_state = fsm_state[6];
// command resister
reg [3:0] cmd4;
always @(posedge clk or negedge resetn)
begin
if (!resetn)
cmd4 <= 4'b1111; // invalid xfer pattern
else if (cmd_state & ack_change)
cmd4 <= iodata4_i[3:0];
end
wire [3:0] fifo_stat = ~{req_tx1, req_rx1, req_tx0, req_rx0 };
// IO Write Data
assign iodata4_o = ({4{fif_state}} & fifo_stat)
| ({4{wdh_state}} & ((cmd4[1]) ? rx1_axis_wdata8[7:4] : rx0_axis_wdata8[7:4]))
| ({4{wdl_state}} & ((cmd4[1]) ? rx1_axis_wdata8[3:0] : rx0_axis_wdata8[3:0]))
;
assign iodata4_e = {4{|(fsm_state[6:4])}};
assign iodata4_t = {4{!iodata4_e}};
// and ack
assign rx0_axis_ack = !cmd4[1] & cmd4[0] & wdl_state & ack_change;
assign rx1_axis_ack = cmd4[1] & cmd4[0] & wdl_state & ack_change;
// IO Read data
// first register high nibble read data
reg [3:0] rd4_hi;
always @(posedge clk or negedge resetn)
begin
if (!resetn)
rd4_hi <= 4'b0000; // initialize
else if (rdh_state & ack_change)
rd4_hi <= iodata4_i[3:0];
end
assign tx_axis_rdata8 = {rd4_hi[3:0],iodata4_i[3:0]};
// then ack with 8-bit data to selected axis buffer
assign tx0_axis_ack = !cmd4[1] & !cmd4[0] & rdl_state & ack_change;
assign tx1_axis_ack = cmd4[1] & !cmd4[0] & rdl_state & ack_change;
// stream buffers with valid qualifiers
reg [8:0] rx0_reg9;
reg [8:0] rx1_reg9;
reg [8:0] tx0_reg9;
reg [8:0] tx1_reg9;
// axis RX1 port interface
always @(posedge clk or negedge resetn)
begin
if (!resetn)
rx0_reg9 <= 9'b0_00000000;
else begin
if (!rx0_reg9[8] & axis_rx0_tvalid) rx0_reg9 <= {1'b1,axis_rx0_tdata8[7:0]};
else if (rx0_reg9[8] & rx0_axis_ack) rx0_reg9[8] <= 1'b0;
end
end
assign axis_rx0_tready = !rx0_reg9[8];
assign rx0_axis_wdata8 = rx0_reg9[7:0];
assign rx0_axis_req = rx0_reg9[8] & !fsm_state[2] & !fsm_state[3];
// axis RX2 port interface
always @(posedge clk or negedge resetn)
begin
if (!resetn)
rx1_reg9 <= 9'b0_00000000;
else begin
if (!rx1_reg9[8] & axis_rx1_tvalid) rx1_reg9 <= {1'b1,axis_rx1_tdata8[7:0]};
else if (rx1_reg9[8] & rx1_axis_ack) rx1_reg9[8] <= 1'b0;
end
end
assign axis_rx1_tready = !rx1_reg9[8];
assign rx1_axis_wdata8 = rx1_reg9[7:0];
assign rx1_axis_req = rx1_reg9[8] & !fsm_state[2] & !fsm_state[3];
// axis TX1 port interface
always @(posedge clk or negedge resetn)
begin
if (!resetn)
tx0_reg9 <= 9'b0_00000000;
else begin
if (!tx0_reg9[8] & tx0_axis_ack) tx0_reg9 <= {1'b1,tx_axis_rdata8[7:0]};
else if (tx0_reg9[8] & axis_tx0_tready) tx0_reg9[8] <= 1'b0;
end
end
assign axis_tx0_tvalid = tx0_reg9[8];
assign axis_tx0_tdata8[7:0] = tx0_reg9[7:0];
assign tx0_axis_req = !tx0_reg9[8];
// axis tx2 port interextio8x4_ifsmface
always @(posedge clk or negedge resetn)
begin
if (!resetn)
tx1_reg9 <= 9'b0_00000000;
else begin
if (!tx1_reg9[8] & tx1_axis_ack) tx1_reg9 <= {1'b1,tx_axis_rdata8[7:0]};
else if (tx1_reg9[8] & axis_tx1_tready) tx1_reg9[8] <= 1'b0;
end
end
assign axis_tx1_tvalid = tx1_reg9[8];
assign axis_tx1_tdata8[7:0] = tx1_reg9[7:0];
assign tx1_axis_req = !tx1_reg9[8];
// request handshake
always @(posedge clk or negedge resetn)
begin
if (!resetn)
req_rx0 <= 1'b0; // avoid X propagation
else if (rx0_axis_req & !req_rx0) // capture rx_req front edge
req_rx0 <= 1'b1;
else if (rx0_axis_ack & req_rx0)
req_rx0 <= 1'b0;
end
always @(posedge clk or negedge resetn)
begin
if (!resetn)
req_rx1 <= 1'b0; // avoid X propagation
else if (rx1_axis_req & !req_rx1) // capture rx_req front edge
req_rx1 <= 1'b1;
else if (rx1_axis_ack & req_rx1)
req_rx1 <= 1'b0;
end
// request handshake
always @(posedge clk or negedge resetn)
begin
if (!resetn)
req_tx0 <= 1'b0; // avoid X propagation
else if (tx0_axis_req & !req_tx0) // capture tx_req front edge
req_tx0 <= 1'b1;
else if (tx0_axis_ack & req_tx0)
req_tx0 <= 1'b0;
end
always @(posedge clk or negedge resetn)
begin
if (!resetn)
req_tx1 <= 1'b0; // avoid X propagation
else if (tx1_axis_req & !req_tx1) // capture tx_req front edge
req_tx1 <= 1'b1;
else if (tx1_axis_ack & req_tx1)
req_tx1 <= 1'b0;
end
endmodule
/*
extio8x4_ifsm u_extio8x4_tfsm
(
.clk ( clk ),
.resetn ( resetn ),
// RX 4-channel AXIS interface
.axis_rx0_tready ( axis_rx0_tready ),
.axis_rx0_tvalid ( axis_rx0_tvalid ),
.axis_rx0_tdata8 ( axis_rx0_tdata8 ),
.axis_rx1_tready ( axis_rx1_tready ),
.axis_rx1_tvalid ( axis_rx1_tvalid ),
.axis_rx1_tdata8 ( axis_rx1_tdata8 ),
.axis_tx0_tready ( axis_tx0_tready ),
.axis_tx0_tvalid ( axis_tx0_tvalid ),
.axis_tx0_tdata8 ( axis_tx0_tdata8 ),
.axis_tx1_tready ( axis_tx1_tready ),
.axis_tx1_tvalid ( axis_tx1_tvalid ),
.axis_tx1_tdata8 ( axis_tx1_tdata8 ),
// external io interface
.iodata4_i ( iodata4_i ),
.iodata4_o ( iodata4_o ),
.iodata4_e ( iodata4_e ),
.iodata4_t ( iodata4_t ),
.ioreq1_s ( ioreq1_s ),
.ioreq2_s ( ioreq2_s ),
.ioack_o ( ioack_o )
);
*/
# Definitional proc to organize widgets for parameters.
proc init_gui { IPINST } {
ipgui::add_param $IPINST -name "Component_Name"
#Adding Page
ipgui::add_page $IPINST -name "Page 0"
}