Commit 354a7663 authored by Andrey Filippov's avatar Andrey Filippov

started debugging dma write

parent b01dd1bb
......@@ -76,6 +76,8 @@ module ahci_dma (
output sys_dav, // at least one dword is ready to be read
// output sys_dav_many, // several DWORDs are in the FIFO (TODO: decide how many)
input sys_re, // sys_out data read, advance internal FIFO
output last_h2d_data,// when active and no new data for 2 clocks - that was the last one
// Data HBA -> System memory interface @ mclk
input [31:0] sys_in, // HBA -> system memory
output sys_nfull, // internal FIFO has room for more data (will decide - how big reserved space to keep)
......@@ -494,7 +496,8 @@ module ahci_dma (
.done_flush (done_flush), // output // @ hclk
.dout (sys_out), // output[31:0]
.dout_vld (sys_dav), // output
.dout_re (sys_re) // input
.dout_re (sys_re), // input
.last_data (last_h2d_data) // output
);
ahci_dma_wr_fifo #( // device to memory
......
......@@ -59,7 +59,8 @@ module ahci_dma_rd_fifo#(
// mclk domain
output [31:0] dout,
output dout_vld,
input dout_re
input dout_re,
output last_data // pulse @mclk (input done for the last prd - slow send out FIS, no data for 2 clocks - that was the last
);
localparam ADDRESS_NUM = (1<<ADDRESS_BITS); // 8 for ADDRESS_BITS==3
reg [ADDRESS_BITS : 0] waddr; // 1 extra bit
......@@ -100,7 +101,6 @@ module ahci_dma_rd_fifo#(
reg flush_r;
wire done_flush_mclk;
assign din_re = busy && fifo_half_hclk && din_av_safe_r;
assign fifo_wr = en_fifo_wr && fifo_half_hclk && (din_av_safe_r || !busy);
assign fifo_di_vld = (busy && (!extra_in || (qwcntr != 0)))? 4'hf : last_mask ;
......@@ -182,9 +182,20 @@ module ahci_dma_rd_fifo#(
.rst (mrst), // input
.src_clk (mclk), // input
.dst_clk (hclk), // input
.in_pulse (done_flush_mclk), // input
.in_pulse (flush_r && din_re && (qwcntr == 0)), // input
.out_pulse (done_flush), // output
.busy() // output
);
pulse_cross_clock #(
.EXTRA_DLY(0)
) last_data_i (
.rst (mrst), // input
.src_clk (mclk), // input
.dst_clk (hclk), // input
.in_pulse (done_flush_mclk), // input
.out_pulse (last_data), // output
.busy() // output
);
endmodule
......@@ -69,7 +69,8 @@ module ahci_fis_receive#(
input set_sts_80, // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update
input clear_xfer_cntr, // clear pXferCntr (is it needed as a separate input)?
input decr_dwc, // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers
input decr_dwcr, // decrement DMA Xfer counter after read (in this module) // need pulse to 'update_prdbc' to write to registers
input decr_dwcw, // decrement DMA Xfer counter after write (from decr_DXC_dw)// need pulse to 'update_prdbc' to write to registers
input [11:0] decr_DXC_dw, // decrement value (in DWORDs)
input pcmd_fre, // control bit enables saving FIS to memory (will be ignored for signature)
......@@ -89,7 +90,7 @@ module ahci_fis_receive#(
output reg sactive0, // bit 0 of sActive DWORD received in SDB FIS
// Using even word count (will be rounded up), partial DWORD (last) will be handled by PRD length if needed
output [31:2] xfer_cntr, // transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc
output reg xfer_cntr_zero,// valid next cycle
output xfer_cntr_zero,// valid next cycle
output [11:0] data_in_dwords, // number of data dwords received (valid with 'done')
// FSM will send this pulse
// output reg data_in_words_apply, // apply data_in_words
......@@ -147,7 +148,7 @@ localparam DATA_TYPE_OK = 2;
localparam DATA_TYPE_ERR = 3;
reg xfer_cntr_zero_r;
wire dma_in_start;
wire dma_in_stop;
wire dma_skipping_extra; // skipping extra FIS data not needed for DMA
......@@ -166,6 +167,7 @@ localparam DATA_TYPE_ERR = 3;
reg fis_rec_run; // running received FIS
reg is_data_fis;
reg is_ignore;
wire is_FIS_HEAD = data_in_ready && (hba_data_in_type == DATA_TYPE_FIS_HEAD);
wire is_FIS_NOT_HEAD = data_in_ready && (hba_data_in_type != DATA_TYPE_FIS_HEAD);
......@@ -206,6 +208,8 @@ localparam DATA_TYPE_ERR = 3;
reg fis_first_invalid_r;
reg fis_first_flushing_r;
assign xfer_cntr_zero = xfer_cntr_zero_r;
// Forward data to DMA (dev->mem) engine
assign dma_in_valid = dma_in && dma_in_ready && (hba_data_in_type == DATA_TYPE_DMA) && data_in_ready && !too_long_err;
// Will also try to skip to the end of too long FIS
......@@ -278,6 +282,7 @@ localparam DATA_TYPE_ERR = 3;
reg_ps <= get_psfis ? 1 : 0;
reg_d2h <= get_rfis ? 1 : 0;
reg_sdb <= get_rfis ? 1 : 0;
is_ignore <= get_ignore ? 1 : 0;
end else if (wreg_we_r && !dwords_over) begin
fis_dcount <= fis_dcount - 1; // update even if not writing to registers
if (fis_save) reg_addr_r <= reg_addr_r + 1; // update only when writing to registers
......@@ -295,9 +300,11 @@ localparam DATA_TYPE_ERR = 3;
if (hba_rst ||get_fis) dwords_over <= 0;
else if (wreg_we_r && !(|fis_dcount)) dwords_over <= 1;
/// else if (wreg_we_r && (!(|fis_dcount) || is_fis_end)) dwords_over <= 1;
if (hba_rst) wreg_we_r <= 0;
else wreg_we_r <= fis_rec_run && data_in_ready && !is_fis_end && !dwords_over && (|fis_dcount || !wreg_we_r);
else wreg_we_r <= fis_rec_run && data_in_ready && !is_fis_end && !dwords_over && (|fis_dcount || !wreg_we_r) &&
(!is_ignore || !wreg_we_r); // Ignore - unknown length, ned to look for is_fis_end with latency
fis_end_r <= {fis_end_r[0], fis_end_w};
......@@ -363,13 +370,15 @@ 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;
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_dwc) xfer_cntr_r[31:2] <= {xfer_cntr_r[31:2]} - {18'b0, decr_DXC_dw[11: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]} -
{18'b0, decr_dwcr? data_in_dwords: decr_DXC_dw[11:0]};
if (hba_rst || reg_sdb[0] || reg_ps[4] || reg_ds[5]) prdbc_r[31:2] <= 0;
else if (decr_dwc) prdbc_r[31:2] <= {prdbc_r[31:2]} + {18'b0, decr_DXC_dw[11:0]};
else if (decr_dwcw || decr_dwcr) prdbc_r[31:2] <= {prdbc_r[31:2]} + {18'b0, decr_dwcr? data_in_dwords: decr_DXC_dw[11:0]};
xfer_cntr_zero <= xfer_cntr_r[31:2] == 0;
xfer_cntr_zero_r <= xfer_cntr_r[31:2] == 0;
update_err_sts_r <= update_pio || update_err_sts || clear_bsy_drq || set_bsy || set_sts_7f || set_sts_80;
// update_pio_r <= update_pio;
......
......@@ -72,6 +72,7 @@ module ahci_fis_transmit #(
// ahci_fis_receive interface
input [31:2] xfer_cntr, // transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc
input xfer_cntr_zero, // transfer counter was not set
output dma_ctba_ld, // load command table address from
......@@ -91,6 +92,7 @@ module ahci_fis_transmit #(
input [31:0] dma_out, // 32-bit data from the DMA module, HBA -> device port
input dma_dav, // at least one dword is ready to be read from DMA module
output dma_re, // read dword from DMA module to the output register
input last_h2d_data,// single pulse, after it watch for FIS end (no data for 2 clocks)
// Data System memory or FIS -> device
output reg [31:0] todev_data, // 32-bit data from the system memory to HBA (dma data)
......@@ -108,7 +110,7 @@ module ahci_fis_transmit #(
wire [1:0] fis_data_type;
wire [31:0] fis_data_out;
wire write_or_w = (dma_en_r?(dma_dav && todev_ready):fis_data_valid); // do not fill the buffer if FIFO is not ready for DMA,
wire write_or_w;
// for fis_data_valid - longer latency
// wire fis_out_w = !dma_en_r && fis_data_valid && todev_ready;
wire dma_re_w = dma_en_r && dma_dav && todev_ready;
......@@ -154,7 +156,7 @@ module ahci_fis_transmit #(
reg fis_dw_first;
wire fis_dw_last;
reg [11:2] dx_dwords_left;
reg [11:0] dx_dwords_left;
reg dx_fis_pend_r; // waiting to send first DWORD of the H2D data transfer
wire dx_dma_last_w; // sending last adat word
reg dx_busy_r;
......@@ -166,9 +168,16 @@ module ahci_fis_transmit #(
wire done_w = xmit_ok_r || ((|dx_err_r) && dx_busy_r) || dma_start; // done on last transmit or error
reg fetch_cmd_busy_r;
assign todev_valid = todev_full_r;
reg xfer_cntr_not_set;
reg watch_prd_end;
wire masked_last_h2d_data = xfer_cntr_not_set && last_h2d_data; // otherwise use xfer counter to find FIS end
wire watch_prd_end_w = masked_last_h2d_data || watch_prd_end; // Maybe not needed - just use watch_prd_end
// reg [1:0] was_dma_re; // previous values of dma_re
reg [2:0] was_dma_ndav; // inverted/masked previous values of dma_dav
wire send_last_w = was_dma_ndav[2];
// assign todev_valid = todev_full_r;
assign todev_valid = todev_full_r && (!watch_prd_end_w || dma_dav || send_last_w);
assign dma_re = dma_re_w;
assign reg_re = reg_re_r[1:0];
......@@ -193,10 +202,13 @@ module ahci_fis_transmit #(
assign fis_data_type = {fis_dw_last, (write_or_w && dx_fis_pend_r) | (fis_dw_first && ct_stb)};
assign fis_data_out = ({32{dx_fis_pend_r}} & DATA_FIS) | ({32{ct_stb}} & ct_data) ;
assign dx_dma_last_w = dma_en_r && dma_re_w && (dx_dwords_left[11:2] == 1);
assign dx_dma_last_w = dma_en_r && dma_re_w && (dx_dwords_left[11:0] == 1);
assign dx_err = dx_err_r;
assign dma_dev_wr = ch_w_r;
/// assign write_or_w = (dma_en_r?(dma_dav && todev_ready && ()):fis_data_valid); // do not fill the buffer if FIFO is not ready for DMA,
assign write_or_w = (dma_en_r?(dma_dav && todev_ready && (!todev_full_r || watch_prd_end_w)):fis_data_valid); // do not fill the buffer if FIFO is not ready for DMA,
// When watching for FIS end, do not fill/use output register in the same cycle
always @ (posedge mclk) begin
// Mutliplex between DMA and FIS output to the output routed to transmit FIFO
......@@ -209,7 +221,13 @@ module ahci_fis_transmit #(
if (hba_rst) todev_type <= 3; // invalid? - no, now first and last word in command FIS (impossible?)
else if (write_or_w) todev_type <= dma_en_r? {dx_dma_last_w, 1'b0} : fis_data_type;
else if (was_dma_ndav[1]) todev_type <= {1'b1, 1'b0}; // type = last in FIS
if (hba_rst) was_dma_ndav <= 0;
else was_dma_ndav <= {was_dma_ndav[1:0], ~dma_dav & todev_full_r & watch_prd_end_w} ;
if (hba_rst || dx_xmit || done_w) watch_prd_end <= 0;
else if (masked_last_h2d_data) watch_prd_end <= 1;
// Read 3 DWORDs from the command header
if (hba_rst) fetch_chead_r <= 0; // running 1
......@@ -291,8 +309,10 @@ module ahci_fis_transmit #(
//TODO: update xfer length, prdtl (only after R_OK) - yes, do it outside
if (dx_xmit) dx_dwords_left[11:2] <= (|xfer_cntr[31:11])?10'h200:{1'b0,xfer_cntr[10:2]};
else if (dma_re_w) dx_dwords_left[11:2] <= dx_dwords_left[11:2] - 1;
if (dx_xmit) xfer_cntr_not_set <= xfer_cntr_zero; // if it was zero - rely on PRDs
if (dx_xmit) dx_dwords_left[11:0] <= (xfer_cntr_zero || (|xfer_cntr[31:13])) ? 12'h800 : {1'b0,xfer_cntr[12:2]};
else if (dma_re_w) dx_dwords_left[11:0] <= dx_dwords_left[11:0] - 1;
if (dx_xmit) dwords_sent <= 0;
else if (dma_re_w) dwords_sent <= dwords_sent + 1;
......
......@@ -141,7 +141,7 @@ module ahci_fsm
/// input dma_prd_done, // output (finished next prd)
output dma_prd_irq_clear, // reset pending prd_irq
input dma_prd_irq_pend, // prd interrupt pending. This is just a condition for irq - actual will be generated after FIS OK
/// input dma_cmd_busy, // output reg (DMA engine is processing PRDs)
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
......@@ -189,7 +189,8 @@ module ahci_fsm
output set_sts_80, // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update
output clear_xfer_cntr, // clear pXferCntr (is it needed as a separate input)?
output decr_dwc, // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers
output decr_dwcr, // decrement DMA Xfer counter after read // need pulse to 'update_prdbc' to write to registers
output decr_dwcw, // decrement DMA Xfer counter after write // need pulse to 'update_prdbc' to write to registers
// output [11:0] decr_DXC_dw, // decrement value (in DWORDs)
input pxcmd_fre, // control bit enables saving FIS to memory
input pPioXfer, // state variable
......@@ -422,7 +423,8 @@ module ahci_fsm
.SET_STS_7F (set_sts_7f), // output reg
.SET_STS_80 (set_sts_80), // output reg
.XFER_CNTR_CLEAR (clear_xfer_cntr), // output reg
.DECR_DWC (decr_dwc), // output reg
.DECR_DWCR (decr_dwcr), // output reg
.DECR_DWCW (decr_dwcw), // output reg
.FIS_FIRST_FLUSH (fis_first_flush), // output reg
// FIS_TRANSMIT
.CLEAR_CMD_TO_ISSUE (clearCmdToIssue), // output reg
......@@ -492,8 +494,8 @@ module ahci_fsm
.PIO_I (pio_i), // input
.NPD (!pio_d), // input pio_d = 0 , "ch_a == 1" is not needed
.PIOX (pPioXfer), // input
.XFER0 (xfer_cntr_zero), // input xfer_cntr_zero
.PIOX_XFER0 (pPioXfer && xfer_cntr_zero), // input pPioXfer && xfer_cntr_zero
.XFER0 (xfer_cntr_zero && !dma_cmd_busy), // input xfer_cntr_zero
.PIOX_XFER0 (pPioXfer && xfer_cntr_zero &&!dma_cmd_busy), // input pPioXfer && xfer_cntr_zero
// FIS_TRANSMIT
.CTBAA_CTBAP (ch_a && ch_p), // input
.CTBAP (ch_p), // input
......
......@@ -252,11 +252,13 @@ module ahci_top#(
/// wire dma_prd_done; // output (finished next prd)
wire dma_prd_irq_clear; // reset pending prd_irq
wire dma_prd_irq_pend; // prd interrupt pending. This is just a condition for irq - actual will be generated after FIS OK
/// wire dma_cmd_busy; // output reg (DMA engine is processing PRDs)
wire dma_cmd_busy; // output reg (DMA engine is processing PRDs)
wire dma_cmd_done; // output (last PRD is over)
wire [31:0] dma_dout; // output[31:0]
wire dma_dav; // output
wire dma_re; // input
wire last_h2d_data;// when active and no new data for 2 clocks - that was the last one
wire dma_in_ready; // output
wire dma_we; // input
wire dma_extra_din; // all DRDs are transferred to memory, but FIFO has some data. Valid when transfer is stopped
......@@ -289,7 +291,8 @@ module ahci_top#(
wire frcv_set_bsy; // set PxTFD.STS.BSY, update
wire frcv_set_sts_7f; // set PxTFD.STS = 0x7f, update
wire frcv_set_sts_80; // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update
wire frcv_decr_dwc; // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers
wire frcv_decr_dwcr; // decrement DMA Xfer counter after read // need pulse to 'update_prdbc' to write to registers
wire frcv_decr_dwcw; // decrement DMA Xfer counter after write // need pulse to 'update_prdbc' to write to registers
wire frcv_clear_xfer_cntr; // Clear pXferCntr to 0
// fsm <-
......@@ -543,7 +546,7 @@ module ahci_top#(
.dma_prd_irq_clear (dma_prd_irq_clear), // output
.dma_prd_irq_pend (dma_prd_irq_pend), // input
/// .dma_cmd_busy (dma_cmd_busy), // input
.dma_cmd_busy (dma_cmd_busy), // input
/// .dma_cmd_done (dma_cmd_done), // input
.dma_cmd_abort (dma_cmd_abort_fsm), // output
......@@ -582,7 +585,8 @@ module ahci_top#(
.set_sts_7f (frcv_set_sts_7f), // output
.set_sts_80 (frcv_set_sts_80), // output
.clear_xfer_cntr (frcv_clear_xfer_cntr), //output Clear pXferCntr
.decr_dwc (frcv_decr_dwc), // output increment pXferCntr after transmit by data transmitted)
.decr_dwcr (frcv_decr_dwcr), // output increment pXferCntr after transmit by data transmitted)
.decr_dwcw (frcv_decr_dwcw), // output increment pXferCntr after transmit by data transmitted)
// .decr_DXC_dw (data_out_dwords), // output[11:2] **** Probably not needed
.pxcmd_fre (pcmd_fre), // input
......@@ -799,11 +803,12 @@ module ahci_top#(
.prd_irq_clear (dma_prd_irq_clear),// input
.prd_irq_pend (dma_prd_irq_pend), // output reg
.cmd_busy (), // dma_cmd_busy), // output reg
.cmd_busy (dma_cmd_busy), // dma_cmd_busy), // output reg Some data to transmit!
.cmd_done (dma_cmd_done), // output
.sys_out (dma_dout), // output[31:0]
.sys_dav (dma_dav), // output
.sys_re (dma_re), // input
.last_h2d_data (last_h2d_data), // output
.sys_in (d2h_data), // input[31:0]
.sys_nfull (dma_in_ready), // output
.sys_we (dma_we), // input
......@@ -897,7 +902,8 @@ module ahci_top#(
.set_sts_7f (frcv_set_sts_7f), // input
.set_sts_80 (frcv_set_sts_80), // input
.clear_xfer_cntr (frcv_clear_xfer_cntr), // input Clear pXferCntr
.decr_dwc (frcv_decr_dwc), // input
.decr_dwcr (frcv_decr_dwcr), // input
.decr_dwcw (frcv_decr_dwcw), // input
.decr_DXC_dw (data_out_dwords), // input[11:2]
.pcmd_fre (pcmd_fre), // input
......@@ -967,6 +973,7 @@ module ahci_top#(
.reg_re (regs_re_ftransmit), // output[1:0]
.reg_rdata (regs_dout), // input[31:0]
.xfer_cntr (xfer_cntr[31:2]), // input[31:2]
.xfer_cntr_zero (xfer_cntr_zero), // input
.dma_ctba_ld (ctba_ld), // output
.dma_start (dma_cmd_start), // output
.dma_dev_wr (dev_wr), // output
......@@ -979,6 +986,7 @@ module ahci_top#(
.dma_out (dma_dout), // input[31:0]
.dma_dav (dma_dav), // input
.dma_re (dma_re), // output
.last_h2d_data (last_h2d_data), // input
.todev_data (h2d_data), // output[31:0] reg
.todev_type (h2d_type), // output[1:0] reg
.todev_valid (h2d_valid), // output
......
......@@ -704,6 +704,17 @@ task send_pio_setup; // @SuppressThisWarning VEditor - Used in testbench
end
endtask
task send_dma_activate; // @SuppressThisWarning VEditor - Used in testbench
input integer id;
output integer status;
begin
transmit_data[0] = FIS_DMAA;
linkTransmitFIS(id, 1, 0, status);
end
endtask
task send_identify_data; // @SuppressThisWarning VEditor - Used in testbench
input integer id;
......
/*******************************************************************************
* Module: action_decoder
* Date:2016-01-25
* Date:2016-01-27
* Author: auto-generated file, see ahci_fsm_sequence.py
* Description: Decode sequencer code to 1-hot actions
*******************************************************************************/
......@@ -39,7 +39,8 @@ module action_decoder (
output reg SET_STS_7F,
output reg SET_STS_80,
output reg XFER_CNTR_CLEAR,
output reg DECR_DWC,
output reg DECR_DWCR,
output reg DECR_DWCW,
output reg FIS_FIRST_FLUSH,
output reg CLEAR_CMD_TO_ISSUE,
output reg DMA_ABORT,
......@@ -90,26 +91,27 @@ module action_decoder (
SET_STS_7F <= enable && data[ 9] && data[ 2];
SET_STS_80 <= enable && data[10] && data[ 2];
XFER_CNTR_CLEAR <= enable && data[ 4] && data[ 3];
DECR_DWC <= enable && data[ 5] && data[ 3];
FIS_FIRST_FLUSH <= enable && data[ 6] && data[ 3];
CLEAR_CMD_TO_ISSUE <= enable && data[ 7] && data[ 3];
DMA_ABORT <= enable && data[ 8] && data[ 3];
DMA_PRD_IRQ_CLEAR <= enable && data[ 9] && data[ 3];
XMIT_COMRESET <= enable && data[10] && data[ 3];
SEND_SYNC_ESC <= enable && data[ 5] && data[ 4];
SET_OFFLINE <= enable && data[ 6] && data[ 4];
R_OK <= enable && data[ 7] && data[ 4];
R_ERR <= enable && data[ 8] && data[ 4];
FETCH_CMD <= enable && data[ 9] && data[ 4];
ATAPI_XMIT <= enable && data[10] && data[ 4];
CFIS_XMIT <= enable && data[ 6] && data[ 5];
DX_XMIT <= enable && data[ 7] && data[ 5];
GET_DATA_FIS <= enable && data[ 8] && data[ 5];
GET_DSFIS <= enable && data[ 9] && data[ 5];
GET_IGNORE <= enable && data[10] && data[ 5];
GET_PSFIS <= enable && data[ 7] && data[ 6];
GET_RFIS <= enable && data[ 8] && data[ 6];
GET_SDBFIS <= enable && data[ 9] && data[ 6];
GET_UFIS <= enable && data[10] && data[ 6];
DECR_DWCR <= enable && data[ 5] && data[ 3];
DECR_DWCW <= enable && data[ 6] && data[ 3];
FIS_FIRST_FLUSH <= enable && data[ 7] && data[ 3];
CLEAR_CMD_TO_ISSUE <= enable && data[ 8] && data[ 3];
DMA_ABORT <= enable && data[ 9] && data[ 3];
DMA_PRD_IRQ_CLEAR <= enable && data[10] && data[ 3];
XMIT_COMRESET <= enable && data[ 5] && data[ 4];
SEND_SYNC_ESC <= enable && data[ 6] && data[ 4];
SET_OFFLINE <= enable && data[ 7] && data[ 4];
R_OK <= enable && data[ 8] && data[ 4];
R_ERR <= enable && data[ 9] && data[ 4];
FETCH_CMD <= enable && data[10] && data[ 4];
ATAPI_XMIT <= enable && data[ 6] && data[ 5];
CFIS_XMIT <= enable && data[ 7] && data[ 5];
DX_XMIT <= enable && data[ 8] && data[ 5];
GET_DATA_FIS <= enable && data[ 9] && data[ 5];
GET_DSFIS <= enable && data[10] && data[ 5];
GET_IGNORE <= enable && data[ 7] && data[ 6];
GET_PSFIS <= enable && data[ 8] && data[ 6];
GET_RFIS <= enable && data[ 9] && data[ 6];
GET_SDBFIS <= enable && data[10] && data[ 6];
GET_UFIS <= enable && data[ 8] && data[ 7];
end
endmodule
/*******************************************************************************
* Module: condition_mux
* Date:2016-01-25
* Date:2016-01-27
* Author: auto-generated file, see ahci_fsm_sequence.py
* Description: Select condition
*******************************************************************************/
......
......@@ -49,7 +49,7 @@ actions = ['NOP',
'PFSM_STARTED', 'PCMD_CR_CLEAR', 'PCMD_CR_SET', 'PXCI0_CLEAR', 'PXSSTS_DET_1', 'SSTS_DET_OFFLINE', 'SCTL_DET_CLEAR',
# FIS RECEIVE
'SET_UPDATE_SIG', 'UPDATE_SIG', 'UPDATE_ERR_STS', 'UPDATE_PIO', 'UPDATE_PRDBC', 'CLEAR_BSY_DRQ',
'CLEAR_BSY_SET_DRQ', 'SET_BSY', 'SET_STS_7F', 'SET_STS_80', 'XFER_CNTR_CLEAR', 'DECR_DWC', 'FIS_FIRST_FLUSH',
'CLEAR_BSY_SET_DRQ', 'SET_BSY', 'SET_STS_7F', 'SET_STS_80', 'XFER_CNTR_CLEAR', 'DECR_DWCR', 'DECR_DWCW', 'FIS_FIRST_FLUSH',
# FIS_TRANSMIT
'CLEAR_CMD_TO_ISSUE',
# DMA
......@@ -336,7 +336,7 @@ sequence = [{LBL:'POR', ADDR: 0x0, ACT: NOP},
{IF: 'TX_ERR', GOTO:'ERR:Fatal'}, # 1. dx_err[1] (reset by new command)
{ GOTO:'DX:UpdateByteCount'}, # 3. (#2 - skipped PxFBS.EN==1)
{LBL:'DX:UpdateByteCount', ACT: 'DECR_DWC'}, # decr_dwc - decrement remaining DWORDS count, increment transferred
{LBL:'DX:UpdateByteCount', ACT: 'DECR_DWCW'}, # decr_dwc - decrement remaining DWORDS count, increment transferred
{ ACT: 'UPDATE_PRDBC'}, # update_prdbc
{IF: 'DMA_PRD_IRQ_PEND', GOTO:'DX:PrdSetIntr'}, # 1. dma_prd_irq_pend
{IF: 'PIOX', GOTO:'PIO:Update'}, # 2. pPioXfer
......@@ -359,7 +359,7 @@ sequence = [{LBL:'POR', ADDR: 0x0, ACT: NOP},
{ GOTO:'DR:UpdateByteCount'}, # 2. fis_ok implied
{LBL:'DR:UpdateByteCount', ACT: 'R_OK'}, # send_R_OK to device
{ ACT: 'DECR_DWC'}, # decr_dwc - decrement remaining DWORDS count, increment transferred
{ ACT: 'DECR_DWCR'}, # decr_dwc - decrement remaining DWORDS count, increment transferred
{ ACT: 'UPDATE_PRDBC'}, # update_prdbc
{IF: 'DMA_PRD_IRQ_PEND', GOTO:'DX:PrdSetIntr'}, # 1. dma_prd_irq_pend
{IF: 'PIOX', GOTO:'PIO:Update'}, # 2. pPioXfer (#1 ->DX:PrdSetIS is handled by hardware)
......
, .INIT_00 (256'h00100000000E0000000C00000033000000200000000A0000000A0000000A0000)
, .INIT_01 (256'h001944521C399446543044170000001900480019040802020204008400220006)
, .INIT_02 (256'h001900050019C82E000C04020090002924FB2502014000190003004204040000)
, .INIT_03 (256'h845284BE44374C682C4214190012003900480018000A01080022001901020050)
, .INIT_04 (256'h00190090003900900019144601020408020202040039B07D707A021000398C6B)
, .INIT_05 (256'h64540C2504580000004E24FB25020420004C24FB25020420005C000000390000)
, .INIT_06 (256'hA47150F8903900600104006B0202003000E2A89368F018E918CB98A758D73882)
, .INIT_07 (256'h0410003900000039B07D00000050004400220039B07D707A307730F000880102)
, .INIT_08 (256'h00050091C88F002200240091288B28FE000C0090008624FB25020140009CD0FB)
, .INIT_09 (256'h48A528A128FE00140039487F0CAD28FE0090009724FB250200C0005004020091)
, .INIT_0A (256'h8839089C020800AD009000AB24FB2502042000500081005048A5002200240039)
, .INIT_0B (256'h00C002080039889C020800090039889C50BA0024002800B5D0FB50F800A000B1)
, .INIT_0C (256'h009000CF24FB250202200039889C50BA00240028009000C5C50224FB24FB0120)
, .INIT_0D (256'h0050C8E028FE000C009000DB24FB25020240003934D2000000D4001100D4C8D2)
, .INIT_0E (256'h00F60082009000ED24FB2502042000390401009000E624FB2502044000500101)
, .INIT_0F (256'h0100020101000021011001000021004400F6000000F6009000F424FB25020420)
, .INIT_01 (256'h001944521C399446543044170000001900880019003002020204008400220006)
, .INIT_02 (256'h001900050019C82E000C04020110002924FB2502024000190003004204040000)
, .INIT_03 (256'h845284BE44374C682C4214190012003900880018000A02080022001901020090)
, .INIT_04 (256'h00190110003901100019144601020030020202040039B07D707A041000398C6B)
, .INIT_05 (256'h64540C2504580000004E24FB250200C0004C24FB250200C0005C000000390000)
, .INIT_06 (256'hA47150F8903900A00104006B0202005000E2A89368F018E918CB98A758D73882)
, .INIT_07 (256'h0060003900000039B07D00000050004400220039B07D707A307730F001080102)
, .INIT_08 (256'h00050091C88F002200240091288B28FE000C0110008624FB25020240009CD0FB)
, .INIT_09 (256'h48A528A128FE00140039487F0CAD28FE0110009724FB25020140005004020091)
, .INIT_0A (256'h8839089C040800AD011000AB24FB250200C000500081005048A5002200240039)
, .INIT_0B (256'h00C004080039889C040800090039889C50BA0024004800B5D0FB50F8012000B1)
, .INIT_0C (256'h011000CF24FB250204200039889C50BA00240028011000C5C50224FB24FB0220)
, .INIT_0D (256'h0050C8E028FE000C011000DB24FB25020440003934D2000000D4001100D4C8D2)
, .INIT_0E (256'h00F60082011000ED24FB250200C000390401011000E624FB2502018000500101)
, .INIT_0F (256'h0100020101000021021001000021004400F6000000F6011000F424FB250200C0)
, .INIT_10 (256'h0000000000000000000000000000000000000000000000390041000001000000)
, .INITP_00 (256'hC8220098170902401E272722222800309418800820809C802018880022222222)
, .INITP_01 (256'h22082227209C82720A09C22089C680272181A01CB889C8605A2A89C882068270)
......
......@@ -672,6 +672,7 @@ localparam COMMAND_TABLE = 32'h3f00; // 256 bytes for a command table in the sys
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
reg [31:0] sysmem[0:4095];
......@@ -830,14 +831,69 @@ localparam ATA_IDFY = 'hec; // Identify command
end
endtask
task setup_dma_write_identify_command_multi4; // Write DMA, use data received during read identify
input integer lba;
input integer prd_int; // [0] - first prd interrupt, ... [31] - 31-st
input integer nw1; // first segment lengtth (in words)
input integer nw2; // second segment lengtth (in words)
input integer nw3; // third segment lengtth (in words)
integer nw4;
integer i;
begin
nw4 = 256 - nw1 - nw2 - nw3; // total 512 bytes, 256 words
// clear system memory for command
for (i = 0; i < 64; i = i+1) sysmem[(COMMAND_TABLE >> 2) + i] = 0;
// 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)
( 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)
// All other DWORDs are 0 for this command
// Set PRDT (four items)
// PRDT #1
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 0] = SYS_MEM_START + IDENTIFY_BUF; // not shifted
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 3] = (prd_int[0] << 31) | (2 * nw1 - 1); // 2 * nw1 bytes
// PRDT #2
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 4] = SYS_MEM_START + IDENTIFY_BUF + (2 * nw1);
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 7] = (prd_int[0] << 31) | (2 * nw2 - 1); // 2 * nw2 bytes
// PRDT #3
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 8] = SYS_MEM_START + IDENTIFY_BUF + (2 * nw1) + (2 * nw2);
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 11] = (prd_int[0] << 31) | (2 * nw3 - 1); // 2 * nw3 bytes
// PRDT #4
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 12] = SYS_MEM_START + IDENTIFY_BUF + (2 * nw1) + (2 * nw2) + (2 * nw3);
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 15] = (prd_int[0] << 31) | (2 * nw4 - 1); // 2 * nw4 bytes
// Setup command header
maxigp1_writep ((CLB_OFFS32 + 0) << 2, (5 << 0) | // 'CFL' - number of DWORDs in thes CFIS
(0 << 5) | // 'A' Not ATAPI
(1 << 6) | // 'W' Is write to device
(1 << 7) | // 'P' Prefetchable = 1
(0 << 8) | // 'R' Not a Reset
(0 << 9) | // 'B' Not a BIST
// (0 << 10) | // 'C' Do not clear BSY/CI after transmitting this command
(1 << 10) | // 'C' Do clear BSY/CI after transmitting this command
(4 << 16)); // 'PRDTL' - number of PRDT entries (4)
maxigp1_writep ((CLB_OFFS32 +2 ) << 2, (SYS_MEM_START + COMMAND_TABLE) & 32'hffffffc0); // 'CTBA' - Command table base address
// Set Command Issued
maxigp1_writep (HBA_PORT__PxCI__CI__ADDR << 2, 1); // 'PxCI' - Set 'Command issue' for slot 0 (the only one)
// relax and enjoy
end
endtask
initial begin //Host
wait (!RST);
//reg [639:0] TESTBENCH_TITLE = "RESET"; // to show human-readable state in the GTKWave
TESTBENCH_TITLE = "NO_RESET";
$display("[Testbench]: %s @%t", TESTBENCH_TITLE, $time);
repeat (10) begin
@ (posedge CLK);
end
repeat (10) @ (posedge CLK);
axi_set_rd_lag(0);
axi_set_b_lag(0);
......@@ -907,13 +963,19 @@ initial begin //Host
wait (IRQ);
TESTBENCH_TITLE = "Got 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
// sysmem_print ('h1e81,'h180); // for shifted
sysmem_print ('h1e80,'h180);
$finish;
setup_dma_write_identify_command_multi4(1,'h123456, 27,71,83); // LBA = 'h123456
TESTBENCH_TITLE = "Set DMA Write command for device";
$display("[Testbench]: %s @%t", TESTBENCH_TITLE, $time);
repeat (50) @(posedge CLK);
// $finish;
//HBA_PORT__PxIE__DHRE__MASK = 'h1;
end
......@@ -924,6 +986,13 @@ function func_is_dev_identify;
end
endfunction
function func_is_dev_dma_write;
input [31:0] dw;
begin
func_is_dev_dma_write = ((dw & 'hff) == FIS_H2DR ) && (((dw >> 16) & 'hff) == ATA_WDMA);
end
endfunction
integer status;
initial begin //Device
dev.clear_transmit_pause(0);
......@@ -940,7 +1009,7 @@ initial begin //Device
$display("[Dev-TB]: %s, status = 0x%x @%t", DEVICE_TITLE, status, $time);
// Wait for host requests 'identify'
@(dev.receive_id);
forever @(dev.receive_id) begin
if (func_is_dev_identify(dev.receive_data[0])) begin
DEVICE_TITLE = "Got Identify";
$display("[Dev-TB]: %s @%t", DEVICE_TITLE, $time);
......@@ -963,14 +1032,22 @@ initial begin //Device
status); // output integer status;
DEVICE_TITLE = "Device sent Data FIS (Identify)";
$display("[Dev-TB]: %s, status = 0x%x @%t", DEVICE_TITLE, status, $time);
end else begin
DEVICE_TITLE = "Expected Identify, got else";
end else if (func_is_dev_dma_write(dev.receive_data[0])) begin
DEVICE_TITLE = "Got DMA Write";
$display("[Dev-TB]: %s @%t", DEVICE_TITLE, $time);
$display("[Dev-TB]: %h @%t", dev.receive_data[0], $time);
end
dev.send_dma_activate (69, // input integer id;
status); // output integer status;
end else begin
DEVICE_TITLE = "Expected Identify or DMA Write, got else";
$display("[Dev-TB]: %s @%t", DEVICE_TITLE, $time);
$display("[Dev-TB]: %h @%t", dev.receive_data[0], $time);
end
end
end
initial begin
// #30000;
#50000;
......
[*]
[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI
[*] Wed Jan 27 20:37:20 2016
[*] Thu Jan 28 08:34:30 2016
[*]
[dumpfile] "/home/andrey/git/x393_sata/simulation/tb_ahci-20160127133150634.fst"
[dumpfile_mtime] "Wed Jan 27 20:32:21 2016"
[dumpfile_size] 3824683
[dumpfile] "/home/andrey/git/x393_sata/simulation/tb_ahci-20160128011041668.fst"
[dumpfile_mtime] "Thu Jan 28 08:11:37 2016"
[dumpfile_size] 6645501
[savefile] "/home/andrey/git/x393_sata/tb_ahci_01.sav"
[timestart] 22094000
[size] 1823 1173
[timestart] 16640000
[size] 1823 1180
[pos] 1994 0
*-19.117058 23716667 23903334 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
*-22.068264 26843458 28869922 29536522 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] tb_ahci.
[treeopen] tb_ahci.dev.phy.
[treeopen] tb_ahci.dut.
......@@ -752,7 +752,7 @@ tb_ahci.dut.sata_top.ahci_top_i.axi_ahci_regs_i.any_access
tb_ahci.dut.sata_top.ahci_top_i.axi_ahci_regs_i.set_port_rst
@1401200
-axi_ahci_regs
@c00200
@800200
-ahci_fsm
@c00022
tb_ahci.dut.sata_top.ahci_top_i.ahci_fsm_i.pgm_addr[9:0]
......@@ -973,10 +973,16 @@ tb_ahci.dut.sata_top.ahci_top_i.ahci_fsm_i.async_pend_r[1:0]
@28
tb_ahci.dut.sata_top.ahci_top_i.ahci_fsm_i.async_ackn
tb_ahci.dut.sata_top.ahci_top_i.ahci_fsm_i.async_from_st
@1401200
@1000200
-ahci_fsm
@c00200
-ahci_fis_receive
@22
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.xfer_cntr[31:2]
@28
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.xfer_cntr_zero
@22
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.decr_DXC_dw[11:0]
@200
-
@28
......@@ -1004,7 +1010,6 @@ tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.wreg_we_r
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.dwords_over
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_rec_run
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.dma_in_ready
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.is_fis_end
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_end_w
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.data_in_ready
@800028
......@@ -1014,17 +1019,39 @@ tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_end_r[1:0]
(1)tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_end_r[1:0]
@1001200
-group_end
@28
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.hba_data_in_ready
@22
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.hba_data_in_type[1:0]
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.hba_data_in[31:0]
@28
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.hba_data_in_valid
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.dma_skipping_extra
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_first_flushing_r
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.dma_in_valid
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.dma_in
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.dma_in_valid
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_first_flushing_r
@c00028
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_end_r[1:0]
@28
(0)tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_end_r[1:0]
(1)tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_end_r[1:0]
@1401200
-group_end
@28
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.is_fis_end
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.hba_data_in_ready
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.hba_data_in_valid
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_rec_run
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.wreg_we_r
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.dwords_over
@800022
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_dcount[3:0]
@28
(0)tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_dcount[3:0]
(1)tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_dcount[3:0]
(2)tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_dcount[3:0]
(3)tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_receive_i.fis_dcount[3:0]
@1001200
-group_end
@1401200
-ahci_fis_receive
@c00200
......@@ -1106,6 +1133,9 @@ tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_transmit_i.todev_valid
@22
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_transmit_i.todev_type[1:0]
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_transmit_i.todev_data[31:0]
tb_ahci.dut.sata_top.ahci_top_i.ahci_fis_transmit_i.dwords_sent[11:0]
@200
-
@1001200
-group_end
-group_end
......@@ -1269,6 +1299,8 @@ tb_ahci.simul_axi_hp_wr_i.wdata_i.fill[7:0]
-simul_axi_hp_wr
@800200
-ahci_dma
@29
tb_ahci.dut.sata_top.ahci_top_i.ahci_dma_i.cmd_busy
@28
tb_ahci.dut.sata_top.ahci_top_i.ahci_dma_i.hrst
tb_ahci.dut.sata_top.ahci_top_i.ahci_dma_i.mrst
......@@ -1538,6 +1570,10 @@ tb_ahci.dut.sata_top.ahci_top_i.ahci_dma_i.qw_datawr_left[21:3]
tb_ahci.dut.sata_top.ahci_top_i.ahci_dma_i.afi_wvalid
@22
tb_ahci.dut.sata_top.ahci_top_i.ahci_dma_i.qw_datawr_burst[3:0]
@28
tb_ahci.dut.sata_top.ahci_top_i.ahci_dma_i.mclk
tb_ahci.dut.sata_top.ahci_top_i.ahci_dma_i.ct_done
tb_ahci.dut.sata_top.ahci_top_i.ahci_dma_i.ct_done_mclk
@c00200
-dma_d2h_fifo
@28
......@@ -1647,7 +1683,7 @@ tb_ahci.dut.sata_top.ahci_top_i.ahci_dma_i.ahci_dma_wr_fifo_i.fifo_rd_r
tb_ahci.dut.sata_top.ahci_top_i.ahci_dma_i.ahci_dma_wr_fifo_i.raddr[3:0]
@1401200
-dma_d2h_fifo
@800200
@c00200
-sim_d2h
@200
-
......@@ -1661,7 +1697,7 @@ tb_ahci.afi_sim_wr_data[63:0]
@28
tb_ahci.afi_sim_wr_ready
tb_ahci.afi_sim_wr_valid
@1000200
@1401200
-sim_d2h
@c00200
-ahci_fis_receive
......
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