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
869188e9
Commit
869188e9
authored
Jul 22, 2015
by
Alexey Grebenkin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dma_adapter rtl done
parent
6a13fd70
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
121 additions
and
94 deletions
+121
-94
dma_adapter.v
dma_adapter.v
+121
-94
No files found.
dma_adapter.v
View file @
869188e9
...
...
@@ -29,26 +29,13 @@
* a big dma data storage and axi interface. So it shall recieve data and control
* for 1 burst and pass it to axi.
*/
/*
* For debug only:
* DMA write:
* 0x0c: |mem[:] => use dbg registers as a source of dma data
* 0x10: addr of the buffer
* 0x14: size
* 0x18: burst len
* 0x1c: start dma
* 0x20-0x3c - data
*/
module
send_dma
#(
parameter
REGISTERS_CNT
=
20
)
(
input
wire
clk
,
input
wire
rst
,
// dbg iface
input
wire
[
32
*
REGISTERS_CNT
-
1
:
0
]
mem
,
input
wire
dbg_mode
,
output
wire
clrstart
,
// cmd iface
input
wire
cmd_type
,
// 1 = wr, 0 = rd
input
wire
cmd_val
,
// issue a cmd
...
...
@@ -57,9 +44,11 @@ module send_dma #(
// data iface
input
wire
[
63
:
0
]
wr_data_in
,
output
wire
wr_val_out
,
input
wire
wr_val_in
,
output
wire
wr_ack_out
,
output
wire
[
63
:
0
]
rd_data_out
,
input
wire
rd_val_in
,
output
wire
rd_val_out
,
input
wire
rd_ack_in
,
// membridge iface
output
wire
[
7
:
0
]
cmd_ad
,
...
...
@@ -89,91 +78,133 @@ module send_dma #(
// if not busy and got cmd with val => cmd recieved, assert busy, start a respective algorithm
wire
wr_start
;
wire
rd_start
;
wire
dma_start
;
reg
wr_done
;
reg
rd_done
;
reg
cmd_type_r
;
reg
cmd_addr_r
;
reg
cmd_val_r
;
reg
[
31
:
7
]
cmd_addr_r
;
reg
cmd_busy_r
;
wire
set_busy
;
wire
clr_busy
;
assign
set_busy
=
~
cmd_busy_r
&
cmd_val
;
assign
clr_busy
=
cmd_busy_r
&
(
wr_done
|
rd_done
)
assign
clr_busy
=
cmd_busy_r
&
(
wr_done
|
rd_done
)
;
assign
cmd_busy
=
cmd_busy_r
;
assign
wr_start
=
set_busy
&
cmd_type
;
assign
rd_start
=
set_busy
&
~
cmd_type
;
always
@
(
posedge
clk
)
begin
cmd_type_r
<=
rst
?
1'b0
:
cmd_addr_r
<=
rst
?
1'b0
:
cmd_val_r
<=
rst
?
1'b0
:
cmd_busy_r
<=
rst
?
1'b0
:
~
cmd_busy_r
&
cmd_val_r
cmd_type_r
<=
rst
?
1'b0
:
set_busy
?
cmd_type
:
cmd_type_r
;
cmd_addr_r
<=
rst
?
1'b0
:
set_busy
?
cmd_addr
:
cmd_addr_r
;
cmd_busy_r
<=
(
cmd_busy_r
|
set_busy
)
&
~
rst
&
~
clr_busy
;
end
/*
* Read/write state machine
* Read/write
data
state machine
* For better readability the state machine is splitted to two pieces:
* the first one is responsible only for the CMD WRITE case handling,
* the second one, respectively, for CMD READ
*
*
Each fsm starts a membridge fsm, which, if being 1st time launched, sets up
* membridge's registers, or, if have been launched before, just programs read/write
*
Simultaniously with each fsm starts a membridge fsm, which, if being 1st time launched,
*
sets up
membridge's registers, or, if have been launched before, just programs read/write
* address.
*
* Current implementation is extremely slow, but simple and reliable
* After all other parts are implemented and this place occurs to be a bottleneck
* then replace it (and may be membridge too) with something more ... pipelined
*/
reg
[
1
:
0
]
rdwr_state
;
// check if memberidge was already set up
reg
membr_is_set
;
always
@
(
posedge
clk
)
membr_is_set
<=
(
membr_is_set
|
dma_start
)
&
~
rst
;
// common state register
reg
[
3
:
0
]
rdwr_state
;
// Get data from buffer
localparam
READ_IDLE
=
0
;
localparam
READ_
ON
=
2
;
localparam
READ_DATA
=
3
;
localparam
READ_IDLE
=
0
;
localparam
READ_
WAIT_ADDR
=
3
;
localparam
READ_DATA
=
4
;
reg
rd_reset_page
;
reg
rd_next_page
;
reg
rd_data
reg
rd_data
;
reg
[
6
:
0
]
rd_data_count
;
wire
rd_stop
;
wire
rd_cnt_to_pull
;
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
;
always
@
(
posedge
clk
)
if
(
rst
)
begin
rd_state
<=
READ_IDLE
;
rd_done
<=
rdwr_state
<=
READ_IDLE
;
rd_done
<=
1'b0
;
rd_data_count
<=
7'h0
;
rd_next_page
<=
1'b0
;
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_
ON:
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
// Put data into buffer
localparam
WRITE_IDLE
=
0
;
localparam
WRITE_ON
=
1
;
localparam
WRITE_IDLE
=
0
;
localparam
WRITE_DATA
=
1
;
localparam
WRITE_WAIT_ADDR
=
2
;
reg
wr_en
;
reg
wr_reset_page
;
reg
wr_next_page
;
reg
[
63
:
0
]
wr_data
;
reg
[
6
:
0
]
wr_
page_offse
t
;
reg
[
6
:
0
]
wr_
data_coun
t
;
reg
wr_page_ready
;
reg
wr_val
;
wire
[
31
:
0
]
dw0
=
mem
[
32
*
9
-
1
:
32
*
8
]
;
wire
[
31
:
0
]
dw1
=
mem
[
32
*
10
-
1
:
32
*
9
]
;
wire
[
31
:
0
]
dw2
=
mem
[
32
*
11
-
1
:
32
*
10
]
;
wire
[
31
:
0
]
dw3
=
mem
[
32
*
12
-
1
:
32
*
11
]
;
wire
[
6
:
0
]
wr_cnt_to_push
;
wire
wr_stop
;
assign
wr_cnt_to_push
=
7'hf
;
assign
wr_stop
=
wr_
page_offse
t
==
wr_cnt_to_push
;
assign
wr_stop
=
wr_
val_in
&
wr_data_coun
t
==
wr_cnt_to_push
;
assign
wr_
val_in
=
wr_val
;
assign
wr_
ack_out
=
wr_val_in
&
rdwr_state
==
WRITE_DATA
;
assign
wr_data_in
=
wr_data
;
...
...
@@ -182,7 +213,7 @@ always @ (posedge clk)
if
(
rst
)
begin
wr_done
<=
1'b0
;
wr_
page_offset
<=
7'd0
;
wr_
data_count
<=
7'd0
;
wr_val
<=
1'b0
;
wr_data
<=
64'h0
;
wr_next_page
<=
1'b0
;
...
...
@@ -195,37 +226,42 @@ always @ (posedge clk)
case
(
wr_state
)
WRITE_IDLE:
begin
wr_
page_offset
<=
7'd0
;
wr_
data_count
<=
7'd0
;
wr_done
<=
1'b0
;
wr_val
<=
1'b0
;
wr_data
<=
64'h0
;
wr_next_page
<=
1'b0
;
wr_reset_page
<=
wr_start
?
1'b1
:
1'b0
;
wr_en
<=
1'b0
;
wr_page_ready
<=
1'b0
;
rdwr_state
<=
wr_start
?
WRITE_
ON
:
WRITE_IDLE
;
rdwr_state
<=
wr_start
?
WRITE_
DATA
:
WRITE_IDLE
;
end
WRITE_
ON
:
WRITE_
DATA
:
begin
wr_done
<=
wr_stop
?
1'b1
:
1'b0
;
wr_page_offset
<=
wr_page_offset
+
1'b1
;
wr_val
<=
1'b1
;
wr_data
<=
~
dbg_mode
?
in_data
:
wr_page_offset
[
1
:
0
]
==
2'b00
?
{
dw0
,
25'h0
,
wr_page_offset
}
:
wr_page_offset
[
1
:
0
]
==
2'b01
?
{
dw1
,
25'h0
,
wr_page_offset
}
:
wr_page_offset
[
1
:
0
]
==
2'b10
?
{
dw2
,
25'h0
,
wr_page_offset
}
:
{
dw3
,
25'h0
,
wr_page_offset
};
wr_done
<=
wr_stop
&
membr_state
==
IDLE
?
1'b1
:
1'b0
;
wr_data_count
<=
wr_val_in
?
wr_data_count
+
1'b1
:
wr_data_count
;
wr_data
<=
in_data
:
wr_next_page
<=
wr_stop
?
1'b1
:
1'b0
;
wr_reset_page
<=
1'b0
;
wr_en
<=
1'b1
;
wr_en
<=
wr_val_in
;
wr_page_ready
<=
wr_stop
?
1'b1
:
1'b0
;
rdwr_state
<=
wr_stop
?
WRITE_IDLE
:
WRITE_ON
;
rdwr_state
<=
wr_stop
&
membr_state
==
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_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
;
end
default:
// read is executed
begin
wr_done
<=
1'b0
;
wr_page_offset
<=
7'd0
;
wr_val
<=
1'b0
;
wr_data_count
<=
7'd0
;
wr_data
<=
64'h0
;
wr_next_page
<=
1'b0
;
wr_reset_page
<=
1'b0
;
...
...
@@ -235,13 +271,12 @@ always @ (posedge clk)
end
endcase
// temporary assigments
assign
status_start
=
1'b0
;
// no need until status is used
assign
cmd_wrmem
=
1'b0
;
// for now only writing
assign
xfer_reset_page_wr
=
1'b0
;
// for now only writing
assign
buf_rpage_nxt
=
1'b0
;
// for now only writing
assign
buf_rd
=
1'b0
;
// for now only writing
assign
xfer_reset_page_wr
=
1'b0
;
// membridge interface assigments
assign
status_start
=
1'b0
;
// no need until status is used
assign
cmd_wrmem
=
~
cmd_type_r
;
assign
xfer_reset_page_wr
=
rd_reset_page
;
assign
buf_rpage_nxt
=
rd_next_page
;
assign
buf_rd
=
rd_en
;
assign
buf_wdata
=
wr_data
;
assign
buf_wr
=
wr_en
;
assign
buf_wpage_nxt
=
wr_next_page
;
...
...
@@ -249,16 +284,9 @@ assign xfer_reset_page_rd = wr_reset_page;
assign
page_ready_chn
=
cmd_wrmem
?
1'b0
:
wr_page_ready
;
assign
frame_done_chn
=
1'b1
;
// compute membridge parameters to corresponding mem register
// dma fsm
// mode = 0
// width = 4
// size = 0x14
// start = 0
// lo_address = 0x10
// ctrl = 0x1c
// len = 0x18
/*
* Transfer address and membridge set-ups state machine
*/
localparam
MEMBR_IDLE
=
0
;
localparam
MEMBR_MODE
=
1
;
localparam
MEMBR_WIDTH
=
2
;
...
...
@@ -275,11 +303,8 @@ reg membr_done;
reg
[
2
:
0
]
membr_state
;
reg
membr_setup
;
// indicates the first tick of the state
wire
membr_inprocess
;
wire
dma_start
;
assign
dma_start
=
|
mem
[
32
*
8
-
1
:
32
*
7
]
;
assign
clrstart
=
dma_start
&
membr_state
==
MEMBR_IDLE
;
//assign wr_start = membr_state == MEMBR_CTRL;
assign
dma_start
=
wr_start
|
rd_start
;
always
@
(
posedge
clk
)
if
(
rst
)
...
...
@@ -288,6 +313,7 @@ always @ (posedge clk)
membr_addr
<=
16'h0
;
membr_start
<=
1'b0
;
membr_setup
<=
1'b0
;
membr_done
<=
1'b0
;
membr_state
<=
MEMBR_IDLE
;
end
else
...
...
@@ -298,7 +324,9 @@ always @ (posedge clk)
membr_addr
<=
16'h200
;
membr_start
<=
dma_start
?
1'b1
:
1'b0
;
membr_setup
<=
dma_start
?
1'b1
:
1'b0
;
membr_state
<=
dma_start
?
MEMBR_MODE
:
MEMBR_IDLE
;
membr_done
<=
1'b0
;
membr_state
<=
dma_start
&
membr_is_set
?
MEMBR_LOADDDR
:
dma_start
?
MEMBR_MODE
:
MEMBR_IDLE
;
end
MEMBR_MODE:
begin
...
...
@@ -306,6 +334,7 @@ always @ (posedge clk)
membr_addr
<=
16'h207
;
membr_start
<=
membr_inprocess
?
1'b0
:
1'b1
;
membr_setup
<=
membr_inprocess
|
membr_setup
?
1'b0
:
1'b1
;
membr_done
<=
1'b0
;
membr_state
<=
membr_inprocess
|
membr_setup
?
MEMBR_MODE
:
MEMBR_WIDTH
;
end
MEMBR_WIDTH:
...
...
@@ -314,6 +343,7 @@ always @ (posedge clk)
membr_addr
<=
16'h206
;
membr_start
<=
membr_inprocess
?
1'b0
:
1'b1
;
membr_setup
<=
membr_inprocess
|
membr_setup
?
1'b0
:
1'b1
;
membr_done
<=
1'b0
;
membr_state
<=
membr_inprocess
|
membr_setup
?
MEMBR_WIDTH
:
MEMBR_LEN
;
end
MEMBR_LEN:
...
...
@@ -322,6 +352,7 @@ always @ (posedge clk)
membr_addr
<=
16'h205
;
membr_start
<=
membr_inprocess
?
1'b0
:
1'b1
;
membr_setup
<=
membr_inprocess
|
membr_setup
?
1'b0
:
1'b1
;
membr_done
<=
1'b0
;
membr_state
<=
membr_inprocess
|
membr_setup
?
MEMBR_LEN
:
MEMBR_START
;
end
MEMBR_START:
...
...
@@ -330,6 +361,7 @@ always @ (posedge clk)
membr_addr
<=
16'h204
;
membr_start
<=
membr_inprocess
?
1'b0
:
1'b1
;
membr_setup
<=
membr_inprocess
|
membr_setup
?
1'b0
:
1'b1
;
membr_done
<=
1'b0
;
membr_state
<=
membr_inprocess
|
membr_setup
?
MEMBR_START
:
MEMBR_SIZE
;
end
MEMBR_SIZE:
...
...
@@ -338,14 +370,16 @@ always @ (posedge clk)
membr_addr
<=
16'h203
;
membr_start
<=
membr_inprocess
?
1'b0
:
1'b1
;
membr_setup
<=
membr_inprocess
|
membr_setup
?
1'b0
:
1'b1
;
membr_done
<=
1'b0
;
membr_state
<=
membr_inprocess
|
membr_setup
?
MEMBR_SIZE
:
MEMBR_LOADDR
;
end
MEMBR_LOADDR:
begin
membr_data
<=
mem
[
32
*
5
-
1
:
32
*
4
]
;
membr_data
<=
cmd_addr_r
;
membr_addr
<=
16'h202
;
membr_start
<=
membr_inprocess
?
1'b0
:
1'b1
;
membr_setup
<=
membr_inprocess
|
membr_setup
?
1'b0
:
1'b1
;
membr_done
<=
1'b0
;
membr_state
<=
membr_inprocess
|
membr_setup
?
MEMBR_LOADDR
:
MEMBR_CTRL
;
end
MEMBR_CTRL:
...
...
@@ -354,6 +388,7 @@ always @ (posedge clk)
membr_addr
<=
16'h200
;
membr_start
<=
membr_inprocess
?
1'b0
:
1'b1
;
membr_setup
<=
1'b0
;
membr_done
<=
membr_inprocess
|
membr_setup
?
1'b0
:
1'b1
;
membr_state
<=
membr_inprocess
|
membr_setup
?
MEMBR_CTRL
:
MEMBR_IDLE
;
end
default:
...
...
@@ -362,6 +397,7 @@ always @ (posedge clk)
membr_addr
<=
16'h0
;
membr_start
<=
1'b0
;
membr_setup
<=
1'b0
;
membr_done
<=
1'b0
;
membr_state
<=
MEMBR_IDLE
;
end
endcase
...
...
@@ -386,7 +422,6 @@ assign cmd_stb = out_stb;
always
@
(
posedge
clk
)
if
(
rst
)
begin
membr_done
<=
1'b0
;
state
<=
STATE_IDLE
;
out_ad
<=
8'h0
;
out_stb
<=
1'b0
;
...
...
@@ -395,56 +430,48 @@ always @ (posedge clk)
case
(
state
)
STATE_IDLE:
begin
membr_done
<=
1'b0
;
out_ad
<=
8'h0
;
out_stb
<=
1'b0
;
state
<=
membr_setup
?
STATE_CMD_0
:
STATE_IDLE
;
end
STATE_CMD_0:
begin
membr_done
<=
1'b0
;
out_ad
<=
membr_addr
[
7
:
0
]
;
out_stb
<=
1'b1
;
state
<=
STATE_CMD_1
;
end
STATE_CMD_1:
begin
membr_done
<=
1'b0
;
out_ad
<=
membr_addr
[
15
:
8
]
;
out_stb
<=
1'b0
;
state
<=
STATE_DATA_0
;
end
STATE_DATA_0:
begin
membr_done
<=
1'b0
;
out_ad
<=
membr_data
[
7
:
0
]
;
out_stb
<=
1'b0
;
state
<=
STATE_DATA_1
;
end
STATE_DATA_1:
begin
membr_done
<=
1'b0
;
out_ad
<=
membr_data
[
15
:
8
]
;
out_stb
<=
1'b0
;
state
<=
STATE_DATA_2
;
end
STATE_DATA_2:
begin
membr_done
<=
1'b0
;
out_ad
<=
membr_data
[
23
:
16
]
;
out_stb
<=
1'b0
;
state
<=
STATE_DATA_3
;
end
STATE_DATA_3:
begin
membr_done
<=
1'b0
;
out_ad
<=
membr_data
[
31
:
24
]
;
out_stb
<=
1'b0
;
state
<=
STATE_IDLE
;
end
default:
begin
membr_done
<=
1'b1
;
out_ad
<=
8'hff
;
out_stb
<=
1'b0
;
state
<=
STATE_IDLE
;
...
...
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