Commit 87fd75fd authored by Andrey Filippov's avatar Andrey Filippov

fixed 2 more bugs in h2d/fifo control

parent 282f41b3
......@@ -393,7 +393,7 @@ localparam DATA_TYPE_ERR = 3;
if (reg_sdb[1]) sactive0 <= hba_data_in[0];
if (hba_rst || reg_sdb[0] || clear_xfer_cntr) xfer_cntr_r[31:2] <= 0;
if (hba_rst || reg_sdb[0] || clear_xfer_cntr) xfer_cntr_r[31:2] <= 0;
else if (reg_ps[4] || reg_ds[5]) xfer_cntr_r[31:2] <= {reg_ds[5]?hba_data_in[31:16]:16'b0,
hba_data_in[15:2]} + hba_data_in[1]; // round up
else if ((decr_dwcw || decr_dwcr) && !xfer_cntr_zero_r) xfer_cntr_r[31:2] <= {xfer_cntr_r[31:2]} -
......
......@@ -24,7 +24,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*/
`timescale 1ns/1ps
//`define CHECK_LOW_H2D_FIFO // reduce actual h2d fifo size during simulation, to test h2d_ready
/** TODO:
1. Check nothing is left in H2D FIFO after data is sent - it will happen after DPATp received.
2. Make DPATp an error? It is not easy to insert 0x00000046" data FIS header before remaining data (already in FIS)
- it may also hold fis_transmit, as maximal data fis is 4x of the FIFO size.
*/
module ahci_sata_layers #(
`ifdef USE_DATASCOPE
parameter ADDRESS_BITS = 10, //for datascope
......@@ -105,6 +110,9 @@ module ahci_sata_layers #(
output wire txn_out,
input wire rxp_in,
input wire rxn_in,
output debug_is_data, // @clk (sata clk) - last symbol was data output
output debug_dmatp, // @clk (sata clk) - received CODE_DMATP
`ifdef USE_DATASCOPE
// Datascope interface (write to memory that can be software-read)
output datascope_clk,
......@@ -142,6 +150,13 @@ module ahci_sata_layers #(
localparam H2D_TYPE_FIS_HEAD = 1;
localparam H2D_TYPE_FIS_LAST = 2;
`ifdef SIMULATION
`ifdef CHECK_LOW_H2D_FIFO
localparam H2D_FIFO_THRESHOLD = 4; // to test h2d_ready - will turn off frequently, much earlier than fifo almost full
`endif
`endif
wire phy_ready; // active when GTX gets aligned output
wire link_established; // Received 3 back-to-back non-ALIGNp
wire [31:0] ll_h2d_data_in;
......@@ -186,7 +201,9 @@ module ahci_sata_layers #(
wire [FIFO_ADDR_WIDTH:0] d2h_fill;
wire d2h_nempty;
wire h2d_fifo_rd = h2d_nempty && ll_strobe_out; // TODO: check latency in link.v
wire h2d_fifo_wr = h2d_valid;
// wire h2d_fifo_wr = h2d_valid;
//2016.12.10
wire h2d_fifo_wr = h2d_valid && h2d_ready; // or should valid depend on ready in the fis_transmit?
wire d2h_fifo_rd = d2h_valid && d2h_ready;
wire d2h_fifo_wr = ll_d2h_valid || fis_over_r; // fis_over_r will push FIS end to FIFO
......@@ -205,7 +222,18 @@ assign ll_h2d_last = (h2d_type_out == H2D_TYPE_FIS_LAST);
assign d2h_valid = d2h_nempty;
assign d2h_many = |d2h_fill[FIFO_ADDR_WIDTH:3]; //
assign h2d_ready = !h2d_fill[FIFO_ADDR_WIDTH] && !(&h2d_fill[FIFO_ADDR_WIDTH:3]);
// assign h2d_ready = !h2d_fill[FIFO_ADDR_WIDTH] && !(&h2d_fill[FIFO_ADDR_WIDTH:3]);
// 2016:12:10 sometimes overflow happened because of a BUG
`ifdef SIMULATION
`ifdef CHECK_LOW_H2D_FIFO
assign h2d_ready = !h2d_fill[FIFO_ADDR_WIDTH] && (h2d_fill < ((1 << BITS_TO_START_XMIT) + H2D_FIFO_THRESHOLD ));
`else
assign h2d_ready = !h2d_fill[FIFO_ADDR_WIDTH] && !(&h2d_fill[FIFO_ADDR_WIDTH-1:3]); // same as with synthesis
`endif
`else
assign h2d_ready = !h2d_fill[FIFO_ADDR_WIDTH] && !(&h2d_fill[FIFO_ADDR_WIDTH-1:3]);
`endif
assign ll_d2h_almost_full = d2h_fill[FIFO_ADDR_WIDTH] || &d2h_fill[FIFO_ADDR_WIDTH-1:6]; // 63 dwords (maybe use :5?) - time to tell device to stop
// assign ll_frame_req_w = !ll_frame_busy && h2d_pending && (((h2d_type == H2D_TYPE_FIS_LAST) && h2d_fifo_wr ) || (|h2d_fill[FIFO_ADDR_WIDTH : BITS_TO_START_XMIT]));
......@@ -317,7 +345,9 @@ assign debug_phy = debug_phy0;
.phy_err_in (ph2ll_err_out), // input[3:0] wire // disperr | notintable
// to phy
.phy_data_out (ll2ph_data_in), // output[31:0] wire
.phy_isk_out (ll2ph_charisk_in), // output[3:0] wire // charisk
.phy_isk_out (ll2ph_charisk_in), // output[3:0] wire // charisk
.debug_is_data (debug_is_data), // output reg @clk (sata clk) - last symbol was data output
.debug_dmatp (debug_dmatp), // output reg @clk (sata clk) - received CODE_DMATP
.debug_out (debug_link)
);
......
......@@ -190,6 +190,8 @@ module ahci_top#(
output irq, // CPU interrupt request
input debug_link_send_data, // @posedge sata_clk - last symbol was data output (to count sent out)
input debug_link_dmatp, // link received DMATp from device
`ifdef USE_DATASCOPE
// Datascope interface (write to memory that can be software-read)
......@@ -1204,6 +1206,7 @@ wire [9:0] xmit_dbg_01;
.soft_write_addr (soft_write_addr), // input[9:0]
.soft_write_data (soft_write_data), // input[31:0]
.soft_write_en (soft_write_en), // input
.cfis (fsnd_cfis_xmit), // input command FIS - to reset dword counter
.h2d_data (h2d_data), // input[31:0]
.h2d_type (h2d_type), // input[1:0]
.h2d_valid (h2d_valid), // input
......@@ -1212,6 +1215,8 @@ wire [9:0] xmit_dbg_01;
.d2h_type (d2h_type), // input[1:0]
.d2h_valid (d2h_valid), // input
.d2h_ready (d2h_ready), // input
.debug_link_send_data(debug_link_send_data), // input
.debug_link_dmatp (debug_link_dmatp), // link received DMATp from device
.datascope_clk (datascope_clk), // output
.datascope_waddr (datascope_waddr), // output[9:0] reg
.datascope_we (datascope_we), // output
......@@ -1327,6 +1332,8 @@ module datascope_timing #(
input [31:0] soft_write_data,
input soft_write_en,
input cfis, // to reset send counter
// outgoing FISes
input [31:0] h2d_data, // 32-bit data from the system memory to HBA (dma data)
input [ 1:0] h2d_type, // 0 - data, 1 - FIS head, 2 - FIS END (make FIS_Last?)
......@@ -1341,6 +1348,8 @@ module datascope_timing #(
input d2h_valid, // Data available from the transport layer in FIFO
input d2h_ready, // This module or DMA consumes DWORD
input debug_link_send_data, // @posedge mclk (sata_clk, 75MHz) - last symbol was data output (to count sent out)
input debug_link_dmatp, // link received DMATp from device
output datascope_clk,
output reg [ADDRESS_BITS-1:0] datascope_waddr,
output datascope_we,
......@@ -1360,6 +1369,9 @@ module datascope_timing #(
reg [31:0] fis_data;
reg [27:0] cur_time;
reg was_h2d_last;
reg h2d_ready_d; // delayed h2d_ready to count 1->0 transitions
reg [ 7:0] h2d_nready_cntr; // count (infrequent) events when h2d FIFO turns off ready
// reg
wire fis_start = (h2d_valid && h2d_ready && (h2d_type == 1)) ||
(d2h_valid && d2h_ready && (d2h_type == 1));
......@@ -1367,11 +1379,44 @@ module datascope_timing #(
// wire fis_end_we = (fis_left == 0) || fis_end;
wire pre_we_w = fis_run && (d2h_valid?(d2h_valid && d2h_ready):(h2d_valid && h2d_ready));
reg fis_run_d2;
reg fis_run_d3;
reg fis_run_d4; // to read non 0x39 d2h fis
reg fis_run_d5; // number of dwords sent by link a s data symbols
// reg fis_first;
reg data_fis;
reg pre_we_r;
reg we_r;
reg we_r;
wire inc_dw_cntr = fis_run && (d2h_valid?(d2h_ready && (d2h_type == 0)):(h2d_valid && h2d_ready));
wire is_cfis_w = h2d_valid && (h2d_data[ 7: 0] == 8'h27) && // valid @ fis_start
((h2d_data[23:16] == 8'h25) || // Read DMA Extended
(h2d_data[23:16] == 8'h35) || // Write DMA Extended
(h2d_data[23:16] == 8'hC8) || // Read DMA
(h2d_data[23:16] == 8'hCA)); // Write DMA
reg is_cfis_r;
reg [23:0] last_dma_cmd;
reg set_dma_count;
reg [21:0] dw_count;
wire [7:0] fis_data_w = d2h_valid ? d2h_data[7:0] : h2d_data[7:0];
reg [31:0] non_dma_act; // last D2H FIS that was not DMA activate, received after DMA/IO command
reg set_non_dma_act;
reg [21:0] link_count;
reg [21:0] link_count_latched;
reg reset_link_count; // data FIS from dma command until
reg was_link_dmatp; //
// input debug_link_dmatp, // link received DMATp from device
assign datascope_we = we_r;
assign datascope_clk = clk;
always @ (posedge clk) begin
was_h2d_last <= h2d_type[1] && h2d_valid && h2d_ready;
......@@ -1384,17 +1429,29 @@ module datascope_timing #(
else if (write_tag_w) pend_punch_time <= 1;
else if (write_punch_time) pend_punch_time <= 0;
if (write_punch_time || fis_start) datascope_di <= {write_punch_time?{1'b1,punch_tag}:{3'b0,d2h_valid},cur_time};
else if (fis_we) datascope_di <= fis_data;
else if (!fis_run && fis_run_d) datascope_di <= {19'h7fff8, fis_len};
if (write_punch_time || fis_start) datascope_di <= {write_punch_time?{1'b1,punch_tag}:{3'b0,d2h_valid},cur_time};
else if (fis_we) datascope_di <= fis_data;
else if (!fis_run && fis_run_d) datascope_di <= {19'h7fff8, fis_len};
else if (!fis_run_d && fis_run_d2) datascope_di <= {10'h2a8, dw_count};
else if (!fis_run_d2 && fis_run_d3) datascope_di <= {8'h55, last_dma_cmd};
else if (!fis_run_d3 && fis_run_d4) datascope_di <= non_dma_act;
else if (!fis_run_d4 && fis_run_d5) datascope_di <= {h2d_nready_cntr[7:0], was_link_dmatp, 1'b0, link_count_latched};
pre_we_r <= pre_we_w || fis_start ;
we_r <= write_punch_time || fis_start || (fis_we ? pre_we_r : (!fis_run && fis_run_d));
// we_r <= write_punch_time || fis_start || (fis_we ? pre_we_r : (!fis_run && fis_run_d));
we_r <= write_punch_time || fis_start || (fis_we ? pre_we_r : (!fis_run && (fis_run_d || fis_run_d2 || fis_run_d3 || fis_run_d4 || fis_run_d5))); // 3 after
if (fis_start) fis_left <= FIS_LEN - 1;
else if (pre_we_w) fis_left <= fis_left - 1;
// if (fis_start) fis_first <= 1;
// else if (pre_we_w) fis_first <= 0;
if (fis_end) data_fis <= 0;
// else if (pre_we_w && fis_start) data_fis <= fis_data_w == 8'h46;
else if (fis_start) data_fis <= fis_data_w == 8'h46;
if (rst) fis_we <= 0;
else if (fis_start) fis_we <= 1;
else if ((fis_left == 0) || fis_end) fis_we <= 0;
......@@ -1403,7 +1460,46 @@ module datascope_timing #(
else if (fis_start) fis_run <= 1;
else if (fis_end) fis_run <= 0;
fis_run_d <= fis_run;
fis_run_d <= fis_run;
fis_run_d2 <= fis_run_d;
fis_run_d3 <= fis_run_d2;
fis_run_d4 <= fis_run_d3;
fis_run_d5 <= fis_run_d4;
if (cfis) dw_count <= 0;
else if (inc_dw_cntr && data_fis) dw_count <= dw_count + 1;
if (rst) reset_link_count <= 0;
else if (cfis) reset_link_count <= 1;
else if (fis_start && (fis_data_w == 8'h46)) reset_link_count <= 0;
if (reset_link_count) link_count <= 0;
else if (debug_link_send_data) link_count <= link_count + 1; // will only be valid later, latch at next fis start
if (fis_start) link_count_latched <= link_count;
if (reset_link_count) was_link_dmatp <= 0;
else if (debug_link_dmatp) was_link_dmatp <= 1;
h2d_ready_d <= h2d_ready;
if (rst) h2d_nready_cntr <= 0;
else if (!h2d_ready && h2d_ready_d) h2d_nready_cntr <= h2d_nready_cntr+1;
if (fis_start) is_cfis_r <= is_cfis_w;
if (fis_start && is_cfis_w) last_dma_cmd[23:16] <= h2d_data[23:16]; // command code
set_dma_count <= (fis_len == 3) && h2d_valid && h2d_ready && is_cfis_r;
if (set_dma_count) last_dma_cmd[15:0] <= fis_data[15:0];
set_non_dma_act <= fis_start && d2h_valid && (fis_data_w != 8'h39);
if (set_dma_count) non_dma_act <= 32'h33333333;
else if (set_non_dma_act) non_dma_act <= fis_data;
if (fis_start) fis_len <= d2h_valid? 0 : 1;
else if (pre_we_w) fis_len <= fis_len + 1;
......
......@@ -239,6 +239,8 @@
reg [2:0] nhrst_r;
wire hrst = !nhrst_r[2];
wire debug_link_send_data; // @sata clk - last symbol was data output
wire debug_link_dmatp; // @clk (sata clk) - received CODE_DMATP
wire [FREQ_METER_WIDTH-1:0] xclk_period;
`ifdef USE_DATASCOPE
......@@ -403,7 +405,8 @@
.sctl_ipm (sctl_ipm), // output[3:0]
.sctl_spd (sctl_spd), // output[3:0]
.irq (irq), // output
.debug_link_send_data (debug_link_send_data), // input @posedge sata_clk - last symbol was data output (to count sent out)
.debug_link_dmatp (debug_link_dmatp), // link received DMATp from device
`ifdef USE_DATASCOPE
.datascope1_clk (datascope_clk), // input
.datascope1_waddr (datascope_waddr), // input[9:0]
......@@ -489,6 +492,10 @@
.txn_out (TXN), // output wire
.rxp_in (RXP), // input wire
.rxn_in (RXN), // input wire
.debug_is_data (debug_link_send_data), //output @clk (sata clk) - last symbol was data output
.debug_dmatp (debug_link_dmatp), // @clk (sata clk) - received CODE_DMATP
`ifdef USE_DATASCOPE
.datascope_clk (datascope_clk), // output
.datascope_waddr (datascope_waddr), // output[9:0]
......
......@@ -47,7 +47,8 @@ module sata_device(
// reg [31:0] DEV_DATA;
integer DEV_DATA;
//`endif
//`define TERMINATE_DMA_H2D
//`undef TERMINATE_DMA_H2D
wire phy_ready;
wire [31:0] phy2dev_data;
......@@ -569,6 +570,10 @@ task linkMonitorFIS;
cnt = cnt + 1;
if (cnt <= 2048)
pause = pause + receive_data_pause[cnt];
`ifdef TERMINATE_DMA_H2D
linkSendPrim("DMAT");
`endif
end
end
@ (posedge clk)
......
......@@ -99,6 +99,8 @@ module link #(
// to phy
output wire [DATA_BYTE_WIDTH*8 - 1:0] phy_data_out,
output wire [DATA_BYTE_WIDTH - 1:0] phy_isk_out, // charisk
output reg debug_is_data, // @clk (sata clk) - last symbol was data output
output reg debug_dmatp, // @clk (sata clk) - received CODE_DMATP
// debug
output [31:0] debug_out //
);
......@@ -580,6 +582,10 @@ begin
end
endgenerate
always @ (posedge clk) begin
debug_dmatp <= rcvd_dword[CODE_DMATP];
end
// select which primitive shall be sent
wire [PRIM_NUM - 1:0] select_prim;
assign select_prim[CODE_SYNCP] = ~alignes_pair & (state_idle | state_sync_esc | state_rcvr_wait | state_reset);
......@@ -618,6 +624,10 @@ always @ (posedge clk)
{DATA_BYTE_WIDTH*8{select_prim[CODE_CRC]}} & prim_data[CODE_CRC] |
{DATA_BYTE_WIDTH*8{select_prim[CODE_DATA]}} & prim_data[CODE_DATA];
always @ (posedge clk)
debug_is_data <= select_prim[CODE_DATA];
always @ (posedge clk)
to_phy_isk <= rst | ~select_prim[CODE_DATA] & ~select_prim[CODE_CRC] ? {{(DATA_BYTE_WIDTH - 1){1'b0}}, 1'b1} : {DATA_BYTE_WIDTH{1'b0}} ;
......
......@@ -2,6 +2,6 @@
, .INIT_08 (256'h000000000024000600000000000000000000000080000C000000000080000800)
, .INIT_09 (256'h000000000000000000000000000000000000000000000000FFFFFFFF00000000)
, .INIT_0B (256'h0000000000000000000000000000003300000000000000000000000000000000)
, .INIT_0C (256'h00000000000000000000000000000000000000000101000B001000000001FFFE)
, .INIT_0C (256'h000000000000000000000000000000000000000001010011001000000001FFFE)
, .INIT_0D (256'h000001000000000000000040000000000001FFFE000000008000000000000000)
, .INIT_0E (256'h0000000000000000000000000000000000000000000000000000000040000001)
......@@ -97,7 +97,7 @@
// RO: HBA Revision ID
localparam PCI_Header__RID__RID__ADDR = 'h62;
localparam PCI_Header__RID__RID__MASK = 'hff;
localparam PCI_Header__RID__RID__DFLT = 'hb;
localparam PCI_Header__RID__RID__DFLT = 'h11;
// RO: Base Class Code: 1 - Mass Storage Device
localparam PCI_Header__CC__BCC__ADDR = 'h62;
localparam PCI_Header__CC__BCC__MASK = 'hff000000;
......
......@@ -31,7 +31,7 @@ __status__ = "Development"
"""
**** Modify next value for new file versions, re-run this file *****
"""
RID = 0x0b # Revision ID
RID = 0x011 # Revision ID
VID = 0xfffe # What to use for non-PCI "vendorID"?
DID = 0x0001
SSVID = 0xfffe
......
......@@ -1497,6 +1497,17 @@ if __name__ == "__main__":
"""
camogm_test -d /dev/sda2 -b 4194304 -c 30000
dd if=/dev/sda skip=257142656 count=1 | hexdump -e '"%08_ax: "' -e ' 16/4 "%08x " "\n"'
cat /sys/devices/soc0/amba@0/80000000.elphel-ahci/lba_current
cat /sys/devices/soc0/amba@0/80000000.elphel-ahci/lba_start
camogm_test -d /dev/sda2 -b 4194304 -c 10000
x393sata.py
modprobe ahci_elphel &
sleep 2
......@@ -1520,7 +1531,8 @@ import x393_mem
mem = x393_mem.X393Mem(1,0,1)
sata = x393sata.x393sata()
hex(mem.read_mem(sata.get_reg_address('PCI_Header__RID')))
hex([((mem.read_mem(0x80000ffc) >> 10) & 0xffc) + 0x80001000,mem.mem_dump (0x80001000, 0x400,4),sata.reg_status()][0])
sata.setup_pio_read_identify_command()
sata.dd_read_dma_ext(142615470, 512, 512)
......
......@@ -1120,6 +1120,9 @@ localparam ATA_RDMA_EXT = 'h25; // Read DMA devices that support 48-bit Addressi
(ATA_RDMA_EXT << 16) | // Command = 0x25 (READ_DMA_EXT)
( 0 << 24); // features = 0 ?
// All other 4 DWORDs are 0 for this command
sysmem[(COMMAND_TABLE >> 2) + 3] = 1; // count
// Set PRDT (four items)
// PRDT #1
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 0] = SYS_MEM_START + IDENTIFY_BUF; // not shifted
......@@ -1178,6 +1181,7 @@ localparam ATA_RDMA_EXT = 'h25; // Read DMA devices that support 48-bit Addressi
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)
// All other DWORDs are 0 for this command
sysmem[(COMMAND_TABLE >> 2) + 3] = 1; // count
// Set PRDT (four items)
// PRDT #1
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 0] = SYS_MEM_START + IDENTIFY_BUF; // not shifted
......@@ -1227,6 +1231,7 @@ localparam ATA_RDMA_EXT = 'h25; // Read DMA devices that support 48-bit Addressi
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)
// All other DWORDs are 0 for this command
sysmem[(COMMAND_TABLE >> 2) + 3] = 1; // count
// Set PRDT (four items)
// PRDT #1
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 0] = SYS_MEM_START + IDENTIFY_BUF; // not shifted
......
This diff is collapsed.
No preview for this file type
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