Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
x393_sata
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
x393_sata
Commits
4336698a
Commit
4336698a
authored
Jan 09, 2016
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
finished initial code for ahci_fis_transmit module
parent
892ec17c
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
101 additions
and
102 deletions
+101
-102
ahci_fis_transmit.v
ahci/ahci_fis_transmit.v
+101
-102
No files found.
ahci/ahci_fis_transmit.v
View file @
4336698a
...
@@ -21,32 +21,32 @@
...
@@ -21,32 +21,32 @@
`timescale
1
ns
/
1
ps
`timescale
1
ns
/
1
ps
module
ahci_fis_transmit
#(
module
ahci_fis_transmit
#(
parameter
PREFETCH_ALWAYS
=
0
,
parameter
READ_REG_LATENCY
=
2
,
// 0 if reg_rdata is available with reg_re/reg_addr
parameter
READ_REG_LATENCY
=
2
,
// 0 if reg_rdata is available with reg_re/reg_addr
parameter
READ_CT_LATENCY
=
2
,
// 0 if reg_rdata is available with reg_re/reg_addr
parameter
READ_CT_LATENCY
=
2
,
// 0 if reg_rdata is available with reg_re/reg_addr
parameter
ADDRESS_BITS
=
10
// number of memory address bits - now fixed. Low half - RO/RW/RWC,RW1 (2-cycle write), 2-nd just RW (single-cycle)
parameter
ADDRESS_BITS
=
10
// number of memory address bits - now fixed. Low half - RO/RW/RWC,RW1 (2-cycle write), 2-nd just RW (single-cycle)
)(
)(
input
hba_rst
,
// @posedge mclk -
sync reset
input
hba_rst
,
// @posedge mclk -
when port is reset (even COMINIT)?
input
mclk
,
// for command/status
input
mclk
,
// for command/status
// Command pulses to execute states
input
fetch_cmd
,
// Enter p:FetchCmd, fetch command header (from the register memory, prefetch command FIS)
input
fetch_cmd
,
// Enter p:FetchCmd, fetch command header (from the register memory, prefetch command FIS)
// wait for either fetch_cmd_busy == 0 or pCmdToIssue ==1 after fetch_cmd
// wait for either fetch_cmd_busy == 0 or pCmdToIssue ==1 after fetch_cmd
output
pCmdToIssue
,
// AHCI port variable
output
dmaCntrZero
,
// DmA counter is zero (first command)
output
reg
fetch_cmd_busy
,
// does not include prefetching CT
// input fetch_ct, // fetch command table (ch_ctba[31:7] should be valid by now)
input
cfis_xmit
,
// transmit command (wait for dma_ct_busy == 0)
input
cfis_xmit
,
// transmit command (wait for dma_ct_busy == 0)
input
dx_transmit
,
// send FIS header DWORD, (just 0x46), then forward DMA data
input
dx_transmit
,
// send FIS header DWORD, (just 0x46), then forward DMA data
// transmit until error, 2048DWords or pDmaXferCnt
// transmit until error, 2048DWords or pDmaXferCnt
input
atapi_xmit
,
// tarsmit ATAPI command FIS
output
reg
done
,
output
reg
busy
,
input
clearCmdToIssue
,
// From CFIS:SUCCESS
output
pCmdToIssue
,
// AHCI port variable
// output dmaCntrZero, // DMA counter is zero - would be a duplicate to the one in receive module and dwords_sent output
output
reg
fetch_cmd_busy
,
// does not include prefetching CT
input
syncesc_recv
,
// These two inputs interrupt transmit
input
syncesc_recv
,
// These two inputs interrupt transmit
input
xmit_err
,
//
input
xmit_err
,
//
output
dx_busy
,
output
dx_done
,
// single-clock dx_transmit is finished, check dx_err
output
[
1
:
0
]
dx_err
,
// bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command)
output
[
1
:
0
]
dx_err
,
// bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command)
input
atapi_xmit
,
// tarsmit ATAPI command FIS
output
[
15
:
0
]
ch_prdtl
,
// Physical region descriptor table length (in entries, 0 is 0)
output
[
15
:
0
]
ch_prdtl
,
// Physical region descriptor table length (in entries, 0 is 0)
output
ch_c
,
// Clear busy upon R_OK for this FIS
output
ch_c
,
// Clear busy upon R_OK for this FIS
output
ch_b
,
// Built-in self test command
output
ch_b
,
// Built-in self test command
...
@@ -56,39 +56,30 @@ module ahci_fis_transmit #(
...
@@ -56,39 +56,30 @@ module ahci_fis_transmit #(
output
ch_a
,
// ATAPI: 1 means device should send PIO setup FIS for ATAPI command
output
ch_a
,
// ATAPI: 1 means device should send PIO setup FIS for ATAPI command
output
[
4
:
0
]
ch_cfl
,
// length of the command FIS in DW, 0 means none. 0 and 1 - illegal,
output
[
4
:
0
]
ch_cfl
,
// length of the command FIS in DW, 0 means none. 0 and 1 - illegal,
// maximal is 16 (0x10)
// maximal is 16 (0x10)
// output [31:7] ch_ctba, // command table base address - use reg_rdata[31:7] - outside
output
reg
[
11
:
2
]
dwords_sent
,
// number of DWORDs transmitted (up to 2048)
output
reg
[
11
:
2
]
dwords_sent
,
// number of DWORDs transmitted (up to 2048)
// register memory interface
// register memory interface
output
reg
[
ADDRESS_BITS
-
1
:
0
]
reg_addr
,
output
reg
[
ADDRESS_BITS
-
1
:
0
]
reg_addr
,
output
reg_re
,
output
reg_re
,
input
[
31
:
0
]
reg_rdata
,
input
[
31
:
0
]
reg_rdata
,
// ahci_fis_receive interface
// 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
[
31
:
2
]
xfer_cntr
,
// transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc
output
dma_ctba_ld
,
// load command table
base address
output
dma_ctba_ld
,
// load command table
address from
output
dma_start
,
// start processing command table, reset prdbc (next cycle after dma_ctba_ld, bits prdtl valid)
output
dma_start
,
// start processing command table, reset prdbc (next cycle after dma_ctba_ld, bits prdtl valid)
output
dma_dev_wr
,
// write to device (valid at start)
output
dma_dev_wr
,
// write to device (valid at start)
input
dma_ct_busy
,
// dma module is busy reading command table from the system memory
input
dma_ct_busy
,
// dma module is busy reading command table from the system memory
// issue dma_prd_start same time as dma_start if prefetch enabled, otherwise with cfis_xmit
// issue dma_prd_start same time as dma_start if prefetch enabled, otherwise with cfis_xmit
output
dma_prd_start
,
// at or after cmd_start - enable reading PRD/data (if any) ch_prdtl should be valid
output
reg
dma_prd_start
,
// at or after cmd_start - enable reading PRD/data (if any) ch_prdtl should be valid, twice - OK
output
reg
cmd_abort
,
// try to abort a command TODO: Implement
// output cmd_abort, // try to abort a command TODO: Implement
// reading out command table data from DMA module
// reading out command table data from DMA module
output
reg
[
4
:
0
]
ct_addr
,
// DWORD address
output
reg
[
4
:
0
]
ct_addr
,
// DWORD address
output
ct_re
,
//
output
ct_re
,
//
input
[
31
:
0
]
ct_data
,
//
input
[
31
:
0
]
ct_data
,
//
// DMA (memory -> device) interface
// DMA (memory -> device) interface
input
[
31
:
0
]
dma_out
,
// 32-bit data from the DMA module, HBA -> device port
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
input
dma_dav
,
// at least one dword is ready to be read from DMA module
...
@@ -122,30 +113,31 @@ module ahci_fis_transmit #(
...
@@ -122,30 +113,31 @@ module ahci_fis_transmit #(
reg
ch_p_r
;
reg
ch_p_r
;
reg
ch_w_r
;
reg
ch_w_r
;
reg
ch_a_r
;
reg
ch_a_r
;
reg
[
4
:
0
]
ch_cfl_r
;
reg
[
4
:
0
]
ch_cmd_len_r
;
reg
[
4
:
0
]
ch_cfl_out_r
;
reg
[
4
:
0
]
cfis_acmd_left_r
;
// number of DWORDS in CFIS or ACMD area of the command table left to be fetched from ahci_dma module BRAM
// For CFIS this register is set from ch_cmd_len_r, for ACMD - from the xfer_cntr input
// (stored in the ahci_fis_receive module)
reg
[
4
:
0
]
cfis_acmd_left_out_r
;
// Same, just with latency of the data available from the ahci_dma module
// reg [31:7] ch_ctba_r;
// reg [31:7] ch_ctba_r;
reg
[
READ_REG_LATENCY
:
0
]
reg_re_r
;
reg
[
READ_REG_LATENCY
:
0
]
reg_re_r
;
wire
reg_re_w
;
// combined conditions to read register memory
wire
reg_re_w
;
// combined conditions to read register memory
/// wire reg_stb = reg_re_r[READ_REG_LATENCY];
/// wire reg_stb = reg_re_r[READ_REG_LATENCY];
wire
pre_reg_stb
=
reg_re_r
[
READ_REG_LATENCY
-
1
]
;
wire
pre_reg_stb
=
reg_re_r
[
READ_REG_LATENCY
-
1
]
;
reg
[
3
:
0
]
fetch_chead_r
;
reg
[
3
:
0
]
fetch_chead_r
;
reg
[
3
:
0
]
fetch_chead_stb_r
;
reg
[
3
:
0
]
fetch_chead_stb_r
;
wire
chead_done_w
=
fetch_chead_stb_r
[
2
]
;
// done fetching command header
wire
chead_done_w
=
fetch_chead_stb_r
[
2
]
;
// done fetching command header
reg
chead_bsy
;
// busy reading command header
reg
chead_bsy
;
// busy reading command header
reg
chead_bsy_re
;
// busy sending read command header
reg
chead_bsy_re
;
// busy sending read command header
reg
pCmdToIssue_r
;
reg
pCmdToIssue_r
;
wire
clearCmdToIssue
;
// TODO: assign - clear pCmdToIssue
// reg fetch_ct_r;
// reg fetch_ct_r;
reg
cfis_xmit_pend_r
;
//
reg
acfis_xmit_pend_r
;
//
reg
cfis_xmit_start_r
;
reg
acfis_xmit_start_r
;
reg
cfis_xmit_busy_r
;
//
reg
acfis_xmit_busy_r
;
//
reg
dmaCntrZero_r
;
// first command
// reg anc_fis_r; // This is ATAPI FIS, not Command FIS
// wire start_sync_escape_w = cfis_xmit && ch_r_r; - no, it should be instead of a ct_fetch
// TODO: Start FIS transmit when all FIS is in FIFO or data and >half(too slow, need minimum to be able to send wait primitive) or less?
wire
cfis_xmit_start_w
=
(
dx_transmit
||
cfis_xmit_pend_r
)
&&
!
dma_ct_busy
&&
!
fetch_cmd_busy
;
// dma_ct_busy no gaps with fetch_cmd_busy
wire
acfis_xmit_start_w
=
(
cfis_xmit
||
atapi_xmit
||
a
cfis_xmit_pend_r
)
&&
!
dma_ct_busy
&&
!
fetch_cmd_busy
;
// dma_ct_busy no gaps with fetch_cmd_busy
wire
cfis_xmit_end
;
wire
acfis_xmit_end
=
ct_stb
&&
fis_dw_last
;
wire
ct_re_w
;
// next cycle will be ct_re;
wire
ct_re_w
;
// next cycle will be ct_re;
reg
[
READ_CT_LATENCY
:
0
]
ct_re_r
;
reg
[
READ_CT_LATENCY
:
0
]
ct_re_r
;
...
@@ -159,8 +151,9 @@ module ahci_fis_transmit #(
...
@@ -159,8 +151,9 @@ module ahci_fis_transmit #(
wire
dx_dma_last_w
;
// sending last adat word
wire
dx_dma_last_w
;
// sending last adat word
reg
dx_busy_r
;
reg
dx_busy_r
;
reg
[
1
:
0
]
dx_err_r
;
reg
[
1
:
0
]
dx_err_r
;
reg
dx_done_r
;
wire
any_cmd_start
=
fetch_cmd
||
cfis_xmit
||
dx_transmit
||
atapi_xmit
;
wire
any_cmd_start
=
fetch_cmd
||
cfis_xmit
||
dx_transmit
||
atapi_xmit
;
wire
done_w
=
dx_dma_last_w
||
((
|
dx_err_r
)
&&
dx_busy_r
)
||
chead_done_w
||
acfis_xmit_end
;
// done on last transmit or error
assign
todev_valid
=
todev_full_r
;
assign
todev_valid
=
todev_full_r
;
assign
dma_re
=
dma_re_w
;
assign
dma_re
=
dma_re_w
;
...
@@ -173,73 +166,71 @@ module ahci_fis_transmit #(
...
@@ -173,73 +166,71 @@ module ahci_fis_transmit #(
assign
ch_p
=
ch_p_r
;
assign
ch_p
=
ch_p_r
;
assign
ch_w
=
ch_w_r
;
assign
ch_w
=
ch_w_r
;
assign
ch_a
=
ch_a_r
;
assign
ch_a
=
ch_a_r
;
assign
ch_cfl
=
ch_cfl_r
;
assign
ch_cfl
=
cfis_acmd_left_r
;
// assign ch_ctba = ch_ctba_r[31:7];
assign
reg_re_w
=
fetch_cmd
||
chead_bsy_re
;
assign
reg_re_w
=
fetch_cmd
||
chead_bsy_re
;
assign
dma_ctba_ld
=
fetch_chead_stb_r
[
2
]
;
assign
dma_ctba_ld
=
fetch_chead_stb_r
[
2
]
;
assign
dma_start
=
fetch_chead_stb_r
[
3
]
;
// next cycle after dma_ctba_ld
assign
dma_start
=
fetch_chead_stb_r
[
3
]
;
// next cycle after dma_ctba_ld
assign
pCmdToIssue
=
pCmdToIssue_r
;
assign
pCmdToIssue
=
pCmdToIssue_r
;
assign
dmaCntrZero
=
dmaCntrZero_r
;
//
assign dmaCntrZero = dmaCntrZero_r;
assign
ct_re
=
ct_re_r
[
0
]
;
assign
ct_re
=
ct_re_r
[
0
]
;
assign
fis_data_valid
=
ct_stb
;
// no wait write to output register 'todev_data', ct_re_r[0] is throttled according to FIFO room availability
assign
fis_data_valid
=
ct_stb
;
// no wait write to output register 'todev_data', ct_re_r[0] is throttled according to FIFO room availability
assign
ct_re_w
=
todev_ready
&&
((
c
h_cfl_r
[
4
:
1
]
!=
0
)
||
(
ch_cfl
_r
[
0
]
&&
!
ct_re_r
[
0
]))
;
// Later add more sources
assign
ct_re_w
=
todev_ready
&&
((
c
fis_acmd_left_r
[
4
:
1
]
!=
0
)
||
(
cfis_acmd_left
_r
[
0
]
&&
!
ct_re_r
[
0
]))
;
// Later add more sources
assign
fis_dw_last
=
(
c
h_cfl
_out_r
==
1
)
;
assign
fis_dw_last
=
(
c
fis_acmd_left
_out_r
==
1
)
;
assign
fis_data_type
=
{
fis_dw_last
,
(
write_or_w
&&
dx_fis_pend_r
)
|
(
fis_dw_first
&&
ct_stb
)
};
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
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
:
2
]
==
1
)
;
assign
dx_busy
=
dx_busy_r
;
assign
dx_done
=
dx_done_r
;
assign
dx_err
=
dx_err_r
;
assign
dx_err
=
dx_err_r
;
assign
dma_dev_wr
=
ch_w_r
;
always
@
(
posedge
mclk
)
begin
always
@
(
posedge
mclk
)
begin
// Mutliplex between DMA and FIS output to the output routed to transmit FIFO
// Mutliplex between DMA and FIS output to the output routed to transmit FIFO
// Count bypassing DMA dwords to generate FIS_last condition?
// Count bypassing DMA dwords to generate FIS_last condition?
if
(
hba_rst
)
todev_full_r
<=
0
;
if
(
hba_rst
)
todev_full_r
<=
0
;
else
if
(
write_or_w
)
todev_full_r
<=
1
;
// do not fill the buffer if FIFO is not ready
else
if
(
write_or_w
)
todev_full_r
<=
1
;
// do not fill the buffer if FIFO is not ready
else
if
(
todev_ready
)
todev_full_r
<=
0
;
else
if
(
todev_ready
)
todev_full_r
<=
0
;
if
(
write_or_w
)
todev_data
<=
dma_en_r
?
dma_out
:
fis_data_out
;
if
(
write_or_w
)
todev_data
<=
dma_en_r
?
dma_out
:
fis_data_out
;
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
;
if
(
hba_rst
)
todev_type
<=
3
;
// invalid? - no, now first and last word in command FIS (impossible?)
// Read 3 DWORDs from the command header
else
if
(
write_or_w
)
todev_type
<=
dma_en_r
?
{
dx_dma_last_w
,
1'b0
}
:
fis_data_type
;
if
(
hba_rst
)
fetch_chead_r
<=
0
;
if
(
hba_rst
)
fetch_chead_r
<=
0
;
// running 1
else
if
(
fetch_cmd
)
fetch_chead_r
<=
1
;
else
if
(
fetch_cmd
)
fetch_chead_r
<=
1
;
else
fetch_chead_r
<=
fetch_chead_r
<<
1
;
else
fetch_chead_r
<=
fetch_chead_r
<<
1
;
if
(
hba_rst
)
fetch_chead_stb_r
<=
0
;
if
(
hba_rst
)
fetch_chead_stb_r
<=
0
;
else
if
(
pre_reg_stb
&&
chead_bsy
)
fetch_chead_stb_r
<=
1
;
else
if
(
pre_reg_stb
&&
chead_bsy
)
fetch_chead_stb_r
<=
1
;
else
fetch_chead_stb_r
<=
fetch_chead_stb_r
<<
1
;
else
fetch_chead_stb_r
<=
fetch_chead_stb_r
<<
1
;
if
(
hba_rst
)
chead_bsy
<=
0
;
if
(
hba_rst
)
chead_bsy
<=
0
;
else
if
(
fetch_cmd
)
chead_bsy
<=
1
;
else
if
(
fetch_cmd
)
chead_bsy
<=
1
;
else
if
(
chead_done_w
)
chead_bsy
<=
0
;
else
if
(
chead_done_w
)
chead_bsy
<=
0
;
if
(
hba_rst
)
chead_bsy_re
<=
0
;
if
(
hba_rst
)
chead_bsy_re
<=
0
;
else
if
(
fetch_cmd
)
chead_bsy_re
<=
1
;
else
if
(
fetch_cmd
)
chead_bsy_re
<=
1
;
else
if
(
fetch_chead_r
[
1
])
chead_bsy_re
<=
0
;
// read 3 dwords
else
if
(
fetch_chead_r
[
1
])
chead_bsy_re
<=
0
;
// read 3 dwords
if
(
hba_rst
)
reg_re_r
<=
0
;
if
(
hba_rst
)
reg_re_r
<=
0
;
// [0] -> reg_re output
else
if
(
reg_re_w
)
reg_re_r
<=
1
;
else
if
(
reg_re_w
)
reg_re_r
<=
1
;
else
reg_re_r
<=
reg_re_r
<<
1
;
else
reg_re_r
<=
reg_re_r
<<
1
;
if
(
fetch_cmd
)
reg_addr
<=
CLB_OFFS32
;
// there will be more conditions
if
(
fetch_cmd
)
reg_addr
<=
CLB_OFFS32
;
// there will be more conditions
else
if
(
reg_re_r
[
0
])
reg_addr
<=
reg_addr
+
1
;
else
if
(
reg_re_r
[
0
])
reg_addr
<=
reg_addr
+
1
;
// save command header data to registers
// save command header data to registers
if
(
fetch_chead_stb_r
[
0
])
begin
if
(
fetch_chead_stb_r
[
0
])
begin
ch_prdtl_r
<=
reg_rdata
[
31
:
16
]
;
ch_prdtl_r
<=
reg_rdata
[
31
:
16
]
;
ch_c_r
<=
reg_rdata
[
10
]
;
ch_c_r
<=
reg_rdata
[
10
]
;
ch_b_r
<=
reg_rdata
[
9
]
;
ch_b_r
<=
reg_rdata
[
9
]
;
ch_r_r
<=
reg_rdata
[
8
]
;
ch_r_r
<=
reg_rdata
[
8
]
;
ch_p_r
<=
reg_rdata
[
7
]
;
ch_p_r
<=
reg_rdata
[
7
]
;
ch_w_r
<=
reg_rdata
[
6
]
;
ch_w_r
<=
reg_rdata
[
6
]
;
ch_a_r
<=
reg_rdata
[
5
]
;
ch_a_r
<=
reg_rdata
[
5
]
;
ch_c
fl_r
<=
reg_rdata
[
4
:
0
]
;
ch_c
md_len_r
<=
reg_rdata
[
4
:
0
]
;
end
end
if
(
hba_rst
)
pCmdToIssue_r
<=
0
;
if
(
hba_rst
)
pCmdToIssue_r
<=
0
;
...
@@ -250,39 +241,41 @@ module ahci_fis_transmit #(
...
@@ -250,39 +241,41 @@ module ahci_fis_transmit #(
else
if
(
fetch_cmd
)
fetch_cmd_busy
<=
1
;
else
if
(
fetch_cmd
)
fetch_cmd_busy
<=
1
;
else
if
(
dma_start
)
fetch_cmd_busy
<=
0
;
else
if
(
dma_start
)
fetch_cmd_busy
<=
0
;
// fetch and send command fis
//CFIS/ATAPI common
if
(
hba_rst
||
cfis_xmit_start_w
)
cfis_xmit_pend_r
<=
0
;
else
if
(
cfis_xmit
)
cfis_xmit_pend_r
<=
1
;
cfis_xmit_start_r
<=
!
hba_rst
&&
cfis_xmit_start_w
;
if
(
hba_rst
)
cfis_xmit_busy_r
<=
0
;
// if (hba_rst || cfis_xmit) anc_fis_r <= 0;
else
if
(
cfis_xmit_start_r
)
cfis_xmit_busy_r
<=
1
;
// else if (atapi_xmit) anc_fis_r <= 1;
else
if
(
cfis_xmit_end
)
cfis_xmit_busy_r
<=
0
;
// fetch and send command/atapi FIS
if
(
hba_rst
||
acfis_xmit_start_w
)
acfis_xmit_pend_r
<=
0
;
else
if
(
cfis_xmit
||
atapi_xmit
)
acfis_xmit_pend_r
<=
1
;
acfis_xmit_start_r
<=
!
hba_rst
&&
acfis_xmit_start_w
;
if
(
hba_rst
)
acfis_xmit_busy_r
<=
0
;
else
if
(
acfis_xmit_start_r
)
acfis_xmit_busy_r
<=
1
;
else
if
(
acfis_xmit_end
)
acfis_xmit_busy_r
<=
0
;
if
(
fetch_chead_stb_r
[
0
])
ch_cfl_r
<=
reg_rdata
[
4
:
0
]
;
// Will assume that there is room for ...
if
(
cfis_xmit
)
cfis_acmd_left_r
<=
ch_cmd_len_r
[
4
:
0
]
;
// Will assume that there is room for ...
else
if
(
cfis_xmit_busy_r
&&
ct_re_r
[
0
])
ch_cfl_r
<=
ch_cfl_r
-
1
;
else
if
(
atapi_xmit
)
cfis_acmd_left_r
<=
(
|
xfer_cntr
[
31
:
4
])
?
5'h4
:
{
3'b0
,
xfer_cntr
[
3
:
2
]
};
else
if
(
acfis_xmit_busy_r
&&
ct_re_r
[
0
])
cfis_acmd_left_r
<=
cfis_acmd_left_r
-
1
;
// Counting CFIS dwords sent to TL
// Counting CFIS
/ATAPI FIS
dwords sent to TL
if
(
cfis_xmit_start_w
)
ch_cfl_out_r
<=
ch_cfl
_r
;
if
(
acfis_xmit_start_r
)
cfis_acmd_left_out_r
<=
cfis_acmd_left
_r
;
else
if
(
ct_stb
)
ch_cfl_out_r
<=
ch_cfl
_out_r
-
1
;
else
if
(
ct_stb
)
cfis_acmd_left_out_r
<=
cfis_acmd_left
_out_r
-
1
;
ct_re_r
<=
{
ct_re_r
[
READ_CT_LATENCY
-
1
:
0
]
,
ct_re_w
};
ct_re_r
<=
{
ct_re_r
[
READ_CT_LATENCY
-
1
:
0
]
,
ct_re_w
};
if
(
cfis_xmit
)
ct_addr
<=
0
;
if
(
cfis_xmit
)
ct_addr
<=
0
;
else
if
(
ch_cfl_r
[
0
])
ct_addr
<=
ct_addr
+
1
;
else
if
(
atapi_xmit
)
ct_addr
<=
'h10
;
// start of ATAPI area
else
if
(
cfis_acmd_left_r
[
0
])
ct_addr
<=
ct_addr
+
1
;
// first/last dword in FIS
// first/last dword in FIS
if
(
!
cfis_xmit_busy_r
)
fis_dw_first
<=
1
;
if
(
!
a
cfis_xmit_busy_r
)
fis_dw_first
<=
1
;
else
if
(
ct_stb
)
fis_dw_first
<=
0
;
else
if
(
ct_stb
)
fis_dw_first
<=
0
;
//
TODO: Implement ATAPI command, other FIS to send?
//
TODO: update xfer length, prdtl (only after R_OK) - yes, do it outside
// Send Data FIS TODO: abort on errors, and busy (or done) output
// input syncesc_recv, // These two inputs interrupt transmit
// input xmit_err, //
//TODO: update xfer length, prdtl (only after R_OK)?
if
(
dx_transmit
)
dx_dwords_left
[
11
:
2
]
<=
(
|
xfer_cntr
[
31
:
11
])
?
10'h200
:{
1'b0
,
xfer_cntr
[
10
:
2
]
};
if
(
dx_transmit
)
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
;
else
if
(
dma_re_w
)
dx_dwords_left
[
11
:
2
]
<=
dx_dwords_left
[
11
:
2
]
-
1
;
...
@@ -306,15 +299,21 @@ module ahci_fis_transmit #(
...
@@ -306,15 +299,21 @@ module ahci_fis_transmit #(
if
(
hba_rst
)
dx_busy_r
<=
0
;
if
(
hba_rst
)
dx_busy_r
<=
0
;
else
if
(
dx_transmit
)
dx_busy_r
<=
1
;
else
if
(
dx_transmit
)
dx_busy_r
<=
1
;
else
if
(
dx_dma_last_w
||
(
|
dx_err_r
))
dx_busy_r
<=
0
;
else
if
(
dx_dma_last_w
||
(
|
dx_err_r
))
dx_busy_r
<=
0
;
// done on last transmit or error
if
(
hba_rst
)
dx_done_r
<=
0
;
dma_prd_start
<=
(
dma_start
&&
(
PREFETCH_ALWAYS
||
ch_p_r
||
!
ch_w_r
))
||
// device read may prefetch just prd addresses
else
dx_done_r
<=
dx_dma_last_w
||
((
|
dx_err_r
)
&&
dx_busy_r
)
;
(
dx_fis_pend_r
&&
write_or_w
)
;
// enable PRD read now (if it was not already done)
// TODO: Make commmon done for all commands?
end
if
(
hba_rst
)
done
<=
0
;
else
done
<=
done_w
;
if
(
hba_rst
)
busy
<=
0
;
else
if
(
any_cmd_start
)
busy
<=
1
;
else
if
(
done_w
)
busy
<=
0
;
cmd_abort
<=
done_w
&&
(
|
dx_err_r
)
;
end
endmodule
endmodule
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment