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
0fd78dc6
Commit
0fd78dc6
authored
Jan 04, 2016
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Working on AHCI DMA module
parent
270a7673
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
218 additions
and
7 deletions
+218
-7
ahci_dma.v
utils/ahci_dma.v
+218
-7
No files found.
utils/ahci_dma.v
View file @
0fd78dc6
...
...
@@ -31,10 +31,17 @@ module ahci_dma (
input
[
31
:
7
]
ctba
,
// command table base address
input
ctba_ld
,
// load command table base address
input
[
15
:
0
]
prdtl
,
// number of entries in PRD table (valid at cmd_start)
input
dev_wr
,
// write to device (valid at start)
input
cmd_start
,
// start processing command table, reset prdbc
input
cmd_abort
,
// try to abort a command
// Some data from the command table will be used internally, data will be available on the general
// sys_out[31:0] port and should be consumed
output
ct_busy
,
// cleared after 0x20 DWORDs are read out
// reading out command table data
input
[
4
:
0
]
ct_addr
,
// DWORD address
input
ct_re
,
//
output
reg
[
31
:
0
]
ct_data
,
//
// After the first 0x80 bytes of the Command Table are read out, this module will read/process PRDs,
// not forwarding them to the output
output
prd_done
,
// prd done (regardless of the interrupt)
...
...
@@ -43,12 +50,12 @@ module ahci_dma (
output
cmd_done
,
// Data System memory -> HBA interface @ mclk
output
[
31
:
0
]
sys_out
,
// 32-bit data from the system memory to HBA
- command table, dma data
output
[
31
:
0
]
sys_out
,
// 32-bit data from the system memory to HBA
(dma data)
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)
//
output sys_dav_many, // several DWORDs are in the FIFO (TODO: decide how many)
input
sys_re
,
// sys_out data read, advance internal FIFO
// Data HBA -> System memory interface @ mclk
output
[
31
:
0
]
sys_out
,
// 32-bit data from the system memory to HBA - command table, dma data
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)
input
sys_we
,
...
...
@@ -83,14 +90,14 @@ module ahci_dma (
output
afi_wrissuecap1en
,
// AXI_HP signals - read channel
// read address
output
[
31
:
0
]
afi_araddr
,
output
reg
[
31
:
0
]
afi_araddr
,
output
afi_arvalid
,
input
afi_arready
,
// @SuppressThisWarning VEditor unused - used FIF0 level
output
[
5
:
0
]
afi_arid
,
output
[
1
:
0
]
afi_arlock
,
output
[
3
:
0
]
afi_arcache
,
output
[
2
:
0
]
afi_arprot
,
output
[
3
:
0
]
afi_arlen
,
output
reg
[
3
:
0
]
afi_arlen
,
output
[
1
:
0
]
afi_arsize
,
output
[
1
:
0
]
afi_arburst
,
output
[
3
:
0
]
afi_arqos
,
...
...
@@ -108,5 +115,209 @@ module ahci_dma (
)
;
// Read command table
// localparam AFI_FIFO_LAT = 2; // >=2
localparam
SAFE_RD_BITS
=
3
;
//2; // 3;
reg
[
31
:
0
]
ct_data_ram
[
0
:
31
]
;
reg
[
3
:
0
]
int_data_addr
;
// internal (ct,prd) data address
reg
[
31
:
7
]
ctba_r
;
reg
[
15
:
0
]
prdtl_mclk
;
wire
cmd_start_hclk
;
wire
cmd_abort_hclk
;
reg
[
31
:
4
]
ct_maddr
;
// granularity matches PRDT entry - 4xDWORD, 2xQWORD
reg
ct_done_r
;
reg
prd_done_r
;
wire
axi_set_raddr_ready
=
!
(
|
afi_racount
[
2
:
1
])
;
// What is the size of ra fifo?
wire
axi_set_raddr_w
;
wire
axi_set_raddr_ct_w
;
// next will be setting address/len/... to read command table
reg
axi_set_raddr_prd
;
// next will be setting address/len/... to read PRD entry
wire
axi_set_raddr_data_w
;
// next will be setting address/len/... to read DATA
reg
axi_set_raddr_r
;
// [0] - actual write address to fifo
reg
was_ct_addr
;
// AXI RD channel was set to read command table
reg
was_prd_addr
;
// AXI RD channel was set to read prd table
reg
[
31
:
1
]
data_addr
;
// 2 lower addresses will be used in in/out fifo modules
reg
[
3
:
0
]
data_len
;
//
reg
data_irq
;
// interrupt at the end of this PRD
reg
[
21
:
1
]
wcount
;
// Word count
reg
wcount_set
;
reg
[
21
:
1
]
qwcount
;
// only [21:3] are used
reg
next_data16
;
// next data r/w address incremented by 16 QWORDS
wire
data_afi_re
;
reg
[
15
:
0
]
prds_left
;
reg
last_prd
;
reg
[
1
:
0
]
afi_rd_ctl
;
// read non-data (CT or PRD)
reg
[
1
:
0
]
ct_busy_r
;
reg
prd_rd_busy
;
// reading PRD
wire
prd_done
;
// data transfer of one PRD is finished (any direction)
reg
dev_wr_mclk
;
reg
dev_wr_hclk
;
reg
prd_wr
;
// write PRD data to memory
reg
prd_rd
;
// read PRD data from memory
wire
[
3
:
0
]
afi_wstb4
;
// reg [1:0] afi_rready_ctl_r;
assign
afi_arvalid
=
axi_set_raddr_r
[
0
]
;
assign
axi_set_raddr_w
=
(
axi_set_raddr_ct_w
||
axi_set_raddr_prd
||
axi_set_raddr_data_w
)
&&
axi_set_raddr_ready
;
assign
afi_rready
=
afi_rd_ctl
[
0
]
||
data_afi_re
;
assign
ct_busy
=
ct_busy_r
[
0
]
;
assign
afi_wstrb
=
{{
2
{
afi_wstb4
[
3
]
}},{
2
{
afi_wstb4
[
2
]
}},{
2
{
afi_wstb4
[
1
]
}},{
2
{
afi_wstb4
[
0
]
}}};
// assign afi_rready = data_afi_re || ((was_ct_addr || was_prd_addr) &&
// ((|afi_rcount[6:SAFE_RD_BITS]) || (afi_rvalid && !afi_rready &&!(|afi_rready_r))));
always
@
(
posedge
mclk
)
begin
if
(
ct_re
)
ct_data
<=
ct_data_ram
[
ct_addr
]
;
if
(
ctba_ld
)
ctba_r
<=
ctba
[
31
:
7
]
;
if
(
cmd_start
)
prdtl_mclk
<=
prdtl
;
if
(
cmd_start
)
dev_wr_mclk
<=
dev_wr
;
end
always
@
(
posedge
hclk
)
begin
if
(
cmd_start_hclk
)
ct_maddr
[
31
:
4
]
<=
{
ctba_r
[
31
:
7
]
,
3'b0
};
else
if
(
ct_done_r
)
ct_maddr
[
31
:
4
]
<=
ct_maddr
[
31
:
4
]
+
16
;
else
if
(
prd_done_r
)
ct_maddr
[
31
:
4
]
<=
ct_maddr
[
31
:
4
]
+
1
;
if
(
hrst
)
axi_set_raddr_r
<=
0
;
else
axi_set_raddr_r
<=
axi_set_raddr_w
;
if
(
axi_set_raddr_w
)
begin
was_ct_addr
<=
axi_set_raddr_ct_w
;
was_prd_addr
<=
axi_set_raddr_prd
;
end
if
(
cmd_start_hclk
)
prds_left
<=
prdtl_mclk
;
else
if
(
axi_set_raddr_r
&&
was_prd_addr
)
prds_left
<=
prds_left
-
1
;
if
(
axi_set_raddr_r
&&
was_prd_addr
)
last_prd
<=
prds_left
==
1
;
if
(
axi_set_raddr_r
)
begin
if
(
was_ct_addr
||
was_prd_addr
)
afi_araddr
<=
{
ct_maddr
[
31
:
4
]
,
4'b0
};
else
afi_araddr
<=
{
data_addr
[
31
:
3
]
,
3'b0
};
if
(
was_ct_addr
)
afi_arlen
<=
4'hf
;
// 16 QWORDS
else
if
(
was_prd_addr
)
afi_arlen
<=
4'h1
;
// 2 QWORDS
else
afi_arlen
<=
data_len
;
// TBD - all but last are 4'hf
end
if
(
axi_set_raddr_r
)
int_data_addr
<=
0
;
// && (was_ct_addr || was_prd_addr))
else
if
(
afi_rd_ctl
[
0
]
&&
(
was_ct_addr
||
was_prd_addr
))
int_data_addr
<=
int_data_addr
+
1
;
if
(
afi_rd_ctl
[
0
]
&&
was_ct_addr
)
{
ct_data_ram
[
{
int_data_addr
,
1'b1
}
]
,
ct_data_ram
[
{
int_data_addr
,
1'b0
}
]
}
<=
afi_rdata
;
// make sure it is synthesized correctly
if
(
hrst
)
ct_busy_r
[
0
]
<=
0
;
else
if
(
cmd_start_hclk
)
ct_busy_r
[
0
]
<=
1
;
else
if
(
afi_rd_ctl
[
0
]
&&
was_ct_addr
&&
(
&
int_data_addr
))
ct_busy_r
[
0
]
<=
0
;
ct_busy_r
[
1
]
<=
ct_busy_r
[
0
]
;
// delayed version to detect end of command
if
(
hrst
)
prd_rd_busy
<=
0
;
else
if
(
prd_rd_busy
)
prd_rd_busy
<=
1
;
else
if
(
wcount_set
)
prd_rd_busy
<=
0
;
// start PRD read
if
(
hrst
)
axi_set_raddr_prd
<=
0
;
else
axi_set_raddr_prd
<=
((
|
prds_left
)
&&
((
ct_busy_r
==
2'b10
)
||
prd_done
))
;
// store data address from PRD
if
(
afi_rd_ctl
[
0
]
&&
was_prd_addr
&&
(
!
int_data_addr
[
0
]))
data_addr
[
31
:
1
]
<=
afi_rdata
[
31
:
1
]
;
else
if
(
next_data16
)
data_addr
[
31
:
7
]
<=
data_addr
[
31
:
7
]
+
1
;
// add 64 bytes to address, keep low bits
if
(
afi_rd_ctl
[
0
]
&&
was_prd_addr
&&
(
int_data_addr
[
0
]))
data_irq
<=
afi_rdata
[
63
]
;
if
(
afi_rd_ctl
[
0
]
&&
was_prd_addr
&&
(
int_data_addr
[
0
]))
wcount
[
21
:
1
]
<=
afi_rdata
[
37
:
17
]
;
wcount_set
<=
afi_rd_ctl
[
0
]
&&
was_prd_addr
&&
(
int_data_addr
[
0
])
;
if
(
wcount_set
)
qwcount
[
21
:
1
]
<=
wcount
[
21
:
1
]
+
data_addr
[
2
:
1
]
;
if
(
cmd_start_hclk
)
dev_wr_hclk
<=
dev_wr_mclk
;
// 1: memory -> device, 0: device -> memory
prd_wr
<=
wcount_set
&&
!
dev_wr_hclk
;
prd_rd
<=
wcount_set
&&
dev_wr_hclk
;
afi_rd_ctl
<=
{
afi_rd_ctl
[
0
]
,
(
ct_busy_r
[
0
]
||
prd_rd_busy
)
&&
((
|
afi_rcount
[
7
:
SAFE_RD_BITS
])
||
(
afi_rvalid
&&
!
(
|
afi_rd_ctl
)))
};
end
ahci_dma_rd_fifo
#(
// memory to device
.
WCNT_BITS
(
21
)
,
.
ADDRESS_BITS
(
3
)
)
ahci_dma_rd_fifo_i
(
.
mrst
(
mrst
)
,
// input
.
hrst
(
hrst
)
,
// input
.
mclk
(
mclk
)
,
// input
.
hclk
(
hclk
)
,
// input
.
wcnt
(
wcount
[
21
:
1
])
,
// input[20:0]
.
woffs
(
data_addr
[
2
:
1
])
,
// input[1:0]
.
start
(
prd_rd
)
,
// input
.
din
(
afi_rdata
)
,
// input[63:0]
.
din_av
(
afi_rvalid
)
,
// input
.
din_av_many
(
|
afi_rcount
[
7
:
SAFE_RD_BITS
])
,
// input
.
last_prd
(
last_prd
)
,
// input
.
din_re
(
data_afi_re
)
,
// output
.
done
()
,
// output reg
.
done_flush
()
,
// output
.
dout
(
sys_out
)
,
// output[31:0]
.
dout_vld
(
sys_dav
)
,
// output
.
dout_re
(
sys_re
)
// input
)
;
ahci_dma_wr_fifo
#(
// device to memory
.
WCNT_BITS
(
21
)
,
.
ADDRESS_BITS
(
3
)
)
ahci_dma_wr_fifo_i
(
.
mrst
(
mrst
)
,
// input
.
hrst
(
hrst
)
,
// input
.
mclk
(
mclk
)
,
// input
.
hclk
(
hclk
)
,
// input
.
wcnt
(
wcount
[
21
:
1
])
,
// input[20:0]
.
woffs
(
data_addr
[
2
:
1
])
,
// input[1:0]
.
init
(
cmd_start_hclk
)
,
// input
.
start
(
prd_wr
)
,
// input
.
dout
(
afi_wdata
)
,
// output[63:0] reg
.
dout_av
()
,
// input
.
dout_av_many
()
,
// input
.
last_prd
(
last_prd
)
,
// input
.
dout_we
(
afi_wvalid
)
,
// output
.
dout_wstb
(
afi_wstb4
)
,
// output[3:0] reg
.
done
()
,
// output reg
.
busy
()
,
// output
.
din
(
sys_in
)
,
// input[31:0]
.
din_rdy
(
sys_nfull
)
,
// output
.
din_avail
(
sys_we
)
// input
)
;
// mclk -> hclk cross-clock synchronization
pulse_cross_clock
#(
.
EXTRA_DLY
(
0
)
)
cmd_start_hclk_i
(
.
rst
(
mrst
)
,
// input
.
src_clk
(
mclk
)
,
// input
.
dst_clk
(
hclk
)
,
// input
.
in_pulse
(
cmd_start
)
,
// input
.
out_pulse
(
cmd_start_hclk
)
,
// output
.
busy
()
// output
)
;
pulse_cross_clock
#(
.
EXTRA_DLY
(
0
)
)
cmd_abort_hclk_i
(
.
rst
(
mrst
)
,
// input
.
src_clk
(
mclk
)
,
// input
.
dst_clk
(
hclk
)
,
// input
.
in_pulse
(
cmd_abort
)
,
// input
.
out_pulse
(
cmd_abort_hclk
)
,
// output
.
busy
()
// output
)
;
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