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
e151f409
Commit
e151f409
authored
Jan 27, 2016
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
verified/fixed multi-prd, non-aligned (start and length) receive buffer
parent
45736d4f
Changes
3
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
270 additions
and
96 deletions
+270
-96
ahci_dma.v
ahci/ahci_dma.v
+14
-8
tb_ahci.tf
tb/tb_ahci.tf
+91
-5
tb_ahci_01.sav
tb_ahci_01.sav
+165
-83
No files found.
ahci/ahci_dma.v
View file @
e151f409
...
...
@@ -200,6 +200,7 @@ module ahci_dma (
wire
done_dev_wr
;
// finished PRD mem -> device
wire
done_dev_rd
;
// finished PRD device -> mem
wire
prd_done_hclk
=
done_dev_wr
||
done_dev_rd
;
wire
done_flush
;
// done flushing last partial dword
wire
cmd_done_hclk
;
wire
ct_done_mclk
;
...
...
@@ -209,7 +210,7 @@ module ahci_dma (
reg
data_next_burst
;
// wire raddr_prd_rq = (|prds_left) && (ct_done || prd_done);
wire
raddr_prd_rq
=
(
|
prds_left
)
&&
(
first_prd_fetch
||
prd_done
)
;
wire
raddr_prd_rq
=
(
|
prds_left
)
&&
(
first_prd_fetch
||
prd_done
_hclk
)
;
reg
raddr_prd_pend
;
...
...
@@ -244,7 +245,7 @@ module ahci_dma (
// assign prd_done = done_dev_wr || done_dev_rd;
assign
cmd_done_hclk
=
((
ct_busy_r
==
2'b10
)
&&
(
prdtl_mclk
==
0
))
||
done_flush
||
done_dev_rd
;
assign
cmd_done_hclk
=
((
ct_busy_r
==
2'b10
)
&&
(
prdtl_mclk
==
0
))
||
((
done_flush
||
done_dev_rd
)
&&
last_prd
)
;
assign
ct_done
=
(
ct_busy_r
==
2'b10
)
;
assign
first_prd_fetch
=
ct_over_prd_enabled
==
2'b01
;
assign
axi_set_raddr_w
=
axi_set_raddr_ready
&&
(
raddr_ct_pend
||
raddr_prd_pend
||
raddr_data_pend
)
;
...
...
@@ -291,7 +292,9 @@ module ahci_dma (
if
(
ct_re
[
1
])
ct_data
<=
ct_data_reg
;
if
(
ctba_ld
)
ctba_r
<=
ctba
[
31
:
7
]
;
if
(
cmd_start
)
prdtl_mclk
<=
prdtl
;
if
(
cmd_start
)
dev_wr_mclk
<=
dev_wr
;
if
(
mrst
)
cmd_busy
<=
0
;
...
...
@@ -443,14 +446,17 @@ module ahci_dma (
// calculate afi_wlast - it is (qw_datawr_burst == 0), just use register qw_datawr_last
if
(
prd_wr
)
qw_datawr_last
<=
qwcount
[
21
:
3
]
==
0
;
else
if
(
afi_wvalid
)
qw_datawr_last
<=
qw_datawr_burst
==
1
;
/// else if (afi_wvalid) qw_datawr_last <= qw_datawr_burst == 1;
else
if
(
afi_wvalid
)
qw_datawr_last
<=
(
qw_datawr_burst
==
1
)
||
(
qw_datawr_last
&&
!
(
|
qw_datawr_left
[
21
:
3
]))
;
// last case - n*16 + 1 (last burst single)
if
(
prd_wr
)
qw_datawr_burst
<=
(
|
qwcount
[
21
:
7
])
?
4'hf
:
qwcount
[
6
:
3
]
;
else
if
(
afi_wvalid
&&
qw_datawr_last
&&
(
qw_datawr_left
[
21
:
7
]
==
0
))
qw_datawr_burst
<=
qw_datawr_left
[
6
:
3
]
;
// if not last roll over to 'hf
/// else if (afi_wvalid && qw_datawr_last && (qw_datawr_left[21:7] == 0)) qw_datawr_burst <= qw_datawr_left[6:3]; // if not last roll over to 'hf
/// else if (afi_wvalid && (qw_datawr_left[21:7] == 0)) qw_datawr_burst <= qw_datawr_left[6:3]; // if not last roll over to 'hf
else
if
(
afi_wvalid
&&
qw_datawr_last
&&
(
qw_datawr_left
[
21
:
7
]
==
1
))
qw_datawr_burst
<=
qw_datawr_left
[
6
:
3
]
;
// if not last roll over to 'hf
else
if
(
afi_wvalid
)
qw_datawr_burst
<=
qw_datawr_burst
-
1
;
if
(
prd_wr
)
qw_datawr_left
[
21
:
3
]
<=
qwcount
[
21
:
3
]
;
else
if
(
afi_wvalid
&&
qw_datawr_last
)
qw_datawr_left
[
21
:
7
]
<=
qw_datawr_left
[
21
:
7
]
-
1
;
else
if
(
afi_wvalid
&&
qw_datawr_last
)
qw_datawr_left
[
21
:
7
]
<=
qw_datawr_left
[
21
:
7
]
-
1
;
// can go negative - OK?
// Count AXI IDs
if
(
hrst
)
ct_id
<=
0
;
...
...
@@ -581,7 +587,7 @@ module ahci_dma (
.
rst
(
hrst
)
,
// input
.
src_clk
(
hclk
)
,
// input
.
dst_clk
(
mclk
)
,
// input
.
in_pulse
(
done_dev_wr
||
done_dev_rd
)
,
// input
.
in_pulse
(
prd_done_hclk
)
,
// input
.
out_pulse
(
prd_done
)
,
// output
.
busy
()
// output
)
;
...
...
tb/tb_ahci.tf
View file @
e151f409
...
...
@@ -692,7 +692,7 @@ localparam ATA_IDFY = 'hec; // Identify command
wire
[
31
:
0
]
sysmem_di_high
=
(
{{
8
{
~
afi_sim_wr_stb
[
7
]}}
,
{
8
{
~
afi_sim_wr_stb
[
6
]}}
,
{
8
{
~
afi_sim_wr_stb
[
5
]}}
,
{
8
{
~
afi_sim_wr_stb
[
4
]}}}
&
(
sysmem
[
sysmem_dworda_wr
[
31
:
2
]
+
1
]
^
afi_sim_wr_data
[
63
:
32
]
))
^
afi_sim_wr_data
[
63
:
32
]
;
always
@
(
posedge
HCLK
)
begin
always
@
(
posedge
HCLK
)
if
(
afi_sim_wr_ready
&&
afi_sim_wr_valid
)
begin
if
(|
afi_sim_wr_stb
[
3
:
0
]
)
sysmem
[
sysmem_dworda_wr
[
31
:
2
]
]
<=
sysmem_di_low
;
if
(|
afi_sim_wr_stb
[
7
:
4
]
)
sysmem
[
sysmem_dworda_wr
[
31
:
2
]
+
1
]
<=
sysmem_di_high
;
end
...
...
@@ -716,7 +716,7 @@ localparam ATA_IDFY = 'hec; // Identify command
endtask
task
setup_pio_read_identify_command
;
task
setup_pio_read_identify_command
_simple
;
input
integer
prd_int
;
// [0] - first prd interrupt, ... [31] - 31-st
integer
i
;
begin
...
...
@@ -729,7 +729,7 @@ localparam ATA_IDFY = 'hec; // Identify command
( 0 << 24); // features = 0 ?
// 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
+ 2; // shift by 2 bytes
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
// Setup command header
maxigp1_writep ((CLB_OFFS32 + 0) << 2, (5 << 0) | // '
CFL
' - number of DWORDs in thes CFIS
...
...
@@ -747,6 +747,89 @@ localparam ATA_IDFY = 'hec; // Identify command
// relax and enjoy
end
endtask
task setup_pio_read_identify_command_shifted;
input integer prd_int; // [0] - first prd interrupt, ... [31] - 31-st
integer i;
begin
// 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_IDFY << 16) | // Command = 0xEC (IDFY)
( 0 << 24); // features = 0 ?
// 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 + 2; // shift by 2 bytes
sysmem[((COMMAND_TABLE + PRD_OFFSET) >> 2) + 3] = (prd_int[0] << 32) | 511; // 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
(0 << 6) | // 'W' Not 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
(1 << 16)); // 'PRDTL' - number of PRDT entries (just one)
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
task setup_pio_read_identify_command_multi4;
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_IDFY << 16) | // Command = 0xEC (IDFY)
( 0 << 24); // features = 0 ?
// All other 4 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
(0 << 6) | // 'W' Not 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
...
...
@@ -812,7 +895,9 @@ initial begin //Host
maxigp1_print (HBA_PORT__PxSSTS__DET__ADDR << 2,"HBA_PORT__PxSSTS__DET__ADDR");
setup_pio_read_identify_command(1); // prdt interrupt for entry 0
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_multi4(1,27,71,83); // 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)
...
...
@@ -823,7 +908,8 @@ initial begin //Host
maxigp1_print (HBA_PORT__PxIS__PSS__ADDR << 2,"HBA_PORT__PxIS__PSS__ADDR");
sysmem_print ('h1e81,'h180);
// sysmem_print ('h1e81,'h180); // for shifted
sysmem_print ('h1e80,'h180);
$finish;
//HBA_PORT__PxIE__DHRE__MASK = 'h1;
...
...
tb_ahci_01.sav
View file @
e151f409
This diff is collapsed.
Click to expand it.
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