Commit e94b62c6 authored by Andrey Filippov's avatar Andrey Filippov

added modupe to abort/recover AXI HP port after SATA errors, more debugging of the hardware

parent 50ca592a
......@@ -52,87 +52,87 @@
<link>
<name>vivado_logs/VivadoBitstream.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoBitstream-20160205231700944.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoBitstream-20160208095350202.log</location>
</link>
<link>
<name>vivado_logs/VivadoOpt.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOpt-20160205231700944.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOpt-20160208095350202.log</location>
</link>
<link>
<name>vivado_logs/VivadoOptPhys.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOptPhys-20160205231700944.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOptPhys-20160208095350202.log</location>
</link>
<link>
<name>vivado_logs/VivadoOptPower.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOptPower-20160205231700944.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoOptPower-20160208095350202.log</location>
</link>
<link>
<name>vivado_logs/VivadoPlace.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoPlace-20160205231700944.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoPlace-20160208095350202.log</location>
</link>
<link>
<name>vivado_logs/VivadoRoute.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoRoute-20160205231700944.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoRoute-20160208095350202.log</location>
</link>
<link>
<name>vivado_logs/VivadoSynthesis.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoSynthesis-20160205231700944.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoSynthesis-20160208095139740.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimimgSummaryReportImplemented.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimimgSummaryReportImplemented-20160205231700944.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimimgSummaryReportImplemented-20160208095350202.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimimgSummaryReportSynthesis.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimimgSummaryReportSynthesis-20160205231700944.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimimgSummaryReportSynthesis-20160208095139740.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimingReportImplemented.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimingReportImplemented-20160205231700944.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimingReportImplemented-20160208095350202.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimingReportSynthesis.log</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimingReportSynthesis-20160205231700944.log</location>
<location>/home/andrey/git/x393_sata/vivado_logs/VivadoTimingReportSynthesis-20160208095139740.log</location>
</link>
<link>
<name>vivado_state/x393_sata-opt-phys.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-phys-20160205231700944.dcp</location>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-phys-20160208095350202.dcp</location>
</link>
<link>
<name>vivado_state/x393_sata-opt-power.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-power-20160205231700944.dcp</location>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-power-20160208095350202.dcp</location>
</link>
<link>
<name>vivado_state/x393_sata-opt.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-20160205231700944.dcp</location>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-opt-20160208095350202.dcp</location>
</link>
<link>
<name>vivado_state/x393_sata-place.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-place-20160205231700944.dcp</location>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-place-20160208095350202.dcp</location>
</link>
<link>
<name>vivado_state/x393_sata-route.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-route-20160205231700944.dcp</location>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-route-20160208095350202.dcp</location>
</link>
<link>
<name>vivado_state/x393_sata-synth.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-synth-20160205231700944.dcp</location>
<location>/home/andrey/git/x393_sata/vivado_state/x393_sata-synth-20160208095139740.dcp</location>
</link>
</linkedResources>
</projectDescription>
This diff is collapsed.
......@@ -144,7 +144,7 @@ module ahci_fsm
input dma_cmd_busy, // output reg (DMA engine is processing PRDs)
/// input dma_cmd_done, // output (last PRD is over)
output dma_cmd_abort, // try to abort a command
input dma_abort_done, // if abort is not needed, will generate dma_abort_done just next cycle
// Communication with ahci_fis_receive (some are unused)
// Debug features
......@@ -257,15 +257,20 @@ module ahci_fsm
// reg jump_r;
reg [2:0] fsm_jump;
wire fsm_next;
reg fsm_next_r;
// reg fsm_next_r;
reg fsm_actions; // processing actions
reg fsm_act_busy;
reg [1:0] fsm_transitions; // processing transitions
reg fsm_preload; // read first sequence data (2 cycles for regen)
// wire [7:0] precond_w = pgm_data[17:10]; // select what to use - cond_met_w valis after precond_w, same time as conditions
// reg [7:0] conditions;
wire pre_jump_w = (|async_pend_r) ? async_ackn : |(cond_met_w & fsm_transitions[1]);
wire fsm_act_done = get_fis_done || xmit_done || (syncesc_send_pend && syncesc_send_done);
// wire pre_jump_w = (|async_pend_r) ? async_ackn : |(cond_met_w & fsm_transitions[1]);
wire pre_jump_w = (|async_pend_r) ? async_ackn : (cond_met_w & fsm_transitions[1]);
wire fsm_act_done = get_fis_done ||
xmit_done ||
(syncesc_send_pend && syncesc_send_done) ||
dma_abort_done ||
asynq_rq; // cominit_got || pcmd_st_cleared
wire fsm_wait_act_w = pgm_data[16]; // this action requires waiting for done
wire fsm_last_act_w = pgm_data[17];
......@@ -283,6 +288,14 @@ module ahci_fsm
wire phy_ready_chng_w = !hba_rst && !was_rst && (phy_ready != phy_ready_prev);
reg was_last_action_r; // delay last action if it was fsm_wait_act;
wire fsm_transitions_w = // next will be transitions processing
(fsm_last_act_w && fsm_actions && fsm_next && !fsm_wait_act_w) ||
(fsm_act_busy && fsm_act_done && was_last_action_r);
wire conditions_ce = // copy all conditions to the register so they will not change while iterating through them
!fsm_transitions_w && !fsm_transitions[0];
assign fsm_next = (fsm_preload || (fsm_actions && !update_busy && !fsm_act_busy) || fsm_transitions[0]) && !async_pend_r[0]; // quiet if received cominit is pending
assign update_all = fsm_jump[0];
......@@ -344,8 +357,9 @@ module ahci_fsm
if (fsm_actions && fsm_next) was_last_action_r <= fsm_last_act_w;
if (hba_rst || pre_jump_w) fsm_transitions <= 0;
else if ((fsm_last_act_w && fsm_actions && fsm_next && !fsm_wait_act_w) ||
(fsm_act_busy && fsm_act_done && was_last_action_r) ) fsm_transitions <= 1;
else if (fsm_transitions_w) fsm_transitions <= 1;
// else if ((fsm_last_act_w && fsm_actions && fsm_next && !fsm_wait_act_w) ||
// (fsm_act_busy && fsm_act_done && was_last_action_r) ) fsm_transitions <= 1;
else fsm_transitions <= {fsm_transitions[0],fsm_transitions[0]};
if (hba_rst) fsm_preload <= 0;
......@@ -460,6 +474,7 @@ module ahci_fsm
// Condition inputs may be registered if needed
condition_mux condition_mux_i (
.clk (mclk), // input
.ce (conditions_ce), // input
.sel (pgm_data[17:10]), // input[7:0]
.condition (cond_met_w), // output
//COMPOSITE
......
......@@ -92,7 +92,9 @@ module ahci_sata_layers #(
input wire rxp_in,
input wire rxn_in,
output [31:0] debug_sata
output [31:0] debug_phy,
output [31:0] debug_link
);
localparam PHY_SPEED = 2; // SATA2
......@@ -169,8 +171,8 @@ module ahci_sata_layers #(
wire d2h_fifo_wr = ll_d2h_valid || fis_over_r; // fis_over_r will push FIS end to FIFO
reg h2d_pending; // HBA started sending FIS to fifo
wire [31:0] debug_phy;
wire [31:0] debug_link;
// wire [31:0] debug_phy;
// wire [31:0] debug_link;
wire rxelsfull;
wire rxelsempty;
......@@ -184,7 +186,7 @@ module ahci_sata_layers #(
// assign debug_sata = {debug_link[31:4],debug_phy[3:0]} ; //
// assign debug_sata = {debug_link[31:8],debug_phy[7:0]} ; //
assign debug_sata = {debug_link[27:20],debug_phy[23:0]} ; //
// assign debug_sata = {debug_link[27:20],debug_phy[23:0]} ; //
assign ll_h2d_last = (h2d_type_out == H2D_TYPE_FIS_LAST);
assign d2h_valid = d2h_nempty;
......@@ -260,7 +262,7 @@ module ahci_sata_layers #(
.link_reset (ll_link_reset), // input wire // oob sequence is reinitiated and link now is not established or rxelecidle
.sync_escape_req (syncesc_send), // input wire // TL demands to brutally cancel current transaction
.sync_escape_ack (syncesc_send_done), // output wire // acknowlegement of a successful reception?
.incom_stop_req (pcmd_st_cleared), // input wire // TL demands to stop current recieving session
.incom_stop_req (pcmd_st_cleared), // input wire // TL demands to stop current recieving session
.link_established (link_established),
// inputs from phy
.phy_ready (phy_ready), // input wire // phy is ready - link is established
......
This diff is collapsed.
......@@ -115,7 +115,10 @@ module axi_ahci_regs#(
output afi_cache_set,
output was_hba_rst, // last reset was hba reset (not counting system reset)
output was_port_rst, // last reset was port reset
input [31:0] debug_in
input [31:0] debug_in0,
input [31:0] debug_in1,
input [31:0] debug_in2,
input [31:0] debug_in3
`ifdef USE_DATASCOPE
// Datascope interface (write to memory that can be software-read)
,input datascope_clk,
......@@ -188,6 +191,7 @@ module axi_ahci_regs#(
reg wait_first_access = RESET_TO_FIRST_ACCESS; // keep port reset until first access
wire any_access = bram_wen_r || bram_ren[0];
reg debug_rd_r;
reg [31:0] debug_r;
assign bram_addr = bram_ren[0] ? bram_raddr[ADDRESS_BITS-1:0] : (bram_wen_r ? bram_waddr_r : bram_waddr[ADDRESS_BITS-1:0]);
......@@ -198,7 +202,6 @@ module axi_ahci_regs#(
assign was_hba_rst = was_hba_rst_r[0];
assign was_port_rst = was_port_rst_r[0];
always @(posedge aclk) begin
if (arst) write_busy_r <= 0;
......@@ -207,7 +210,7 @@ module axi_ahci_regs#(
if (bram_wen) bram_wdata_r <= bram_wdata;
if (bram_ren[1]) bram_rdata_r <= debug_rd_r? debug_in : bram_rdata;
// if (bram_ren[1]) bram_rdata_r <= debug_rd_r? debug_in : bram_rdata;
bram_wstb_r <= {4{bram_wen}} & bram_wstb;
......@@ -215,8 +218,17 @@ module axi_ahci_regs#(
if (bram_wen) bram_waddr_r <= bram_waddr[ADDRESS_BITS-1:0];
if (bram_ren[0]) debug_rd_r <= &bram_raddr[ADDRESS_BITS-1:4]; // last 16 DWORDs (With AXIBRAM_BITS will be duplicated)
if (bram_ren[0]) debug_r <= bram_raddr[1]? (bram_raddr[0] ? debug_in3: debug_in2):
(bram_raddr[0] ? debug_in1: debug_in0);
if (bram_ren[1]) bram_rdata_r <= debug_rd_r? debug_r : bram_rdata;
end
//debug_rd_r
generate
genvar i;
for (i=0; i < 32; i=i+1) begin: bit_type_block
......@@ -281,10 +293,6 @@ module axi_ahci_regs#(
if (pgm_fsm_set_w) pgm_ad <= ahci_regs_di[17:0];
end
always @(posedge aclk) begin
if (bram_ren[0]) debug_rd_r <= &bram_raddr[ADDRESS_BITS-1:4]; // last 16 DWORDs (With AXIBRAM_BITS will be duplicated)
end
//debug_rd_r
/*
......
/*******************************************************************************
* Module: axi_hp_abort
* Date:2016-02-07
* Author: andrey
* Description: Trying to gracefully reset AXI HP after aborted transmission
* For read channel - just keep afi_rready on until RD FIFO is empty (afi_rcount ==0)
* For write - keep track aof all what was sent so far, assuming aw is always ahead of w
* Reset only by global reset (system POR) - probably it is not possible to just
* reset PL or relaod bitfile,
*
* Copyright (c) 2016 Elphel, Inc .
* axi_hp_abort.v is free software; 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 3 of the License, or
* (at your option) any later version.
*
* axi_hp_abort.v 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 program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
module axi_hp_abort(
input hclk,
input hrst, // just disables processing inputs
input abort,
output busy, // should disable control of afi_wvalid, afi_awid
output reg done,
input afi_awvalid, // afi_awready is supposed to be always on when afi_awvalid (caller uses fifo counetrs) ?
input afi_awready, //
input [ 5:0] afi_awid,
input [3:0] afi_awlen,
input afi_wvalid_in,
input afi_wready,
output afi_wvalid,
output reg [ 5:0] afi_wid,
input afi_arvalid,
input afi_arready,
input [ 3:0] afi_arlen,
input afi_rready_in,
input afi_rvalid,
output afi_rready,
output afi_wlast,
// TODO: Try to resolve problems when afi_racount, afi_wacount afi_wcount do not match expected
input [ 2:0] afi_racount,
input [ 7:0] afi_rcount,
input [ 5:0] afi_wacount,
input [ 7:0] afi_wcount,
output reg dirty, // single bit to be sampled in different clock domain to see if flushing is needed
output reg axi_mismatch, // calculated as 'dirty' but axi hp counters are 0
output [21:0] debug
);
reg busy_r;
wire done_w = busy_r && !dirty ;
reg [3:0] aw_lengths_ram[0:31];
reg [4:0] aw_lengths_waddr = 0;
reg [4:0] aw_lengths_raddr = 0;
reg [5:0] aw_count = 0;
reg [7:0] w_count = 0;
reg [7:0] r_count = 0;
reg adav = 0;
wire arwr = !hrst && afi_arvalid && afi_arready;
wire drd = !hrst && afi_rvalid && afi_rready_in;
wire awr = !hrst && afi_awvalid && afi_awready;
reg ard_r = 0; // additional length read if not much data
wire ard = adav && ((|w_count[7:4]) || ard_r);
wire wwr = !hrst && afi_wready && afi_wvalid_in;
reg afi_rready_r;
reg afi_wlast_r; // wait one cycle after last in each burst (just to ease timing)
reg busy_aborting; // actually aborting
wire reset_counters = busy_r && !busy_aborting;
assign busy = busy_r;
assign afi_rready = busy_aborting && (|r_count) && ((|afi_rcount[7:1]) || (!afi_rready_r && afi_rcount[0]));
assign afi_wlast = busy_aborting && adav && (w_count[3:0] == aw_lengths_ram[aw_lengths_raddr]);
assign afi_wvalid = busy_aborting && adav && !afi_wlast_r;
assign debug = {aw_count[5:0], w_count[7:0], r_count[7:0]};
// Watch for transactios performed by others (and this one too)
always @ (posedge hclk) begin
// read channel
if (reset_counters) r_count <= 0;
else if (drd)
if (arwr) r_count <= r_count + {4'b0, afi_arlen};
else r_count <= r_count - 1;
else
if (arwr) r_count <= w_count + {4'b0, afi_arlen} + 1;
// write channel
if (awr) afi_wid <= afi_awid; // one command is supposed to use just one awid/wid
if (awr) aw_lengths_ram [aw_lengths_waddr] <= afi_awlen;
if (reset_counters) aw_lengths_waddr <= 0;
else if (awr) aw_lengths_waddr <= aw_lengths_waddr + 1;
if (reset_counters) aw_lengths_raddr <= 0;
else if (ard) aw_lengths_raddr <= aw_lengths_raddr + 1;
if (reset_counters) aw_count <= 0;
else if ( awr && !ard) aw_count <= aw_count + 1;
else if (!awr && ard) aw_count <= aw_count - 1;
adav <= !reset_counters && (|aw_count[5:1]) || ((awr || aw_count[0]) && !ard) || (awr && aw_count[0]);
ard_r <= !ard && adav && (w_count[3:0] > aw_lengths_ram[aw_lengths_raddr]);
if (reset_counters) w_count <= 0;
else if (wwr)
if (ard) w_count <= w_count - {4'b0, aw_lengths_ram[aw_lengths_raddr]};
else w_count <= w_count + 1;
else
if (ard) w_count <= w_count - {4'b0, aw_lengths_ram[aw_lengths_raddr]} - 1;
dirty <= (|r_count) || (|aw_count); // assuming w_count can never be non-zero? - no
end
// flushing part
always @ (posedge hclk) begin
if (abort) busy_r <= 1;
else if (done_w) busy_r <= 0;
if (abort && ((|afi_racount) || (|afi_rcount) || (|afi_wacount) || (|afi_wcount))) busy_aborting <= 1;
else if (done_w) busy_aborting <= 0;
done <= done_w;
afi_rready_r <= afi_rready;
afi_wlast_r <= afi_wlast;
axi_mismatch <= busy && !busy_aborting && dirty; //
end
endmodule
......@@ -224,7 +224,8 @@
reg [2:0] nhrst_r;
wire hrst = !nhrst_r[2];
wire [31:0] debug_sata;
wire [31:0] debug_phy;
wire [31:0] debug_link;
always @ (posedge hclk or posedge arst) begin
if (arst) nhrst_r <= 0;
......@@ -365,7 +366,8 @@
.sctl_ipm (sctl_ipm), // output[3:0]
.sctl_spd (sctl_spd), // output[3:0]
.irq (irq), // output
.debug_in (debug_sata) // input[31:0]
.debug_in_phy (debug_phy), // input[31:0]
.debug_in_link (debug_link) // input[31:0]
);
ahci_sata_layers #(
......@@ -424,7 +426,8 @@
.txn_out (TXN), // output wire
.rxp_in (RXP), // input wire
.rxn_in (RXN), // input wire
.debug_sata (debug_sata) // output[31:0]
.debug_phy (debug_phy), // output[31:0]
.debug_link (debug_link) // output[31:0]
);
......
/*******************************************************************************
* Module: action_decoder
* Date:2016-01-27
* Date:2016-02-07
* Author: auto-generated file, see ahci_fsm_sequence.py
* Description: Decode sequencer code to 1-hot actions
*******************************************************************************/
......
/*******************************************************************************
* Module: condition_mux
* Date:2016-01-27
* Date:2016-02-07
* Author: auto-generated file, see ahci_fsm_sequence.py
* Description: Select condition
*******************************************************************************/
......@@ -9,6 +9,7 @@
module condition_mux (
input clk,
input ce, // enable recording all conditions
input [ 7:0] sel,
output condition,
input ST_NB_ND,
......@@ -57,57 +58,104 @@ module condition_mux (
input X_RDY_COLLISION);
wire [44:0] masked;
reg [43:0] registered;
reg [ 5:0] cond_r;
assign condition = |cond_r;
assign masked[ 0] = ST_NB_ND && sel[ 2] && sel[ 1] && sel[ 0];
assign masked[ 1] = PXCI0_NOT_CMDTOISSUE && sel[ 3] && sel[ 1] && sel[ 0];
assign masked[ 2] = PCTI_CTBAR_XCZ && sel[ 4] && sel[ 1] && sel[ 0];
assign masked[ 3] = PCTI_XCZ && sel[ 5] && sel[ 1] && sel[ 0];
assign masked[ 4] = NST_D2HR && sel[ 6] && sel[ 1] && sel[ 0];
assign masked[ 5] = NPD_NCA && sel[ 7] && sel[ 1] && sel[ 0];
assign masked[ 6] = CHW_DMAA && sel[ 3] && sel[ 2] && sel[ 0];
assign masked[ 7] = SCTL_DET_CHANGED_TO_4 && sel[ 4] && sel[ 2] && sel[ 0];
assign masked[ 8] = SCTL_DET_CHANGED_TO_1 && sel[ 5] && sel[ 2] && sel[ 0];
assign masked[ 9] = PXSSTS_DET_NE_3 && sel[ 6] && sel[ 2] && sel[ 0];
assign masked[10] = PXSSTS_DET_EQ_1 && sel[ 7] && sel[ 2] && sel[ 0];
assign masked[11] = NPCMD_FRE && sel[ 4] && sel[ 3] && sel[ 0];
assign masked[12] = FIS_OK && sel[ 5] && sel[ 3] && sel[ 0];
assign masked[13] = FIS_ERR && sel[ 6] && sel[ 3] && sel[ 0];
assign masked[14] = FIS_FERR && sel[ 7] && sel[ 3] && sel[ 0];
assign masked[15] = FIS_EXTRA && sel[ 5] && sel[ 4] && sel[ 0];
assign masked[16] = FIS_FIRST_INVALID && sel[ 6] && sel[ 4] && sel[ 0];
assign masked[17] = FR_D2HR && sel[ 7] && sel[ 4] && sel[ 0];
assign masked[18] = FIS_DATA && sel[ 6] && sel[ 5] && sel[ 0];
assign masked[19] = FIS_ANY && sel[ 7] && sel[ 5] && sel[ 0];
assign masked[20] = NB_ND_D2HR_PIO && sel[ 7] && sel[ 6] && sel[ 0];
assign masked[21] = D2HR && sel[ 3] && sel[ 2] && sel[ 1];
assign masked[22] = SDB && sel[ 4] && sel[ 2] && sel[ 1];
assign masked[23] = DMA_ACT && sel[ 5] && sel[ 2] && sel[ 1];
assign masked[24] = DMA_SETUP && sel[ 6] && sel[ 2] && sel[ 1];
assign masked[25] = BIST_ACT_FE && sel[ 7] && sel[ 2] && sel[ 1];
assign masked[26] = BIST_ACT && sel[ 4] && sel[ 3] && sel[ 1];
assign masked[27] = PIO_SETUP && sel[ 5] && sel[ 3] && sel[ 1];
assign masked[28] = NB_ND && sel[ 6] && sel[ 3] && sel[ 1];
assign masked[29] = TFD_STS_ERR && sel[ 7] && sel[ 3] && sel[ 1];
assign masked[30] = FIS_I && sel[ 5] && sel[ 4] && sel[ 1];
assign masked[31] = PIO_I && sel[ 6] && sel[ 4] && sel[ 1];
assign masked[32] = NPD && sel[ 7] && sel[ 4] && sel[ 1];
assign masked[33] = PIOX && sel[ 6] && sel[ 5] && sel[ 1];
assign masked[34] = XFER0 && sel[ 7] && sel[ 5] && sel[ 1];
assign masked[35] = PIOX_XFER0 && sel[ 7] && sel[ 6] && sel[ 1];
assign masked[36] = CTBAA_CTBAP && sel[ 4] && sel[ 3] && sel[ 2];
assign masked[37] = CTBAP && sel[ 5] && sel[ 3] && sel[ 2];
assign masked[38] = CTBA_B && sel[ 6] && sel[ 3] && sel[ 2];
assign masked[39] = CTBA_C && sel[ 7] && sel[ 3] && sel[ 2];
assign masked[40] = TX_ERR && sel[ 5] && sel[ 4] && sel[ 2];
assign masked[41] = SYNCESC_ERR && sel[ 6] && sel[ 4] && sel[ 2];
assign masked[42] = DMA_PRD_IRQ_PEND && sel[ 7] && sel[ 4] && sel[ 2];
assign masked[43] = X_RDY_COLLISION && sel[ 6] && sel[ 5] && sel[ 2];
assign masked[ 0] = registered[ 0] && sel[ 2] && sel[ 1] && sel[ 0];
assign masked[ 1] = registered[ 1] && sel[ 3] && sel[ 1] && sel[ 0];
assign masked[ 2] = registered[ 2] && sel[ 4] && sel[ 1] && sel[ 0];
assign masked[ 3] = registered[ 3] && sel[ 5] && sel[ 1] && sel[ 0];
assign masked[ 4] = registered[ 4] && sel[ 6] && sel[ 1] && sel[ 0];
assign masked[ 5] = registered[ 5] && sel[ 7] && sel[ 1] && sel[ 0];
assign masked[ 6] = registered[ 6] && sel[ 3] && sel[ 2] && sel[ 0];
assign masked[ 7] = registered[ 7] && sel[ 4] && sel[ 2] && sel[ 0];
assign masked[ 8] = registered[ 8] && sel[ 5] && sel[ 2] && sel[ 0];
assign masked[ 9] = registered[ 9] && sel[ 6] && sel[ 2] && sel[ 0];
assign masked[10] = registered[10] && sel[ 7] && sel[ 2] && sel[ 0];
assign masked[11] = registered[11] && sel[ 4] && sel[ 3] && sel[ 0];
assign masked[12] = registered[12] && sel[ 5] && sel[ 3] && sel[ 0];
assign masked[13] = registered[13] && sel[ 6] && sel[ 3] && sel[ 0];
assign masked[14] = registered[14] && sel[ 7] && sel[ 3] && sel[ 0];
assign masked[15] = registered[15] && sel[ 5] && sel[ 4] && sel[ 0];
assign masked[16] = registered[16] && sel[ 6] && sel[ 4] && sel[ 0];
assign masked[17] = registered[17] && sel[ 7] && sel[ 4] && sel[ 0];
assign masked[18] = registered[18] && sel[ 6] && sel[ 5] && sel[ 0];
assign masked[19] = registered[19] && sel[ 7] && sel[ 5] && sel[ 0];
assign masked[20] = registered[20] && sel[ 7] && sel[ 6] && sel[ 0];
assign masked[21] = registered[21] && sel[ 3] && sel[ 2] && sel[ 1];
assign masked[22] = registered[22] && sel[ 4] && sel[ 2] && sel[ 1];
assign masked[23] = registered[23] && sel[ 5] && sel[ 2] && sel[ 1];
assign masked[24] = registered[24] && sel[ 6] && sel[ 2] && sel[ 1];
assign masked[25] = registered[25] && sel[ 7] && sel[ 2] && sel[ 1];
assign masked[26] = registered[26] && sel[ 4] && sel[ 3] && sel[ 1];
assign masked[27] = registered[27] && sel[ 5] && sel[ 3] && sel[ 1];
assign masked[28] = registered[28] && sel[ 6] && sel[ 3] && sel[ 1];
assign masked[29] = registered[29] && sel[ 7] && sel[ 3] && sel[ 1];
assign masked[30] = registered[30] && sel[ 5] && sel[ 4] && sel[ 1];
assign masked[31] = registered[31] && sel[ 6] && sel[ 4] && sel[ 1];
assign masked[32] = registered[32] && sel[ 7] && sel[ 4] && sel[ 1];
assign masked[33] = registered[33] && sel[ 6] && sel[ 5] && sel[ 1];
assign masked[34] = registered[34] && sel[ 7] && sel[ 5] && sel[ 1];
assign masked[35] = registered[35] && sel[ 7] && sel[ 6] && sel[ 1];
assign masked[36] = registered[36] && sel[ 4] && sel[ 3] && sel[ 2];
assign masked[37] = registered[37] && sel[ 5] && sel[ 3] && sel[ 2];
assign masked[38] = registered[38] && sel[ 6] && sel[ 3] && sel[ 2];
assign masked[39] = registered[39] && sel[ 7] && sel[ 3] && sel[ 2];
assign masked[40] = registered[40] && sel[ 5] && sel[ 4] && sel[ 2];
assign masked[41] = registered[41] && sel[ 6] && sel[ 4] && sel[ 2];
assign masked[42] = registered[42] && sel[ 7] && sel[ 4] && sel[ 2];
assign masked[43] = registered[43] && sel[ 6] && sel[ 5] && sel[ 2];
assign masked[44] = !(|sel); // always TRUE condition (sel ==0)
always @(posedge clk) begin
if (ce) begin
registered[ 0] <= ST_NB_ND;
registered[ 1] <= PXCI0_NOT_CMDTOISSUE;
registered[ 2] <= PCTI_CTBAR_XCZ;
registered[ 3] <= PCTI_XCZ;
registered[ 4] <= NST_D2HR;
registered[ 5] <= NPD_NCA;
registered[ 6] <= CHW_DMAA;
registered[ 7] <= SCTL_DET_CHANGED_TO_4;
registered[ 8] <= SCTL_DET_CHANGED_TO_1;
registered[ 9] <= PXSSTS_DET_NE_3;
registered[10] <= PXSSTS_DET_EQ_1;
registered[11] <= NPCMD_FRE;
registered[12] <= FIS_OK;
registered[13] <= FIS_ERR;
registered[14] <= FIS_FERR;
registered[15] <= FIS_EXTRA;
registered[16] <= FIS_FIRST_INVALID;
registered[17] <= FR_D2HR;
registered[18] <= FIS_DATA;
registered[19] <= FIS_ANY;
registered[20] <= NB_ND_D2HR_PIO;
registered[21] <= D2HR;
registered[22] <= SDB;
registered[23] <= DMA_ACT;
registered[24] <= DMA_SETUP;
registered[25] <= BIST_ACT_FE;
registered[26] <= BIST_ACT;
registered[27] <= PIO_SETUP;
registered[28] <= NB_ND;
registered[29] <= TFD_STS_ERR;
registered[30] <= FIS_I;
registered[31] <= PIO_I;
registered[32] <= NPD;
registered[33] <= PIOX;
registered[34] <= XFER0;
registered[35] <= PIOX_XFER0;
registered[36] <= CTBAA_CTBAP;
registered[37] <= CTBAP;
registered[38] <= CTBA_B;
registered[39] <= CTBA_C;
registered[40] <= TX_ERR;
registered[41] <= SYNCESC_ERR;
registered[42] <= DMA_PRD_IRQ_PEND;
registered[43] <= X_RDY_COLLISION;
end
cond_r[ 0] <= |masked[ 7: 0];
cond_r[ 1] <= |masked[15: 8];
cond_r[ 2] <= |masked[23:16];
......
......@@ -53,7 +53,7 @@ actions = ['NOP',
# FIS_TRANSMIT
'CLEAR_CMD_TO_ISSUE',
# DMA
'DMA_ABORT', 'DMA_PRD_IRQ_CLEAR',
'DMA_ABORT*', 'DMA_PRD_IRQ_CLEAR',
# SATA TRANSPORT/LINK/PHY
'XMIT_COMRESET', 'SEND_SYNC_ESC*', 'SET_OFFLINE', 'R_OK', 'R_ERR',
# FIS TRANSMIT/WAIT DONE
......@@ -158,7 +158,7 @@ sequence = [{LBL:'POR', ADDR: 0x0, ACT: NOP},
{ GOTO:'P:NotRunning'},
{LBL:'P:StartBitCleared', ACT: 'PXCI0_CLEAR'}, # pxci0_clear
{ ACT: 'DMA_ABORT'}, # dma_cmd_abort (should eventually clear PxCMD.CR)?
{ ACT: 'DMA_ABORT*'}, # dma_cmd_abort (should eventually clear PxCMD.CR)?
{ ACT: 'PCMD_CR_CLEAR'}, # pcmd_cr_reset
{ ACT: 'XFER_CNTR_CLEAR'}, # clear_xfer_cntr
......@@ -477,6 +477,7 @@ def condition_mux_verilog(conditions, condition_vals, module_name, fanout, file=
module %s (
input clk,
input ce, // enable recording all conditions
input [%2d:0] sel,
output condition,"""
v=max(condition_vals.values())
......@@ -485,15 +486,14 @@ module %s (
num_inputs += 1
v >>= 1
maximal_length = max([len(n) for n in conditions])
# numregs = (len(conditions) + fanout - 1) // fanout
numregs = (len(conditions) + fanout) // fanout # one more bit for 'always' (sel == 0)
header = header_template%(module_name, datetime.date.today().isoformat(), os.path.basename(__file__), module_name, num_inputs-1)
print(header,file=file)
for input_name in conditions[:len(conditions)-1]:
print(" input %s,"%(input_name),file=file)
print(" input %s);\n"%(conditions[-1]),file=file)
# print(" wire [%2d:0] masked;"%(len(conditions)-1),file=file)
print(" wire [%2d:0] masked;"%(len(conditions)),file=file)
print(" input %s,"%(input_name), file=file)
print(" input %s);\n"%(conditions[-1]), file=file)
print(" wire [%2d:0] masked;"%(len(conditions)), file=file)
print(" reg [%2d:0] registered;"%(len(conditions) -1),file=file)
if numregs > 1:
print(" reg [%2d:0] cond_r;\n"%(numregs-1),file=file)
else:
......@@ -505,7 +505,8 @@ module %s (
print(" assign condition = cond_r;\n",file=file)
for b in range (len(conditions)):
print(" assign masked[%2d] = %s %s"%(b, conditions[b] , " "*(maximal_length - len(conditions[b]))),end="",file=file)
# print(" assign masked[%2d] = %s %s"%(b, conditions[b] , " "*(maximal_length - len(conditions[b]))),end="",file=file)
print(" assign masked[%2d] = registered[%2d] "%(b, b),end="",file=file)
d = condition_vals[conditions[b]]
for nb in range(num_inputs-1,-1,-1):
......@@ -514,7 +515,13 @@ module %s (
print (";", file=file)
print(" assign masked[%2d] = !(|sel); // always TRUE condition (sel ==0)"%(len(conditions)), file=file)
print ("\n always @(posedge clk) begin", file=file)
print ("\n always @(posedge clk) begin", file=file)
print (" if (ce) begin", file=file)
for b in range (len(conditions)):
print(" registered[%2d] <= %s;"%(b, conditions[b]),file=file)
print (" end", file=file)
for nb in range (numregs):
ll = nb * fanout
# hl = min(ll + fanout, len(conditions)) -1
......
......@@ -15,6 +15,6 @@
, .INIT_0E (256'h00F60082011000ED24FB250200C000390401011000E624FB2502018000500101)
, .INIT_0F (256'h0100020101000021021001000021004400F6000000F6011000F424FB250200C0)
, .INIT_10 (256'h0000000000000000000000000000000000000000000000390041000001000000)
, .INITP_00 (256'hC8220098170902401E272722222800309418800820809C802018880022222222)
, .INITP_00 (256'hC8220098170902401E272722222800309418810820809C802018880022222222)
, .INITP_01 (256'h22082227209C82720A09C22089C680272181A01CB889C8605A2A89C882068270)
, .INITP_02 (256'h0000000000000000000000000000000000000000000000000000000000000082)
This diff is collapsed.
......@@ -762,15 +762,35 @@ localparam SYS_MEM_SIZE = 16384; // bytes - size of system memory
localparam COMMAND_TABLE = 32'h3f00; // 256 bytes for a command table in the system memory
localparam IDENTIFY_BUF = 32'h3d00; // 512 bytes for a command table in the system memory
localparam PRD_OFFSET = 'h80; // start of PRD table - 128-th byte in command table
localparam ATA_IDFY = 'hec; // Identify command
localparam ATA_WDMA = 'hca; // Identify command
localparam ATA_IDFY = 'hec; // Identify command
localparam ATA_WDMA = 'hca; // Write to device in DMA mode
localparam ATA_WBUF_PIO = 'he8; // Write 512 bytes to device buffer in PIO mode @SuppressThisWarning VEditor - not yet used
localparam ATA_WBUF_DMA = 'heb; // Write 512 bytes to device buffer in DMA mode @SuppressThisWarning VEditor - not yet used
localparam ATA_RDMA = 'hc8; // Read from device in DMA mode @SuppressThisWarning VEditor - not yet used
localparam ATA_RBUF_PIO = 'he4; // Read 512 bytes from device buffer in PIO mode @SuppressThisWarning VEditor - not yet used
localparam ATA_RBUF_DMA = 'he9; // Read 512 bytes from device buffer in DMA mode @SuppressThisWarning VEditor - not yet used
reg [31:0] sysmem[0:4095];
// connect system memory ty AXI_NP RD and WR channels
// assign HCLK = dut.ps7_i.SAXIHP3ACLK; // shortcut name
// afi loopback
assign #1 afi_sim_rd_valid = afi_sim_rd_ready;
// This is for no-delay memory
// assign #1 afi_sim_rd_valid = afi_sim_rd_ready;
// Make long delay for the first memory read, zero - for the next
reg afi_sim_rd_ready_r;
integer read_system_delay;
localparam SYSTEM_MEMORY_READ_LATENCY = 10; // HCLK cycles
always @ (posedge HCLK) begin
if (!afi_sim_rd_ready) read_system_delay <= SYSTEM_MEMORY_READ_LATENCY;
else if (read_system_delay != 0) read_system_delay <= read_system_delay - 1;
afi_sim_rd_ready_r <= afi_sim_rd_ready && (read_system_delay == 0);
end
assign #1 afi_sim_rd_valid = afi_sim_rd_ready && afi_sim_rd_ready_r;
assign #1 afi_sim_rd_resp = afi_sim_rd_ready?2'b0:2'bx;
assign #1 afi_sim_wr_ready = 1; // afi_sim_wr_valid;
assign #1 afi_sim_bresp_latency=4'h5;
......@@ -809,7 +829,9 @@ localparam ATA_WDMA = 'hca; // Identify command
task setup_pio_read_identify_command_simple;
input integer data_len;
input integer prd_int; // [0] - first prd interrupt, ... [31] - 31-st
integer i;
begin
// clear system memory for command
......@@ -822,7 +844,7 @@ localparam ATA_WDMA = 'hca; // Identify command
// All other 4 DWORDs are 0 for this command
// Set PRDT (single item) TODO: later check multiple small ones
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 0] = SYS_MEM_START + IDENTIFY_BUF;
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 3] = (prd_int[0] << 31) | 511; // 512 bytes in this PRDT
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 3] = (prd_int[0] << 31) | (data_len-1); // 512 bytes in this PRDT
// Setup command header
maxigp1_writep ((CLB_OFFS32 + 0) << 2, (5 << 0) | // 'CFL' - number of DWORDs in thes CFIS
(0 << 5) | // 'A' Not ATAPI
......@@ -939,7 +961,7 @@ localparam ATA_WDMA = 'hca; // Identify command
// fill ATA command
sysmem[(COMMAND_TABLE >> 2) + 0] = FIS_H2DR | // FIS type - H2D register (0x27)
('h80 << 8) | // set C = 1
(ATA_WDMA << 16) | // Command = 0xEC (IDFY)
(ATA_WDMA << 16) | // Command = 0xCA
( 0 << 24); // features = 0 ?
sysmem[(COMMAND_TABLE >> 2) + 1] = lba & 'hffffff; // 24 LSBs of LBA (48-bit require different ATA command)
sysmem[(COMMAND_TABLE >> 2) + 3] = 1; // 1 logical sector (0 means 256)
......@@ -1053,11 +1075,12 @@ initial begin //Host
maxigp1_print (HBA_PORT__PxSSTS__DET__ADDR << 2,"HBA_PORT__PxSSTS__DET__ADDR");
// setup_pio_read_identify_command_simple(1); // prdt interrupt for entry 0
// setup_pio_read_identify_command_shifted(1); // prdt interrupt for entry 0
// setup_pio_read_identify_command_simple(512,1); // prdt interrupt for entry 0
setup_pio_read_identify_command_simple(2560,1); // intentionally too long
/// setup_pio_read_identify_command_shifted(1); // prdt interrupt for entry 0
/// setup_pio_read_identify_command_multi4(1,27,71,83); // prdt interrupt for entry 0
/// setup_pio_read_identify_command_multi4(1,27,64,83); // prdt interrupt for entry 0
setup_pio_read_identify_command_multi4(1,64,63,64); // prdt interrupt for entry 0
/// setup_pio_read_identify_command_multi4(1,64,63,64); // prdt interrupt for entry 0 // last used
maxigp1_print (HBA_PORT__PxCI__CI__ADDR << 2,"HBA_PORT__PxCI__CI__ADDR");
`ifdef TEST_ABORT_COMMAND
// Abort command by clearing ST
......@@ -1080,6 +1103,15 @@ initial begin //Host
maxigp1_writep (HBA_PORT__PxIS__PSS__ADDR << 2, HBA_PORT__PxIS__PSS__MASK); // clear PS interrupt
maxigp1_writep (GHC__IS__IPS__ADDR << 2, 1); // clear global interrupts
wait (~IRQ);
// Reset command with abort_dma
maxigp1_writep (HBA_PORT__PxCMD__FRE__ADDR << 2, HBA_PORT__PxCMD__FRE__MASK); // ST: 1 -> 0
repeat (50) @(posedge CLK);
maxigp1_writep (HBA_PORT__PxCMD__FRE__ADDR << 2, HBA_PORT__PxCMD__FRE__MASK |HBA_PORT__PxCMD__ST__MASK); // ST: 0 -> 1
// Print datascope - contents of the last CFIS sent
maxigp1_print ('h1000,"DATASCOPE 0"); //
maxigp1_print ('h1004,"DATASCOPE 1"); //
......@@ -1093,6 +1125,28 @@ initial begin //Host
// sysmem_print ('h1e81,'h180); // for shifted
sysmem_print ('h1e80,'h180); // Compact dump of "system memory" in hex word format
// Second time read identify:
// Prepare for D2H register FIS with interrupt bit set (expected to be sent after all data will be written to the device)
maxigp1_writep (HBA_PORT__PxIS__DHRS__ADDR << 2, HBA_PORT__PxIS__DHRS__MASK); // clear DHR (D2H register FIS with "I" bit) interrupt
maxigp1_writep (HBA_PORT__PxIE__PSE__ADDR << 2, HBA_PORT__PxIE__DHRE__MASK); // allow only D2H Register interrupts
maxigp1_writep (GHC__IS__IPS__ADDR << 2, 1); // clear global interrupts for port 0 (the only one)
wait (~IRQ);
setup_pio_read_identify_command_simple(512,1); // prdt interrupt for entry 0
maxigp1_print (HBA_PORT__PxCI__CI__ADDR << 2,"HBA_PORT__PxCI__CI__ADDR");
maxigp1_writep (HBA_PORT__PxIE__PSE__ADDR << 2, HBA_PORT__PxIE__PSE__MASK); // allow PS only interrupts (PIO setup)
maxigp1_writep (HBA_PORT__PxIS__PSS__ADDR << 2, HBA_PORT__PxIS__PSS__MASK); // clear that interrupt
wait (IRQ);
TESTBENCH_TITLE = "Got second Identify";
$display("[Testbench]: %s @%t", TESTBENCH_TITLE, $time);
maxigp1_print (HBA_PORT__PxIS__PSS__ADDR << 2,"HBA_PORT__PxIS__PSS__ADDR");
maxigp1_writep (HBA_PORT__PxIS__PSS__ADDR << 2, HBA_PORT__PxIS__PSS__MASK); // clear PS interrupt
maxigp1_writep (GHC__IS__IPS__ADDR << 2, 1); // clear global interrupts
wait (~IRQ);
// end of the second identify insertion
// Prepare for D2H register FIS with interrupt bit set (expected to be sent after all data will be written to the device)
maxigp1_writep (HBA_PORT__PxIS__DHRS__ADDR << 2, HBA_PORT__PxIS__DHRS__MASK); // clear DHR (D2H register FIS with "I" bit) interrupt
maxigp1_writep (HBA_PORT__PxIE__PSE__ADDR << 2, HBA_PORT__PxIE__DHRE__MASK); // allow only D2H Register interrupts
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment