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
f81326a9
Commit
f81326a9
authored
Jan 08, 2016
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Continue on AHCI implementation - started FIS transmit
parent
ce85dcb3
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
206 additions
and
20 deletions
+206
-20
ahci_fis_receive.v
utils/ahci_fis_receive.v
+35
-20
ahci_fis_transmit.v
utils/ahci_fis_transmit.v
+171
-0
No files found.
utils/ahci_fis_receive.v
View file @
f81326a9
...
@@ -43,14 +43,21 @@ module ahci_fis_receive#(
...
@@ -43,14 +43,21 @@ module ahci_fis_receive#(
input
get_sdbfis
,
input
get_sdbfis
,
input
get_ufis
,
input
get_ufis
,
input
get_data_fis
,
input
get_data_fis
,
input
get_ignore
,
// ignore whatever FIS
data in the
input
get_ignore
,
// ignore whatever FIS
(use for DMA activate too?)
output
reg
get_fis_busy
,
// busy processing FIS
output
reg
get_fis_busy
,
// busy processing FIS
output
reg
fis_first_vld
,
// fis_first contains valid FIS header, reset by get_*
output
reg
fis_first_vld
,
// fis_first contains valid FIS header, reset by get_*
output
reg
fis_ok
,
// FIS done, checksum OK reset by starting a new get FIS
output
reg
fis_ok
,
// FIS done, checksum OK reset by starting a new get FIS
output
reg
fis_err
,
// FIS done, checksum ERROR reset by starting a new get FIS
output
reg
fis_err
,
// FIS done, checksum ERROR reset by starting a new get FIS
output
fis_ferr
,
// FIS done, fatal error - FIS too long
output
fis_ferr
,
// FIS done, fatal error - FIS too long
input
update_err_sts
,
// update PxTFD.STS and PxTFD.ERR from the last received regs d2h
input
update_err_sts
,
// update PxTFD.STS and PxTFD.ERR from the last received regs d2h
input
clear_bsy_drq
,
// clear PxTFD.STS.BSY and PxTFD.STS.DRQ, update
input
set_bsy
,
// set PxTFD.STS.BSY, update
input
set_sts_7f
,
// set PxTFD.STS = 0x7f, update
input
set_sts_80
,
// set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update
// TODO: Add writing PRDBC here?
output
[
7
:
0
]
tfd_sts
,
// Current PxTFD status field (updated after regFIS and SDB - certain fields)
output
[
7
:
0
]
tfd_sts
,
// Current PxTFD status field (updated after regFIS and SDB - certain fields)
// tfd_sts[7] - BSY, tfd_sts[4] - DRQ, tfd_sts[0] - ERR
output
[
7
:
0
]
tfd_err
,
// Current PxTFD error field (updated after regFIS and SDB)
output
[
7
:
0
]
tfd_err
,
// Current PxTFD error field (updated after regFIS and SDB)
output
reg
fis_i
,
// value of "I" field in received regsD2H or SDB FIS
output
reg
fis_i
,
// value of "I" field in received regsD2H or SDB FIS
output
reg
sdb_n
,
// value of "N" field in received SDB FIS
output
reg
sdb_n
,
// value of "N" field in received SDB FIS
...
@@ -86,6 +93,8 @@ CLB_OFFS = 0x800 # In the second half of the register space (0x800..0xbff - 1KB)
...
@@ -86,6 +93,8 @@ CLB_OFFS = 0x800 # In the second half of the register space (0x800..0xbff - 1KB)
FB_OFFS = 0xc00 # Needs 0x100 bytes
FB_OFFS = 0xc00 # Needs 0x100 bytes
#HBA_PORT0 = 0x100 Not needed, always HBA_OFFS + 0x100
#HBA_PORT0 = 0x100 Not needed, always HBA_OFFS + 0x100
*/
*/
localparam
HBA_OFFS32
=
0
;
localparam
HBA_OFFS32
=
0
;
localparam
HBA_PORT0_OFFS32
=
'h40
;
localparam
HBA_PORT0_OFFS32
=
'h40
;
...
@@ -147,6 +156,7 @@ localparam DATA_TYPE_ERR = 3;
...
@@ -147,6 +156,7 @@ localparam DATA_TYPE_ERR = 3;
reg
[
15
:
0
]
tf_err_sts
;
reg
[
15
:
0
]
tf_err_sts
;
reg
update_err_sts_r
;
// Forward data to DMA (dev->mem) engine
// Forward data to DMA (dev->mem) engine
assign
dma_in_valid
=
dma_in_ready
&&
(
hda_data_in_type
==
DATA_TYPE_DMA
)
&&
data_in_ready
&&
!
too_long_err
;
assign
dma_in_valid
=
dma_in_ready
&&
(
hda_data_in_type
==
DATA_TYPE_DMA
)
&&
data_in_ready
&&
!
too_long_err
;
...
@@ -163,8 +173,6 @@ localparam DATA_TYPE_ERR = 3;
...
@@ -163,8 +173,6 @@ localparam DATA_TYPE_ERR = 3;
assign
tfd_sts
=
tf_err_sts
[
7
:
0
]
;
assign
tfd_sts
=
tf_err_sts
[
7
:
0
]
;
assign
tfd_err
=
tf_err_sts
[
15
:
8
]
;
assign
tfd_err
=
tf_err_sts
[
15
:
8
]
;
always
@
(
posedge
mclk
)
begin
always
@
(
posedge
mclk
)
begin
if
(
hba_rst
||
dma_in_stop
)
dma_in
<=
0
;
if
(
hba_rst
||
dma_in_stop
)
dma_in
<=
0
;
else
if
(
dma_in_start
)
dma_in
<=
1
;
else
if
(
dma_in_start
)
dma_in
<=
1
;
...
@@ -239,28 +247,35 @@ localparam DATA_TYPE_ERR = 3;
...
@@ -239,28 +247,35 @@ localparam DATA_TYPE_ERR = 3;
if
(
reg_we_w
)
reg_data
[
31
:
8
]
<=
hda_data_in
[
31
:
8
]
;
if
(
reg_we_w
)
reg_data
[
31
:
8
]
<=
hda_data_in
[
31
:
8
]
;
else
if
(
update_sig
[
1
])
reg_data
[
31
:
8
]
<=
hda_data_in
[
23
:
0
]
;
else
if
(
update_sig
[
1
])
reg_data
[
31
:
8
]
<=
hda_data_in
[
23
:
0
]
;
else
if
(
update_err_sts
)
reg_data
[
31
:
8
]
<=
{
16'b0
,
tf_err_sts
[
15
:
8
]
};
else
if
(
update_err_sts
_r
)
reg_data
[
31
:
8
]
<=
{
16'b0
,
tf_err_sts
[
15
:
8
]
};
if
(
reg_we_w
)
reg_data
[
7
:
0
]
<=
hda_data_in
[
7
:
0
]
;
if
(
reg_we_w
)
reg_data
[
7
:
0
]
<=
hda_data_in
[
7
:
0
]
;
else
if
(
update_sig
[
3
])
reg_data
[
7
:
0
]
<=
hda_data_in
[
7
:
0
]
;
else
if
(
update_sig
[
3
])
reg_data
[
7
:
0
]
<=
hda_data_in
[
7
:
0
]
;
else
if
(
update_err_sts
)
reg_data
[
7
:
0
]
<=
tf_err_sts
[
7
:
0
]
;
else
if
(
update_err_sts
_r
)
reg_data
[
7
:
0
]
<=
tf_err_sts
[
7
:
0
]
;
if
(
reg_d2h
||
update_sig
[
0
])
tf_err_sts
<=
hda_data_in
[
15
:
0
]
;
if
(
reg_d2h
||
update_sig
[
0
])
tf_err_sts
<=
hda_data_in
[
15
:
0
]
;
else
if
(
reg_sdb
)
tf_err_sts
<=
{
hda_data_in
[
15
:
8
]
,
tf_err_sts
[
7
]
,
hda_data_in
[
6
:
4
]
,
tf_err_sts
[
3
]
,
hda_data_in
[
2
:
0
]
};
else
if
(
reg_sdb
)
tf_err_sts
<=
{
hda_data_in
[
15
:
8
]
,
tf_err_sts
[
7
]
,
hda_data_in
[
6
:
4
]
,
tf_err_sts
[
3
]
,
hda_data_in
[
2
:
0
]
};
else
if
(
clear_bsy_drq
||
set_bsy
)
tf_err_sts
<=
tf_err_sts
&
{
8'hff
,
clear_bsy_drq
,
3'h7
,
clear_bsy_drq
,
3'h7
}
|
{
8'h0
,
set_bsy
,
7'h0
};
else
if
(
set_sts_7f
||
set_sts_80
)
tf_err_sts
<=
{
tf_err_sts
[
15
:
8
]
,
set_sts_80
,{
7
{
set_sts_7f
}}}
;
reg_we
<=
reg_we_w
||
update_sig
[
3
]
||
update_err_sts_r
;
reg_we
<=
reg_we_w
||
update_sig
[
3
]
||
update_err_sts
;
if
(
reg_we_w
||
update_sig
[
3
])
reg_addr
<=
reg_addr_r
;
if
(
reg_we_w
||
update_sig
[
3
])
reg_addr
<=
reg_addr_r
;
else
if
(
update_err_sts
)
reg_addr
<=
PXTFD_OFFS32
;
else
if
(
update_err_sts
_r
)
reg_addr
<=
PXTFD_OFFS32
;
if
(
reg_d2h
||
reg_sdb
||
reg_ds
[
0
])
fis_i
<=
hda_data_in
[
14
]
;
if
(
reg_d2h
||
reg_sdb
||
reg_ds
[
0
])
fis_i
<=
hda_data_in
[
14
]
;
if
(
reg_sdb
)
sdb_n
<=
hda_data_in
[
15
]
;
if
(
reg_sdb
)
sdb_n
<=
hda_data_in
[
15
]
;
if
(
reg_ds
[
0
])
{
dma_a
,
dma_d
}
<=
{
hda_data_in
[
15
]
,
hda_data_in
[
13
]
};
if
(
reg_ds
[
0
])
{
dma_a
,
dma_d
}
<=
{
hda_data_in
[
15
]
,
hda_data_in
[
13
]
};
if
(
reg_ps
[
0
])
{
pio_i
,
pio_d
}
<=
{
hda_data_in
[
14
]
,
hda_data_in
[
13
]
};
if
(
reg_ps
[
0
])
{
pio_i
,
pio_d
}
<=
{
hda_data_in
[
14
]
,
hda_data_in
[
13
]
};
if
(
reg_ps
[
3
])
pio_es
<=
hda_data_in
[
31
:
24
]
;
if
(
hba_rst
)
pio_es
<=
0
;
else
if
(
reg_ps
[
3
])
pio_es
<=
hda_data_in
[
31
:
24
]
;
if
(
reg_ps
[
4
]
||
reg_ds
[
5
])
xfer_cntr
[
31
:
1
]
<=
{
reg_ds
[
5
]
?
hda_data_in
[
31
:
16
]
:
16'b0
,
hda_data_in
[
15
:
1
]
};
if
(
reg_ps
[
4
]
||
reg_ds
[
5
])
xfer_cntr
[
31
:
1
]
<=
{
reg_ds
[
5
]
?
hda_data_in
[
31
:
16
]
:
16'b0
,
hda_data_in
[
15
:
1
]
};
update_err_sts_r
<=
update_err_sts
||
clear_bsy_drq
||
set_bsy
||
set_sts_7f
||
set_sts_80
;
end
end
endmodule
endmodule
utils/ahci_fis_transmit.v
0 → 100644
View file @
f81326a9
/*******************************************************************************
* Module: ahci_fis_transmit
* Date:2016-01-07
* Author: andrey
* Description: Fetches commands, command tables, creates/sends FIS
*
* Copyright (c) 2016 Elphel, Inc .
* ahci_fis_transmit.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.
*
* ahci_fis_transmit.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
1
ns
/
1
ps
module
ahci_fis_transmit
#(
parameter
READ_REG_LATENCY
=
2
// 0 if reg_rdata is available with reg_re/reg_addr
)(
input
hba_rst
,
// @posedge mclk - sync reset
input
mclk
,
// for command/status
input
fetch_chead
,
// fetch command header (from the register memory
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_b
,
// Built-in self test command
output
ch_r
,
// reset - may need to send SYNC escape before this command
output
ch_p
,
// prefetchable - only used with non-zero PRDTL or ATAPI bit set
output
ch_w
,
// Write: system memory -> device
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,
// maximal is 16 (0x10)
output
[
31
:
7
]
ch_ctba
,
// command table base address
// register memory interface
output
reg
[
ADDRESS_BITS
-
1
:
0
]
reg_addr
,
output
reg_re
,
output
reg
[
31
:
0
]
reg_rdata
,
// DMA (memory -> device) interface
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_re
,
// read dword from DMA module to the outpu register
// Data System memory or FIS -> device
output
reg
[
31
:
0
]
todev_data
,
// 32-bit data from the system memory to HBA (dma data)
output
reg
[
1
:
0
]
todev_type
,
// 0 - data, 1 - FIS head, 2 - FIS END (make FIS_Last?)
output
todev_valid
,
// output register full
input
todev_ready
// send FIFO has room for data (>= ? dwords)
// Add a possiblity to flush any data to FIFO if error was detected after data went there?
)
;
localparam
CLB_OFFS32
=
'h200
;
// # In the second half of the register space (0x800..0xbff - 1KB)
reg
todev_full_r
;
reg
dma_en_r
;
wire
fis_data_valid
;
wire
[
1
:
0
]
fis_data_type
;
wire
[
31
:
0
]
fis_data_out
;
wire
write_or_w
=
(
dma_en_r
?
dma_dav
:
fis_data_valid
)
&&
todev_ready
;
// do not fill the buffer if FIFO is not ready
wire
fis_out_w
=
!
dma_en_r
&&
fis_data_valid
&&
todev_ready
;
wire
dma_re_w
=
dma_en_r
&&
dma_dav
&&
todev_ready
;
reg
[
15
:
0
]
ch_prdtl_r
;
reg
ch_c_r
;
reg
ch_b_r
;
reg
ch_r_r
;
reg
ch_p_r
;
reg
ch_w_r
;
reg
ch_a_r
;
reg
[
4
:
0
]
ch_cfl_r
;
reg
[
31
:
7
]
ch_ctba_r
;
reg
[
READ_REG_LATENCY
:
0
]
reg_re_r
;
wire
reg_re_w
;
// combined conditions to read register memory
wire
reg_stb
=
reg_re_r
[
READ_REG_LATENCY
]
;
wire
pre_reg_stb
=
reg_re_r
[
READ_REG_LATENCY
-
1
]
;
reg
[
3
:
0
]
fetch_chead_r
;
reg
[
2
:
0
]
fetch_chead_stb_r
;
reg
chead_bsy
;
// busy reading command header
reg
chead_bsy_re
;
// busy sending read command header
assign
todev_valid
=
todev_full_r
;
assign
dma_re
=
dma_re_w
;
assign
reg_re
=
reg_re_r
[
0
]
;
assign
ch_prdtl
=
ch_prdtl_r
;
assign
ch_c
=
ch_c_r
;
assign
ch_b
=
ch_b_r
;
assign
ch_r
=
ch_r_r
;
assign
ch_p
=
ch_p_r
;
assign
ch_w
=
ch_w_r
;
assign
ch_a
=
ch_a_r
;
assign
ch_cfl
=
ch_cfl_r
;
assign
ch_ctba
=
ch_ctba_r
[
31
:
7
]
;
assign
reg_re_w
=
fetch_chead
||
chead_bsy_re
;
always
@
(
posedge
mclk
)
begin
// Mutliplex between DMA and FIS output to the output routed to transmit FIFO
// Count bypassing DMA dwords to generate FIS_last condition?
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
(
todev_ready
)
todev_full_r
<=
0
;
if
(
write_or_w
)
todev_data
<=
dma_en_r
?
dma_out
:
fis_data_out
;
if
(
hba_rst
)
todev_type
<=
3
;
// invalid?
else
if
(
write_or_w
)
todev_type
<=
dma_en_r
?
2'h0
:
fis_data_type
;
if
(
hba_rst
)
fetch_chead_r
<=
0
;
else
if
(
fetch_chead
)
fetch_chead_r
<=
1
;
else
fetch_chead_r
<=
fetch_chead_r
<<
1
;
if
(
hba_rst
)
fetch_chead_stb_r
<=
0
;
else
if
(
pre_reg_stb
&&
chead_bsy
)
fetch_chead_stb_r
<=
1
;
else
fetch_chead_stb_r
<=
fetch_chead_stb_r
<<
1
;
if
(
hba_rst
)
chead_bsy
<=
0
;
else
if
(
fetch_chead
)
chead_bsy
<=
1
;
else
if
(
fetch_chead_stb_r
[
2
])
chead_bsy
<=
0
;
if
(
hba_rst
)
chead_bsy_re
<=
0
;
else
if
(
fetch_chead
)
chead_bsy_re
<=
1
;
else
if
(
fetch_chead_r
[
1
])
chead_bsy_re
<=
0
;
// read 3 dwords
if
(
hba_rst
)
reg_re_r
<=
0
;
else
if
(
reg_re_w
)
reg_re_r
<=
1
;
else
reg_re_r
<=
reg_re_r
<<
1
;
if
(
fetch_chead
)
reg_addr
<=
CLB_OFFS32
;
// there will be more conditions
else
if
(
reg_re_r
[
0
])
reg_addr
<=
reg_addr
+
1
;
// save command header data to registers
if
(
fetch_chead_stb_r
[
0
])
begin
ch_prdtl_r
<=
reg_rdata
[
31
:
16
]
;
ch_c_r
<=
reg_rdata
[
10
]
;
ch_b_r
<=
reg_rdata
[
9
]
;
ch_r_r
<=
reg_rdata
[
8
]
;
ch_p_r
<=
reg_rdata
[
7
]
;
ch_w_r
<=
reg_rdata
[
6
]
;
ch_a_r
<=
reg_rdata
[
5
]
;
ch_cfl_r
<=
reg_rdata
[
4
:
0
]
;
end
if
(
fetch_chead_stb_r
[
2
])
ch_ctba_r
[
31
:
7
]
<=
reg_rdata
[
31
:
7
]
;
/*
reg [3:0] fetch_chead_r;
reg [3:0] fetch_chead_stb_r;
reg chead_bsy; // busy reading command header
*/
end
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