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
9c004cf3
Commit
9c004cf3
authored
Jan 04, 2016
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
more code in ahci_dma.v
parent
0fd78dc6
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
81 additions
and
26 deletions
+81
-26
ahci_dma.v
utils/ahci_dma.v
+81
-26
No files found.
utils/ahci_dma.v
View file @
9c004cf3
...
@@ -36,7 +36,7 @@ module ahci_dma (
...
@@ -36,7 +36,7 @@ module ahci_dma (
input
cmd_abort
,
// try to abort a command
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
// 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
// sys_out[31:0] port and should be consumed
output
ct_busy
,
// cleared after 0x20 DWORDs are read out
output
reg
ct_busy
,
// cleared after 0x20 DWORDs are read out
// reading out command table data
// reading out command table data
input
[
4
:
0
]
ct_addr
,
// DWORD address
input
[
4
:
0
]
ct_addr
,
// DWORD address
input
ct_re
,
//
input
ct_re
,
//
...
@@ -44,9 +44,10 @@ module ahci_dma (
...
@@ -44,9 +44,10 @@ module ahci_dma (
// After the first 0x80 bytes of the Command Table are read out, this module will read/process PRDs,
// After the first 0x80 bytes of the Command Table are read out, this module will read/process PRDs,
// not forwarding them to the output
// not forwarding them to the output
output
prd_done
,
// prd done (regardless of the interrupt)
output
prd_done
,
// prd done (regardless of the interrupt) - data transfer of one PRD is finished (any direction)
output
prd_irq
,
// prd interrupt, if enabled
output
prd_irq
,
// prd interrupt, if enabled
output
cmd_busy
,
// all command
output
reg
cmd_busy
,
// all commands
output
cmd_done
,
output
cmd_done
,
// Data System memory -> HBA interface @ mclk
// Data System memory -> HBA interface @ mclk
...
@@ -90,7 +91,7 @@ module ahci_dma (
...
@@ -90,7 +91,7 @@ module ahci_dma (
output
afi_wrissuecap1en
,
output
afi_wrissuecap1en
,
// AXI_HP signals - read channel
// AXI_HP signals - read channel
// read address
// read address
output
reg
[
31
:
0
]
afi_araddr
,
output
[
31
:
0
]
afi_araddr
,
output
afi_arvalid
,
output
afi_arvalid
,
input
afi_arready
,
// @SuppressThisWarning VEditor unused - used FIF0 level
input
afi_arready
,
// @SuppressThisWarning VEditor unused - used FIF0 level
output
[
5
:
0
]
afi_arid
,
output
[
5
:
0
]
afi_arid
,
...
@@ -126,14 +127,16 @@ module ahci_dma (
...
@@ -126,14 +127,16 @@ module ahci_dma (
wire
cmd_start_hclk
;
wire
cmd_start_hclk
;
wire
cmd_abort_hclk
;
wire
cmd_abort_hclk
;
reg
[
31
:
4
]
ct_maddr
;
// granularity matches PRDT entry - 4xDWORD, 2xQWORD
reg
[
31
:
4
]
ct_maddr
;
// granularity matches PRDT entry - 4xDWORD, 2xQWORD
reg
ct_done_r
;
wire
ct_done
;
reg
prd_done_r
;
reg
[
31
:
0
]
afi_addr
;
// common for afi_araddr and afi_awaddr
wire
axi_set_raddr_ready
=
!
(
|
afi_racount
[
2
:
1
])
;
// What is the size of ra fifo?
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_w
;
wire
axi_set_waddr_w
;
wire
axi_set_raddr_ct_w
;
// next will be setting address/len/... to read command table
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
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
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
axi_set_raddr_r
;
// [0] - actual write address to fifo
reg
axi_set_waddr_r
;
// [0] - actual write address to fifo
reg
was_ct_addr
;
// AXI RD channel was set to read command table
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
was_prd_addr
;
// AXI RD channel was set to read prd table
...
@@ -153,41 +156,61 @@ module ahci_dma (
...
@@ -153,41 +156,61 @@ module ahci_dma (
reg
[
1
:
0
]
ct_busy_r
;
reg
[
1
:
0
]
ct_busy_r
;
reg
prd_rd_busy
;
// reading PRD
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_mclk
;
reg
dev_wr_hclk
;
reg
dev_wr_hclk
;
reg
prd_wr
;
// write PRD data to memory
reg
prd_wr
;
// write PRD data to memory
reg
prd_rd
;
// read PRD data from memory
reg
prd_rd
;
// read PRD data from memory
wire
[
3
:
0
]
afi_wstb4
;
wire
[
3
:
0
]
afi_wstb4
;
// reg [1:0] afi_rready_ctl_r;
assign
afi_arvalid
=
axi_set_raddr_r
[
0
]
;
wire
done_dev_wr
;
// finished PRD mem -> device
wire
done_dev_rd
;
// finished PRD device -> mem
wire
done_flush
;
// done flushing last partial dword
wire
cmd_done_hclk
;
wire
ct_done_mclk
;
assign
afi_arvalid
=
axi_set_raddr_r
;
assign
afi_awvalid
=
axi_set_waddr_r
;
assign
axi_set_raddr_w
=
(
axi_set_raddr_ct_w
||
axi_set_raddr_prd
||
axi_set_raddr_data_w
)
&&
axi_set_raddr_ready
;
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
afi_rready
=
afi_rd_ctl
[
0
]
||
data_afi_re
;
assign
ct_busy
=
ct_busy_r
[
0
]
;
//
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_wstrb
=
{{
2
{
afi_wstb4
[
3
]
}},{
2
{
afi_wstb4
[
2
]
}},{
2
{
afi_wstb4
[
1
]
}},{
2
{
afi_wstb4
[
0
]
}}};
assign
prd_done
=
done_dev_wr
||
done_dev_rd
;
// assign afi_rready = data_afi_re || ((was_ct_addr || was_prd_addr) &&
assign
prd_irq
=
data_irq
&&
prd_done
;
// ((|afi_rcount[6:SAFE_RD_BITS]) || (afi_rvalid && !afi_rready &&!(|afi_rready_r))));
assign
cmd_done_hclk
=
((
ct_busy_r
==
2'b10
)
&&
(
prdtl_mclk
==
0
))
||
done_flush
||
done_dev_rd
;
assign
ct_done
=
(
ct_busy_r
==
2'b10
)
;
assign
afi_awaddr
=
afi_addr
;
assign
afi_araddr
=
afi_addr
;
always
@
(
posedge
mclk
)
begin
always
@
(
posedge
mclk
)
begin
if
(
ct_re
)
ct_data
<=
ct_data_ram
[
ct_addr
]
;
if
(
ct_re
)
ct_data
<=
ct_data_ram
[
ct_addr
]
;
if
(
ctba_ld
)
ctba_r
<=
ctba
[
31
:
7
]
;
if
(
ctba_ld
)
ctba_r
<=
ctba
[
31
:
7
]
;
if
(
cmd_start
)
prdtl_mclk
<=
prdtl
;
if
(
cmd_start
)
prdtl_mclk
<=
prdtl
;
if
(
cmd_start
)
dev_wr_mclk
<=
dev_wr
;
if
(
cmd_start
)
dev_wr_mclk
<=
dev_wr
;
if
(
mrst
)
cmd_busy
<=
0
;
else
if
(
cmd_start
)
cmd_busy
<=
1
;
else
if
(
cmd_done
)
cmd_busy
<=
0
;
if
(
mrst
)
ct_busy
<=
0
;
else
if
(
cmd_start
)
ct_busy
<=
1
;
else
if
(
ct_done_mclk
)
ct_busy
<=
0
;
end
end
always
@
(
posedge
hclk
)
begin
always
@
(
posedge
hclk
)
begin
if
(
cmd_start_hclk
)
ct_maddr
[
31
:
4
]
<=
{
ctba_r
[
31
:
7
]
,
3'b0
};
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
(
ct_done
)
ct_maddr
[
31
:
4
]
<=
ct_maddr
[
31
:
4
]
+
16
;
else
if
(
prd_done_r
)
ct_maddr
[
31
:
4
]
<=
ct_maddr
[
31
:
4
]
+
1
;
else
if
(
wcount_set
)
ct_maddr
[
31
:
4
]
<=
ct_maddr
[
31
:
4
]
+
1
;
if
(
hrst
)
axi_set_raddr_r
<=
0
;
if
(
hrst
)
axi_set_raddr_r
<=
0
;
else
axi_set_raddr_r
<=
axi_set_raddr_w
;
else
axi_set_raddr_r
<=
axi_set_raddr_w
;
if
(
hrst
)
axi_set_waddr_r
<=
0
;
else
axi_set_waddr_r
<=
axi_set_waddr_w
;
if
(
axi_set_raddr_w
)
begin
if
(
axi_set_raddr_w
)
begin
was_ct_addr
<=
axi_set_raddr_ct_w
;
was_ct_addr
<=
axi_set_raddr_ct_w
;
was_prd_addr
<=
axi_set_raddr_prd
;
was_prd_addr
<=
axi_set_raddr_prd
;
...
@@ -198,12 +221,15 @@ module ahci_dma (
...
@@ -198,12 +221,15 @@ module ahci_dma (
if
(
axi_set_raddr_r
&&
was_prd_addr
)
last_prd
<=
prds_left
==
1
;
if
(
axi_set_raddr_r
&&
was_prd_addr
)
last_prd
<=
prds_left
==
1
;
if
(
axi_set_raddr_r
)
begin
if
(
axi_set_raddr_w
||
axi_set_waddr_w
)
begin
if
(
was_ct_addr
||
was_prd_addr
)
afi_araddr
<=
{
ct_maddr
[
31
:
4
]
,
4'b0
};
// if (was_ct_addr || was_prd_addr) afi_addr <= {ct_maddr[31:4],4'b0};
else
afi_araddr
<=
{
data_addr
[
31
:
3
]
,
3'b0
};
if
(
axi_set_raddr_ct_w
||
axi_set_raddr_prd
)
afi_addr
<=
{
ct_maddr
[
31
:
4
]
,
4'b0
};
else
afi_addr
<=
{
data_addr
[
31
:
3
]
,
3'b0
};
if
(
was_ct_addr
)
afi_arlen
<=
4'hf
;
// 16 QWORDS
// if (was_ct_addr) afi_arlen <= 4'hf; // 16 QWORDS
else
if
(
was_prd_addr
)
afi_arlen
<=
4'h1
;
// 2 QWORDS
// else if (was_prd_addr) afi_arlen <= 4'h1; // 2 QWORDS
if
(
axi_set_raddr_ct_w
)
afi_arlen
<=
4'hf
;
// 16 QWORDS
else
if
(
axi_set_raddr_prd
)
afi_arlen
<=
4'h1
;
// 2 QWORDS
else
afi_arlen
<=
data_len
;
// TBD - all but last are 4'hf
else
afi_arlen
<=
data_len
;
// TBD - all but last are 4'hf
end
end
...
@@ -225,7 +251,7 @@ module ahci_dma (
...
@@ -225,7 +251,7 @@ module ahci_dma (
// start PRD read
// start PRD read
if
(
hrst
)
axi_set_raddr_prd
<=
0
;
if
(
hrst
)
axi_set_raddr_prd
<=
0
;
else
axi_set_raddr_prd
<=
((
|
prds_left
)
&&
(
(
ct_busy_r
==
2'b10
)
||
prd_done
))
;
else
axi_set_raddr_prd
<=
((
|
prds_left
)
&&
(
ct_done
||
prd_done
))
;
// store data address from PRD
// 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
]
;
if
(
afi_rd_ctl
[
0
]
&&
was_prd_addr
&&
(
!
int_data_addr
[
0
]))
data_addr
[
31
:
1
]
<=
afi_rdata
[
31
:
1
]
;
...
@@ -248,6 +274,12 @@ module ahci_dma (
...
@@ -248,6 +274,12 @@ module ahci_dma (
end
end
// TODO: Push addresses for Data read/data Write (different address FIFO depth), use IDs
// - different for commands (increment for each next command) and data (increment for each PRD) - not really needed, just for debugging
// Generate afi_wlast - each 16-th and the very last QWORD
ahci_dma_rd_fifo
#(
// memory to device
ahci_dma_rd_fifo
#(
// memory to device
.
WCNT_BITS
(
21
)
,
.
WCNT_BITS
(
21
)
,
.
ADDRESS_BITS
(
3
)
.
ADDRESS_BITS
(
3
)
...
@@ -264,8 +296,8 @@ module ahci_dma (
...
@@ -264,8 +296,8 @@ module ahci_dma (
.
din_av_many
(
|
afi_rcount
[
7
:
SAFE_RD_BITS
])
,
// input
.
din_av_many
(
|
afi_rcount
[
7
:
SAFE_RD_BITS
])
,
// input
.
last_prd
(
last_prd
)
,
// input
.
last_prd
(
last_prd
)
,
// input
.
din_re
(
data_afi_re
)
,
// output
.
din_re
(
data_afi_re
)
,
// output
.
done
(
)
,
// output reg
.
done
(
done_dev_wr
)
,
// output reg
.
done_flush
(
)
,
// output
.
done_flush
(
done_flush
)
,
// output
.
dout
(
sys_out
)
,
// output[31:0]
.
dout
(
sys_out
)
,
// output[31:0]
.
dout_vld
(
sys_dav
)
,
// output
.
dout_vld
(
sys_dav
)
,
// output
.
dout_re
(
sys_re
)
// input
.
dout_re
(
sys_re
)
// input
...
@@ -289,13 +321,14 @@ module ahci_dma (
...
@@ -289,13 +321,14 @@ module ahci_dma (
.
last_prd
(
last_prd
)
,
// input
.
last_prd
(
last_prd
)
,
// input
.
dout_we
(
afi_wvalid
)
,
// output
.
dout_we
(
afi_wvalid
)
,
// output
.
dout_wstb
(
afi_wstb4
)
,
// output[3:0] reg
.
dout_wstb
(
afi_wstb4
)
,
// output[3:0] reg
.
done
()
,
// output reg
.
done
(
done_dev_rd
)
,
// output reg
.
busy
()
,
// output
.
busy
()
,
// output
.
din
(
sys_in
)
,
// input[31:0]
.
din
(
sys_in
)
,
// input[31:0]
.
din_rdy
(
sys_nfull
)
,
// output
.
din_rdy
(
sys_nfull
)
,
// output
.
din_avail
(
sys_we
)
// input
.
din_avail
(
sys_we
)
// input
)
;
)
;
// mclk -> hclk cross-clock synchronization
// mclk -> hclk cross-clock synchronization
pulse_cross_clock
#(
pulse_cross_clock
#(
.
EXTRA_DLY
(
0
)
.
EXTRA_DLY
(
0
)
...
@@ -318,6 +351,28 @@ module ahci_dma (
...
@@ -318,6 +351,28 @@ module ahci_dma (
.
busy
()
// output
.
busy
()
// output
)
;
)
;
// hclk -> mclk;
pulse_cross_clock
#(
.
EXTRA_DLY
(
0
)
)
cmd_done_i
(
.
rst
(
hrst
)
,
// input
.
src_clk
(
hclk
)
,
// input
.
dst_clk
(
mclk
)
,
// input
.
in_pulse
(
cmd_done_hclk
)
,
// input
.
out_pulse
(
cmd_done
)
,
// output
.
busy
()
// output
)
;
pulse_cross_clock
#(
.
EXTRA_DLY
(
0
)
)
ct_done_mclk_i
(
.
rst
(
hrst
)
,
// input
.
src_clk
(
hclk
)
,
// input
.
dst_clk
(
mclk
)
,
// input
.
in_pulse
(
ct_done
)
,
// input
.
out_pulse
(
ct_done_mclk
)
,
// output
.
busy
()
// output
)
;
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