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
65abe0b4
Commit
65abe0b4
authored
Aug 04, 2015
by
Alexey Grebenkin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
connected sata host to system ifaces, phy is rewritten. Pre-testing rtl
parent
3153826e
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1849 additions
and
332 deletions
+1849
-332
axi_regs.v
axi_regs.v
+15
-74
dma_adapter.v
dma_adapter.v
+43
-41
dma_control.v
dma_control.v
+206
-43
dma_regs.v
dma_regs.v
+152
-0
sata_host.v
sata_host.v
+42
-4
sata_phy.v
sata_phy.v
+702
-0
sata_top.v
sata_top.v
+532
-0
build
simul/build
+12
-2
tb_top.v
tb/tb_top.v
+9
-0
test_top.v
tb/test_top.v
+16
-7
top.v
top.v
+120
-161
No files found.
axi_regs.v
View file @
65abe0b4
...
...
@@ -2,7 +2,7 @@
* Module: axi_regs
* Date: 2015-07-11
* Author: Alexey
* Description:
temporary registers, connected to axi bus
* Description:
slave axi interface buffer
*
* Copyright (c) 2015 Elphel, Inc.
* axi_regs.v is free software; you can redistribute it and/or modify
...
...
@@ -18,33 +18,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
/*
* Some common formulas for AXI:
* // - integer division, % - leftover
* addr = raddr(waddr) % device_memory_size
* size = arsize(awsize), size_bytes = 2^size, bus_width = log2(bus_width_bytes),
* bus_offset = addr % bus_width_bytes, aligned_bus_addr - address of the first byte on a bus
* word_addr - current memory word's index, word_size_bytes - memory word size
* For the i-th byte on a bus,
* -------burst_cnt = 0:
* aligned_bus_addr = addr // bus_width_bytes * bus_width_bytes
* word_addr[i] = (aligned_bus_addr + i) // word_size_bytes
* word_data[i] = mem[word_addr[i]]
* >data[i] = word_data[i][i % word_size]
* >atrobe[i] = i[bus_width:size] == bus_offset[bus_width:size] & i[size-1:0] >= bus_offset[size-1:0]
* -------burst_cnt > 0:
* let addr_-1 be an addr of a last burst
* Incremental
* addr = addr_-1 // size_bytes * size_bytes + size_bytes
*
* Wrapping
* addr = addr_-1 // size_bytes * size_bytes + size_bytes
*/
`include
"axibram_read.v"
`include
"axibram_write.v"
`include
"membridge.v"
module
axi_regs
(
module
axi_regs
#(
parameter
REGISTERS_CNT
=
20
)
(
input
wire
ACLK
,
// AXI PS Master GP1 Clock , input
input
wire
ARESETN
,
// AXI PS Master GP1 Reset, output
// AXI PS Master GP1: Read Address
...
...
@@ -90,57 +69,19 @@ module axi_regs(
input
wire
BREADY
,
// AXI PS Master GP1 BREADY, output
output
wire
[
11
:
0
]
BID
,
// AXI PS Master GP1 BID[11:0], input
output
wire
[
1
:
0
]
BRESP
,
// AXI PS Master GP1 BRESP[1:0], input
// registers iface
input
wire
[
31
:
0
]
bram_rdata
,
output
wire
[
31
:
0
]
bram_waddr
,
output
wire
[
31
:
0
]
bram_wdata
,
output
wire
[
31
:
0
]
bram_raddr
,
output
wire
[
3
:
0
]
bram_wstb
,
output
wire
bram_wen
,
output
wire
bram_ren
,
output
wire
bram_regen
)
;
// register set
//reg [31:0] mem [3:0];
/*
* DMA write:
* 0x10: addr of the buffer
* 0x14: size
* 0x18: burst len
* 0x1c:
* 0x20-0x3c - data
* Converntional MAXI interface from x393 project
*/
reg
[
32
*
REGISTERS_CNT
-
1
:
0
]
mem
;
/*
* Converntional MAXI interface from x393 project, uses fifos, writes to/reads from memory
*/
wire
[
31
:
0
]
bram_waddr
;
wire
[
31
:
0
]
bram_raddr
;
wire
[
31
:
0
]
bram_wdata
;
wire
[
31
:
0
]
bram_rdata
;
wire
[
3
:
0
]
bram_wstb
;
wire
bram_wen
;
wire
bram_ren
;
wire
bram_regen
;
// 'write into memory'
// for testing purposes the 'memory' is a set of registers for now
// later on will try to use them as an application level registers
genvar
ii
;
generate
for
(
ii
=
0
;
ii
<
REGISTERS_CNT
;
ii
=
ii
+
1
)
begin:
write_to_mem
always
@
(
posedge
ACLK
)
begin
mem
[
32
*
ii
+
31
-:
8
]
<=
bram_wen
&
(
bram_waddr
[
3
:
0
]
==
ii
)
?
bram_wdata
[
31
-:
8
]
&
{
8
{
bram_wstb
[
3
]
}}:
mem
[
32
*
ii
+
31
-:
8
]
;
mem
[
32
*
ii
+
23
-:
8
]
<=
bram_wen
&
(
bram_waddr
[
3
:
0
]
==
ii
)
?
bram_wdata
[
23
-:
8
]
&
{
8
{
bram_wstb
[
2
]
}}:
mem
[
32
*
ii
+
23
-:
8
]
;
mem
[
32
*
ii
+
15
-:
8
]
<=
bram_wen
&
(
bram_waddr
[
3
:
0
]
==
ii
)
?
bram_wdata
[
15
-:
8
]
&
{
8
{
bram_wstb
[
1
]
}}:
mem
[
32
*
ii
+
15
-:
8
]
;
mem
[
32
*
ii
+
7
-:
8
]
<=
bram_wen
&
(
bram_waddr
[
3
:
0
]
==
ii
)
?
bram_wdata
[
7
-:
8
]
&
{
8
{
bram_wstb
[
0
]
}}:
mem
[
32
*
ii
+
7
-:
8
]
;
end
end
endgenerate
// read from memory. Interface's protocol assumes returning data to delay
reg
[
3
:
0
]
bram_raddr_r
;
reg
[
31
:
0
]
bram_rdata_r
;
always
@
(
posedge
ACLK
)
begin
bram_raddr_r
<=
bram_ren
?
bram_raddr
[
3
:
0
]
:
bram_raddr_r
;
bram_rdata_r
<=
bram_regen
?
mem
[
32
*
bram_raddr_r
+
31
-:
32
]
:
bram_rdata_r
;
end
assign
bram_rdata
=
bram_rdata_r
;
// Interface's instantiation
axibram_write
#(
.
ADDRESS_BITS
(
16
)
...
...
dma_adapter.v
View file @
65abe0b4
...
...
@@ -129,11 +129,12 @@ reg rd_reset_page;
reg
rd_next_page
;
reg
rd_data
;
reg
[
6
:
0
]
rd_data_count
;
reg
rd_en
;
wire
rd_stop
;
wire
rd_cnt_to_pull
;
assign
rd_cnt_to_pull
=
=
7'hf
;
assign
rd_cnt_to_pull
=
7'hf
;
assign
rd_stop
=
rd_ack_in
&
rd_data_count
==
rd_cnt_to_pull
;
assign
rd_data_out
=
rd_data
;
...
...
@@ -148,39 +149,40 @@ always @ (posedge clk)
rd_en
<=
1'b0
;
end
else
case
(
rst
)
READ_IDLE:
begin
rdwr_state
<=
rd_start
?
READ_WAIT_ADDR
:
READ_IDLE
;
rd_done
<=
1'b0
;
rd_data_count
<=
7'h0
;
rd_next_page
<=
1'b0
;
rd_en
<=
1'b0
;
end
READ_WAIT_ADDR:
// wait until address information is sent to the bus and input buffer got data
begin
rdwr_state
<=
membr_state
==
IDLE
&
rdata_done
?
READ_DATA
:
READ_WAIT_ADDR
;
rd_done
<=
1'b0
;
rd_data_count
<=
7'h0
;
rd_next_page
<=
1'b0
;
rd_en
<=
1'b0
;
end
READ_DATA:
begin
rdwr_state
<=
rd_stop
?
READ_IDLE
:
READ_DATA
;
rd_done
<=
rd_stop
?
1'b1
:
1'b0
;
rd_data_count
<=
rd_ack_in
?
rd_data_count
+
1'b1
:
rd_data_count
;
rd_next_page
<=
rd_stop
?
1'b1
:
1'b0
;
rd_en
<=
rd_ack_in
?
1'b1
:
1'b0
;
end
default:
// write is processing
begin
rdwr_state
<=
READ_IDLE
;
rd_done
<=
1'b0
;
rd_data_count
<=
7'h0
;
rd_next_page
<=
1'b0
;
rd_en
<=
1'b0
;
end
case
(
rdwr_state
)
READ_IDLE:
begin
rdwr_state
<=
rd_start
?
READ_WAIT_ADDR
:
READ_IDLE
;
rd_done
<=
1'b0
;
rd_data_count
<=
7'h0
;
rd_next_page
<=
1'b0
;
rd_en
<=
1'b0
;
end
READ_WAIT_ADDR:
// wait until address information is sent to the bus and input buffer got data
begin
rdwr_state
<=
membr_state
==
READ_IDLE
&
rdata_done
?
READ_DATA
:
READ_WAIT_ADDR
;
rd_done
<=
1'b0
;
rd_data_count
<=
7'h0
;
rd_next_page
<=
1'b0
;
rd_en
<=
1'b0
;
end
READ_DATA:
begin
rdwr_state
<=
rd_stop
?
READ_IDLE
:
READ_DATA
;
rd_done
<=
rd_stop
?
1'b1
:
1'b0
;
rd_data_count
<=
rd_ack_in
?
rd_data_count
+
1'b1
:
rd_data_count
;
rd_next_page
<=
rd_stop
?
1'b1
:
1'b0
;
rd_en
<=
rd_ack_in
?
1'b1
:
1'b0
;
end
default:
// write is processing
begin
rdwr_state
<=
READ_IDLE
;
rd_done
<=
1'b0
;
rd_data_count
<=
7'h0
;
rd_next_page
<=
1'b0
;
rd_en
<=
1'b0
;
end
endcase
// Put data into buffer
...
...
@@ -220,7 +222,7 @@ always @ (posedge clk)
rdwr_state
<=
WRITE_IDLE
;
end
else
case
(
wr_state
)
case
(
rd
wr_state
)
WRITE_IDLE:
begin
wr_data_count
<=
7'd0
;
...
...
@@ -234,26 +236,26 @@ always @ (posedge clk)
end
WRITE_DATA:
begin
wr_done
<=
wr_stop
&
membr_state
==
IDLE
?
1'b1
:
1'b0
;
wr_done
<=
wr_stop
&
membr_state
==
WRITE_
IDLE
?
1'b1
:
1'b0
;
wr_data_count
<=
wr_val_in
?
wr_data_count
+
1'b1
:
wr_data_count
;
wr_data
<=
in_data
:
wr_data
<=
wr_data_in
;
wr_next_page
<=
wr_stop
?
1'b1
:
1'b0
;
wr_reset_page
<=
1'b0
;
wr_en
<=
wr_val_in
;
wr_page_ready
<=
wr_stop
?
1'b1
:
1'b0
;
rdwr_state
<=
wr_stop
&
membr_state
==
IDLE
?
WRITE_IDLE
:
rdwr_state
<=
wr_stop
&
membr_state
==
WRITE_
IDLE
?
WRITE_IDLE
:
wr_stop
?
WRITE_WAIT_ADDR
:
WRITE_DATA
;
end
WRITE_WAIT_ADDR:
// in case all data is written into a buffer, but address is still being issued on axi bus
begin
wr_done
<=
membr_state
==
IDLE
?
1'b1
:
1'b0
;
wr_done
<=
membr_state
==
WRITE_
IDLE
?
1'b1
:
1'b0
;
wr_data_count
<=
7'd0
;
wr_data
<=
64'h0
;
wr_next_page
<=
1'b0
;
wr_reset_page
<=
1'b0
;
wr_en
<=
1'b0
;
wr_page_ready
<=
1'b0
;
rdwr_state
<=
membr_state
==
IDLE
?
WRITE_IDLE
:
WRITE_WAIT_ADDR
;
rdwr_state
<=
membr_state
==
WRITE_
IDLE
?
WRITE_IDLE
:
WRITE_WAIT_ADDR
;
end
default:
// read is executed
begin
...
...
@@ -322,7 +324,7 @@ always @ (posedge clk)
membr_start
<=
dma_start
?
1'b1
:
1'b0
;
membr_setup
<=
dma_start
?
1'b1
:
1'b0
;
membr_done
<=
1'b0
;
membr_state
<=
dma_start
&
membr_is_set
?
MEMBR_LOADD
D
R
:
membr_state
<=
dma_start
&
membr_is_set
?
MEMBR_LOADDR
:
dma_start
?
MEMBR_MODE
:
MEMBR_IDLE
;
end
MEMBR_MODE:
...
...
dma_control.v
View file @
65abe0b4
...
...
@@ -19,43 +19,207 @@
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
/*
* Later on most of address evaluation logic could divided into 2 parts, which
* Later on most of address evaluation logic could
be
divided into 2 parts, which
* could be presented as 2 instances of 1 parameterized module
* + split data and address parts. Didnt do that because not sure if
* virtual channels would be implemented in the future
*/
module
dma_control
(
input
wire
sclk
,
// sata clock
input
wire
hclk
,
// axi-hp clock
input
wire
rst
,
// registers iface
input
wire
[
31
:
7
]
mem_address
,
input
wire
[
31
:
0
]
lba
,
input
wire
[
31
:
0
]
sector_cnt
,
input
wire
dma_type
,
input
wire
dma_start
,
output
wire
dma_done
,
// adapter data iface
// to main memory
output
wire
[
63
:
0
]
to_data
,
output
wire
to_val
,
input
wire
to_ack
,
// from main memory
input
wire
[
63
:
0
]
from_data
,
input
wire
from_val
,
input
wire
from_ack
// sata host iface
// data from sata host
input
wire
[
31
:
0
]
in_data
,
output
wire
in_val
,
input
wire
in_busy
,
// data to sata host
output
wire
[
31
:
0
]
out_data
,
output
wire
out_val
,
input
wire
out_busy
)
;
module
dma_control
(
input
wire
sclk
,
// sata clock
input
wire
hclk
,
// axi-hp clock
input
wire
rst
,
// registers iface
input
wire
[
31
:
7
]
mem_address
,
input
wire
[
31
:
0
]
lba
,
input
wire
[
31
:
0
]
sector_cnt
,
input
wire
dma_type
,
input
wire
dma_start
,
output
wire
dma_done
,
// adapter command iface
input
wire
adp_busy
,
output
wire
[
31
:
7
]
adp_addr
,
output
wire
adp_type
,
output
wire
adp_val
,
// sata host command iface
input
wire
host_ready_for_cmd
,
output
wire
host_new_cmd
,
output
wire
[
1
:
0
]
host_cmd_type
,
output
wire
[
31
:
0
]
host_sector_count
,
output
wire
[
31
:
0
]
host_sector_addr
,
// adapter data iface
// to main memory
output
wire
[
63
:
0
]
to_data
,
output
wire
to_val
,
input
wire
to_ack
,
// from main memory
input
wire
[
63
:
0
]
from_data
,
input
wire
from_val
,
output
wire
from_ack
,
// sata host iface
// data from sata host
input
wire
[
31
:
0
]
in_data
,
output
wire
in_val
,
input
wire
in_busy
,
// data to sata host
output
wire
[
31
:
0
]
out_data
,
output
wire
out_val
,
input
wire
out_busy
)
;
//////////////////////////////////////////////////////////////////////////////////////
//// ADDRESS
//////////////////////////////////////////////////////////////////////////////////////
wire
dma_done_adp
;
wire
dma_done_host
;
assign
dma_done
=
dma_done_host
&
dma_done_adp
;
reg
adp_busy_sclk
;
/*
* Commands to sata host fsm
*/
// for now only 2 states: idle and send a pulse
reg
host_issued
;
wire
host_issued_set
;
wire
host_issued_clr
;
assign
dma_done_host
=
host_issued
;
assign
host_issued_set
=
~
adp_busy_sclk
&
host_ready_for_cmd
&
dma_start
;
assign
host_issued_clr
=
dma_done
;
always
@
(
posedge
sclk
)
host_issued
<=
(
host_issued
|
host_issued_set
)
&
~
host_issued_clr
&
~
rst
;
// drive iface signals
assign
host_new_cmd
=
host_issued_set
;
assign
host_cmd_type
=
dma_type
;
assign
host_sector_count
=
sector_cnt
;
assign
host_sector_addr
=
lba
;
/*
* Commands to adapter fsm
*/
reg
[
33
:
0
]
quarter_sector_cnt
;
wire
last_data
;
// last 128 bytes of data are transmitted now
wire
adp_val_sclk
;
reg
[
31
:
7
]
current_addr
;
reg
current_type
;
// synchronize with host fsm
reg
adp_done
;
wire
adp_done_clr
;
wire
adp_done_set
;
assign
dma_done_adp
=
adp_done
;
assign
adp_done_set
=
state_wait_done
&
clr_wait_done
&
~
set_wait_busy
;
// = state_wait_done & set_idle;
assign
adp_done_clr
=
dma_done
;
always
@
(
posedge
sclk
)
adp_done
<=
(
adp_done
|
adp_done_set
)
&
~
adp_done_clr
&
~
rst
;
// calculate sent sector count
// 1 sector = 512 bytes for now => 1 quarter_sector = 128 bytes
always
@
(
posedge
sclk
)
quarter_sector_cnt
<=
~
set_wait_busy
?
quarter_sector_cnt
:
state_idle
?
34'h0
:
// new dma request
quarter_sector_cnt
+
1'b1
;
// same dma request, next 128 bytes
// flags if we're currently sending the last data piece of dma transaction
assign
last_data
=
(
sector_cnt
==
quarter_sector_cnt
[
33
:
2
]
+
1'b1
)
&
(
&
quarter_sector_cnt
[
1
:
0
])
;
// calculate outgoing address
// increment every transaction to adapter
always
@
(
posedge
sclk
)
current_addr
<=
~
set_wait_busy
?
current_addr
:
state_idle
?
mem_address
:
// new dma request
current_addr
+
1'b1
;
// same dma request, next 128 bytes
always
@
(
posedge
sclk
)
current_type
<=
~
set_wait_busy
?
current_type
:
state_idle
?
dma_type
:
// new dma request
current_type
;
// same dma request, next 128 bytes
// fsm itself
wire
state_idle
;
reg
state_wait_busy
;
reg
state_wait_done
;
wire
set_wait_busy
;
wire
set_wait_done
;
wire
clr_wait_busy
;
wire
clr_wait_done
;
assign
set_wait_busy
=
state_idle
&
host_issued_set
// same start pulse for both fsms
|
state_wait_done
&
clr_wait_done
&
~
last_data
;
// still have some data to transmit within a current dma request
assign
set_wait_done
=
state_wait_busy
&
clr_wait_busy
;
assign
clr_wait_busy
=
adp_busy_sclk
;
assign
clr_wait_done
=
~
adp_busy_sclk
;
assign
state_idle
=
~
state_wait_busy
&
~
state_wait_done
;
always
@
(
posedge
sclk
)
begin
state_wait_busy
<=
(
state_wait_busy
|
set_wait_busy
)
&
~
clr_wait_busy
&
~
rst
;
state_wait_done
<=
(
state_wait_done
|
set_wait_done
)
&
~
clr_wait_done
&
~
rst
;
end
// conrol signals resync
reg
adp_val_r
;
reg
adp_val_rr
;
always
@
(
posedge
hclk
)
begin
adp_val_r
<=
adp_val_sclk
;
adp_val_rr
<=
adp_val_r
;
end
assign
adp_addr
=
current_addr
;
assign
adp_type
=
current_type
;
assign
adp_val
=
adp_val_rr
;
// Maintaining correct adp_busy level @ sclk
// assuming busy won't toggle rapidly, can afford not implementing handshakes
wire
adp_busy_sclk_set
;
wire
adp_busy_sclk_clr
;
wire
adp_busy_set
;
wire
adp_busy_clr
;
reg
adp_busy_r
;
assign
adp_busy_set
=
adp_busy
&
~
adp_busy_r
;
assign
adp_busy_clr
=
~
adp_busy
&
adp_busy_r
;
always
@
(
posedge
sclk
)
adp_busy_sclk
<=
(
adp_busy_sclk
|
adp_busy_sclk_set
)
&
~
rst
&
~
adp_busy_sclk_clr
;
always
@
(
posedge
hclk
)
adp_busy_r
<=
adp_busy
;
pulse_cross_clock
adp_busy_set_pulse
(
.
rst
(
rst
)
,
.
src_clk
(
hclk
)
,
.
dst_clk
(
sclk
)
,
.
in_pulse
(
adp_busy_set
)
,
.
out_pulse
(
adp_busy_sclk_set
)
,
.
busy
()
)
;
pulse_cross_clock
adp_busy_clr_pulse
(
.
rst
(
rst
)
,
.
src_clk
(
hclk
)
,
.
dst_clk
(
sclk
)
,
.
in_pulse
(
adp_busy_clr
)
,
.
out_pulse
(
adp_busy_sclk_clr
)
,
.
busy
()
)
;
//////////////////////////////////////////////////////////////////////////////////////
//// DATA
//////////////////////////////////////////////////////////////////////////////////////
/*
* from main memory resyncronisation circuit
*/
...
...
@@ -65,8 +229,8 @@ reg [8:0] from_wr_addr;
wire
[
8
:
0
]
from_wr_next_addr
;
wire
[
9
:
0
]
from_rd_next_addr
;
// gray coded addresses
reg
[
9
:
0
]
from_rd_addr
;
reg
[
8
:
0
]
from_wr_addr
;
reg
[
9
:
0
]
from_rd_addr
_gr
;
reg
[
8
:
0
]
from_wr_addr
_gr
;
// anti-metastability shift registers for gray-coded addresses
reg
[
9
:
0
]
from_rd_addr_gr_r
;
reg
[
8
:
0
]
from_wr_addr_gr_r
;
...
...
@@ -99,13 +263,13 @@ end
always
@
(
posedge
sclk
)
begin
from_wr_addr_gr_r
<=
rst
?
9'h0
:
from_wr_addr
;
from_wr_addr_gr_rr
<=
rst
?
9'h0
:
from_wr_addr_
r
r
;
from_wr_addr_gr_rr
<=
rst
?
9'h0
:
from_wr_addr_
gr_
r
;
end
// read address -> hclk (wr) domain to compare
always
@
(
posedge
hclk
)
begin
from_rd_addr_gr_r
<=
rst
?
10'h0
:
from_rd_addr
;
from_rd_addr_gr_rr
<=
rst
?
10'h0
:
from_rd_addr_
r
r
;
from_rd_addr_gr_rr
<=
rst
?
10'h0
:
from_rd_addr_
gr_
r
;
end
// translate resynced write address into ordinary (non-gray) address
genvar
ii
;
...
...
@@ -169,8 +333,8 @@ reg [9:0] to_wr_addr;
wire
[
9
:
0
]
to_wr_next_addr
;
wire
[
8
:
0
]
to_rd_next_addr
;
// gray coded addresses
reg
[
8
:
0
]
to_rd_addr
;
reg
[
9
:
0
]
to_wr_addr
;
reg
[
8
:
0
]
to_rd_addr
_gr
;
reg
[
9
:
0
]
to_wr_addr
_gr
;
// anti-metastability shift registers for gray-coded addresses
reg
[
8
:
0
]
to_rd_addr_gr_r
;
reg
[
9
:
0
]
to_wr_addr_gr_r
;
...
...
@@ -204,16 +368,15 @@ end
always
@
(
posedge
hclk
)
begin
to_wr_addr_gr_r
<=
rst
?
10'h0
:
to_wr_addr
;
to_wr_addr_gr_rr
<=
rst
?
10'h0
:
to_wr_addr_
r
r
;
to_wr_addr_gr_rr
<=
rst
?
10'h0
:
to_wr_addr_
gr_
r
;
end
// read address -> sclk (wr) domain to compare
always
@
(
posedge
sclk
)
begin
to_rd_addr_gr_r
<=
rst
?
9'h0
:
to_rd_addr
;
to_rd_addr_gr_rr
<=
rst
?
9'h0
:
to_rd_addr_
r
r
;
to_rd_addr_gr_rr
<=
rst
?
9'h0
:
to_rd_addr_
gr_
r
;
end
// translate resynced write address into ordinary (non-gray) address
genvar
ii
;
generate
for
(
ii
=
0
;
ii
<
10
;
ii
=
ii
+
1
)
begin:
to_wr_antigray
...
...
dma_regs.v
0 → 100644
View file @
65abe0b4
/*******************************************************************************
* Module: dma_regs
* Date: 2015-07-11
* Author: Alexey
* Description: temporary registers, connected to axi bus
*
* Copyright (c) 2015 Elphel, Inc.
* dma_regs.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.
*
* dma_regs.v file 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/> .
*******************************************************************************/
module
dma_regs
#(
parameter
REGISTERS_CNT
=
20
)
(
input
wire
rst
,
input
wire
ACLK
,
input
wire
sclk
,
// registers iface
output
wire
[
31
:
7
]
mem_address
,
output
wire
[
31
:
0
]
lba
,
output
wire
[
31
:
0
]
sector_cnt
,
output
wire
dma_type
,
output
wire
dma_start
,
input
wire
dma_done
,
// axi buffer iface
output
wire
[
31
:
0
]
bram_rdata
,
input
wire
[
31
:
0
]
bram_raddr
,
input
wire
[
31
:
0
]
bram_waddr
,
input
wire
[
31
:
0
]
bram_wdata
,
input
wire
[
3
:
0
]
bram_wstb
,
input
wire
bram_wen
,
input
wire
bram_ren
,
input
wire
bram_regen
)
;
//reg [32*REGISTERS_CNT - 1:0] mem;
/*
* Converntional MAXI interface from x393 project, uses fifos, writes to/reads from memory
*/
/*
* Temporary mapping:
* rw 0x00: dma address (will automatically align to 128-bytes boundary, i.e. [6:0] -> 0
* rw 0x04: lba
* rw 0x08: sector count
* rw 0x0c: dma type (any(0x0c) => write)
* r1c 0x10: writes: dma start (any(0x10) => start)
* reads: dma status of last issued transfer (0xffffffff => done)
* ro 0x14: dma last issued dma_address
*/
reg
[
31
:
0
]
reg00
;
reg
[
31
:
0
]
reg04
;
reg
[
31
:
0
]
reg08
;
reg
[
31
:
0
]
reg0c
;
reg
[
31
:
0
]
reg10
;
reg
[
31
:
0
]
reg14
;
wire
dma_done_aclk
;
wire
dma_start_aclk
;
reg
dma_issued
;
wire
[
31
:
0
]
wdata
;
pulse_cross_clock
dma_done_pulse
(
.
rst
(
rst
)
,
.
src_clk
(
sclk
)
,
.
dst_clk
(
ACLK
)
,
.
in_pulse
(
dma_done
)
,
.
out_pulse
(
dma_done_aclk
)
,
.
busy
()
)
;
pulse_cross_clock
dma_start_pulse
(
.
rst
(
rst
)
,
.
src_clk
(
ACLK
)
,
.
dst_clk
(
sclk
)
,
.
in_pulse
(
dma_start_aclk
&
~
dma_issued
)
,
.
out_pulse
(
dma_start
)
,
.
busy
()
)
;
assign
dma_start_aclk
=
bram_wen
&
(
bram_waddr
[
3
:
0
]
==
4'h4
)
&
|
wdata
;
assign
wdata
=
bram_wdata
[
31
:
0
]
&
{{
8
{
bram_wstb
[
3
]
}},
{
8
{
bram_wstb
[
2
]
}},
{
8
{
bram_wstb
[
1
]
}},
{
8
{
bram_wstb
[
0
]
}}};
always
@
(
posedge
ACLK
)
dma_issued
<=
(
dma_issued
|
dma_start_aclk
)
&
~
rst
&
~
dma_done_aclk
;
assign
mem_address
=
reg00
[
31
:
7
]
;
assign
lba
=
reg04
;
assign
sector_cnt
=
reg08
;
assign
dma_type
=
|
reg0c
;
always
@
(
posedge
ACLK
)
begin
reg00
<=
rst
?
32'h0
:
bram_wen
&
(
bram_waddr
[
3
:
0
]
==
4'h0
)
?
wdata
:
reg00
;
reg04
<=
rst
?
32'h0
:
bram_wen
&
(
bram_waddr
[
3
:
0
]
==
4'h1
)
?
wdata
:
reg04
;
reg08
<=
rst
?
32'h0
:
bram_wen
&
(
bram_waddr
[
3
:
0
]
==
4'h2
)
?
wdata
:
reg08
;
reg0c
<=
rst
?
32'h0
:
bram_wen
&
(
bram_waddr
[
3
:
0
]
==
4'h3
)
?
wdata
:
reg0c
;
reg10
<=
rst
?
32'h0
:
dma_start_aclk
?
32'h0
:
dma_done_aclk
?
32'hffffffff
:
reg10
;
// status reg
reg14
<=
rst
?
32'h0
:
dma_done_aclk
?
reg00
:
reg14
;
end
// read from registers. Interface's protocol assumes returning data with a delay
reg
[
3
:
0
]
bram_raddr_r
;
reg
[
31
:
0
]
bram_rdata_r
;
always
@
(
posedge
ACLK
)
begin
bram_raddr_r
<=
bram_ren
?
bram_raddr
[
3
:
0
]
:
bram_raddr_r
;
bram_rdata_r
<=
~
bram_regen
?
bram_rdata_r
:
bram_raddr_r
==
4'h0
?
reg00
:
bram_raddr_r
==
4'h1
?
reg04
:
bram_raddr_r
==
4'h2
?
reg08
:
bram_raddr_r
==
4'h3
?
reg0c
:
bram_raddr_r
==
4'h4
?
reg10
:
bram_raddr_r
==
4'h5
?
reg14
:
32'hd34db33f
;
end
assign
bram_rdata
=
bram_rdata_r
;
/*
// for testing purposes the 'memory' is a set of registers for now
// later on will try to use them as an application level registers
genvar ii;
generate
for (ii = 0; ii < REGISTERS_CNT; ii = ii + 1)
begin: write_to_mem
always @ (posedge ACLK)
begin
mem[32*ii + 31-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[31-:8] & {8{bram_wstb[3]}}: mem[32*ii + 31-:8];
mem[32*ii + 23-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[23-:8] & {8{bram_wstb[2]}}: mem[32*ii + 23-:8];
mem[32*ii + 15-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[15-:8] & {8{bram_wstb[1]}}: mem[32*ii + 15-:8];
mem[32*ii + 7-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[ 7-:8] & {8{bram_wstb[0]}}: mem[32*ii + 7-:8];
end
end
endgenerate
// read from memory. Interface's protocol assumes returning data with a delay
reg [3:0] bram_raddr_r;
reg [31:0] bram_rdata_r;
always @ (posedge ACLK) begin
bram_raddr_r <= bram_ren ? bram_raddr[3:0] : bram_raddr_r;
bram_rdata_r <= bram_regen ? mem[32*bram_raddr_r + 31-:32] : bram_rdata_r;
end
assign bram_rdata = bram_rdata_r;
*/
endmodule
sata_host.v
View file @
65abe0b4
...
...
@@ -40,7 +40,7 @@ module sata_host(
input
wire
data_clk_out
,
// timer
output
wire
sata_timer
,
output
wire
[
31
:
0
]
sata_timer
,
// phy
input
wire
clkin_150
,
...
...
@@ -50,9 +50,47 @@ module sata_host(
output
wire
txp_out
,
output
wire
txn_out
,
input
wire
rxp_in
,
input
wire
rxn_in
)
;
input
wire
rxn_in
,
output
wire
plllkdet
,
output
wire
dcmlocked
)
;
/*
assign ready_for_cmd = 1'b0;
assign sata_core_full = 1'b0;
assign sata_dout = 32'b0;
assign sata_core_empty = 1'b0;
assign sata_timer = 1'b0;
assign linkup = 1'b0;
assign txp_out = 1'b0;
assign txn_out = 1'b0;
assign plllkdet = 1'b0;
assign dcmlocked = 1'b0;*/
sata_core
sata_core
(
.
ready_for_cmd
(
ready_for_cmd
)
,
.
new_cmd
(
new_cmd
)
,
.
cmd_type
(
cmd_type
)
,
.
sector_count
(
sector_count
)
,
.
sector_addr
(
sector_addr
)
,
.
sata_din
(
sata_din
)
,
.
sata_din_we
(
sata_din_we
)
,
.
sata_core_full
(
sata_core_full
)
,
.
sata_dout
(
sata_dout
)
,
.
sata_dout_re
(
sata_dout_re
)
,
.
sata_core_empty
(
sata_core_empty
)
,
.
SATA_USER_DATA_CLK_IN
(
data_clk_in
)
,
.
SATA_USER_DATA_CLK_OUT
(
data_clk_out
)
,
.
sata_timer
(
sata_timer
)
,
.
CLKIN_150
(
clkin_150
)
,
.
reset
(
reset
)
,