Skip to content

Commit c4cb3df

Browse files
larsclausenLars-Peter Clausen
authored andcommitted
axi_dmac: Move transfer abort logic to data mover
The transfer abort logic in the src_axi_stream module is making some assumptions about the internal timings of the data mover module. Move this logic inside the data mover module. This will make it easier to update the internal logic without having to update other modules. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
1 parent 92984dc commit c4cb3df

File tree

3 files changed

+58
-54
lines changed

3 files changed

+58
-54
lines changed

library/axi_dmac/data_mover.v

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ module dmac_data_mover #(
3737

3838
parameter ID_WIDTH = 3,
3939
parameter DATA_WIDTH = 64,
40-
parameter BEATS_PER_BURST_WIDTH = 4) (
40+
parameter BEATS_PER_BURST_WIDTH = 4,
41+
parameter ALLOW_ABORT = 0) (
4142

4243
input clk,
4344
input resetn,
@@ -51,6 +52,7 @@ module dmac_data_mover #(
5152
output s_axi_ready,
5253
input s_axi_valid,
5354
input [DATA_WIDTH-1:0] s_axi_data,
55+
input s_axi_last,
5456
input s_axi_sync,
5557

5658
output m_axi_valid,
@@ -60,7 +62,8 @@ module dmac_data_mover #(
6062
input req_valid,
6163
output req_ready,
6264
input [BEATS_PER_BURST_WIDTH-1:0] req_last_burst_length,
63-
input req_sync_transfer_start
65+
input req_sync_transfer_start,
66+
input req_xlast
6467
);
6568

6669
localparam BEAT_COUNTER_MAX = {BEATS_PER_BURST_WIDTH{1'b1}};
@@ -81,7 +84,7 @@ reg needs_sync = 1'b0;
8184
wire has_sync = ~needs_sync | s_axi_sync;
8285

8386
wire s_axi_sync_valid = has_sync & s_axi_valid;
84-
wire s_axi_beat = s_axi_sync_valid & s_axi_ready;
87+
wire transfer_abort_s;
8588

8689
wire last_load;
8790
wire last;
@@ -92,18 +95,51 @@ assign response_id = id;
9295

9396
assign last = eot ? last_eot : last_non_eot;
9497

95-
assign s_axi_ready = pending_burst & active;
96-
assign m_axi_valid = s_axi_sync_valid & pending_burst & active;
97-
assign m_axi_data = s_axi_data;
98+
assign s_axi_ready = (pending_burst & active) & ~transfer_abort_s;
99+
assign m_axi_valid = (s_axi_sync_valid | transfer_abort_s) & pending_burst & active;
100+
assign m_axi_data = transfer_abort_s == 1'b1 ? {DATA_WIDTH{1'b0}} : s_axi_data;
98101
assign m_axi_last = last;
99-
assign m_axi_eot = last & eot;
102+
103+
generate if (ALLOW_ABORT == 1) begin
104+
reg transfer_abort = 1'b0;
105+
reg req_xlast_d = 1'b0;
106+
107+
/*
108+
* A 'last' on the external interface indicates the end of an packet. If such a
109+
* 'last' indicator is observed before the end of the current transfer stop
110+
* accepting data on the external interface and complete the current transfer by
111+
* writing zeros to the buffer.
112+
*/
113+
always @(posedge clk) begin
114+
if (resetn == 1'b0) begin
115+
transfer_abort <= 1'b0;
116+
end else if (m_axi_valid == 1'b1) begin
117+
if (last == 1'b1 && eot == 1'b1 && req_xlast_d == 1'b1) begin
118+
transfer_abort <= 1'b0;
119+
end else if (s_axi_last == 1'b1) begin
120+
transfer_abort <= 1'b1;
121+
end
122+
end
123+
end
124+
125+
always @(posedge clk) begin
126+
if (req_ready == 1'b1) begin
127+
req_xlast_d <= req_xlast;
128+
end
129+
end
130+
131+
assign transfer_abort_s = transfer_abort;
132+
133+
end else begin
134+
assign transfer_abort_s = 1'b0;
135+
end endgenerate
100136

101137
/*
102138
* If req_sync_transfer_start is set all incoming beats will be skipped until
103139
* one has s_axi_sync set. This will be the first beat that is passsed through.
104140
*/
105141
always @(posedge clk) begin
106-
if (s_axi_beat == 1'b1)
142+
if (m_axi_valid == 1'b1) begin
107143
needs_sync <= 1'b0;
108144
end else if (req_ready == 1'b1) begin
109145
needs_sync <= req_sync_transfer_start;
@@ -112,15 +148,15 @@ end
112148

113149
// If we want to support zero delay between transfers we have to assert
114150
// req_ready on the same cycle on which the last load happens.
115-
assign last_load = s_axi_beat && last_eot && eot;
151+
assign last_load = m_axi_valid && last_eot && eot;
116152
assign req_ready = last_load || ~active;
117153

118154
always @(posedge clk) begin
119155
if (req_ready) begin
120156
last_eot <= req_last_burst_length == 'h0;
121157
last_non_eot <= 1'b0;
122158
beat_counter <= 'h1;
123-
end else if (s_axi_beat == 1'b1) begin
159+
end else if (m_axi_valid == 1'b1) begin
124160
last_eot <= beat_counter == last_burst_length;
125161
last_non_eot <= beat_counter == BEAT_COUNTER_MAX;
126162
beat_counter <= beat_counter + 1'b1;
@@ -144,7 +180,7 @@ end
144180

145181
always @(*)
146182
begin
147-
if (s_axi_beat == 1'b1 && last == 1'b1)
183+
if (m_axi_valid == 1'b1 && last == 1'b1)
148184
id_next <= inc_id(id);
149185
else
150186
id_next <= id;

library/axi_dmac/src_axi_stream.v

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -68,48 +68,13 @@ module dmac_src_axi_stream #(
6868
input req_xlast
6969
);
7070

71-
reg transfer_abort = 1'b0;
72-
reg req_xlast_d = 1'b0;
73-
74-
wire [S_AXIS_DATA_WIDTH-1:0] data;
75-
wire data_valid;
76-
wire data_ready;
77-
wire fifo_eot;
78-
7971
assign enabled = enable;
8072

81-
assign data = transfer_abort == 1'b1 ? {S_AXIS_DATA_WIDTH{1'b0}} : s_axis_data;
82-
assign data_valid = s_axis_valid | transfer_abort;
83-
assign s_axis_ready = data_ready & ~transfer_abort;
84-
85-
/*
86-
* A 'last' on the external interface indicates the end of an packet. If such a
87-
* 'last' indicator is observed before the end of the current transfer stop
88-
* accepting data on the external interface and complete the current transfer by
89-
* writing zeros to the buffer.
90-
*/
91-
always @(posedge s_axis_aclk) begin
92-
if (s_axis_aresetn == 1'b0) begin
93-
transfer_abort <= 1'b0;
94-
end else if (data_ready == 1'b1 && data_valid == 1'b1) begin
95-
if (fifo_eot == 1'b1 && req_xlast_d == 1'b1) begin
96-
transfer_abort <= 1'b0;
97-
end else if (s_axis_last == 1'b1) begin
98-
transfer_abort <= 1'b1;
99-
end
100-
end
101-
end
102-
103-
always @(posedge s_axis_aclk) begin
104-
if(req_ready == 1'b1) begin
105-
req_xlast_d <= req_xlast;
106-
end
107-
end
108-
10973
dmac_data_mover # (
11074
.ID_WIDTH(ID_WIDTH),
11175
.DATA_WIDTH(S_AXIS_DATA_WIDTH),
112-
.BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH)
76+
.BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH),
77+
.ALLOW_ABORT(1)
11378
) i_data_mover (
11479
.clk(s_axis_aclk),
11580
.resetn(s_axis_aresetn),
@@ -124,16 +89,17 @@ dmac_data_mover # (
12489
.req_ready(req_ready),
12590
.req_last_burst_length(req_last_burst_length),
12691
.req_sync_transfer_start(req_sync_transfer_start),
92+
.req_xlast(req_xlast),
12793

128-
.s_axi_ready(data_ready),
129-
.s_axi_valid(data_valid),
130-
.s_axi_data(data),
94+
.s_axi_valid(s_axis_valid),
95+
.s_axi_ready(s_axis_ready),
96+
.s_axi_data(s_axis_data),
97+
.s_axi_last(s_axis_last),
13198
.s_axi_sync(s_axis_user[0]),
13299

133100
.m_axi_valid(fifo_valid),
134101
.m_axi_data(fifo_data),
135-
.m_axi_last(fifo_last),
136-
.m_axi_eot(fifo_eot)
102+
.m_axi_last(fifo_last)
137103
);
138104

139105
endmodule

library/axi_dmac/src_fifo_inf.v

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,14 @@ dmac_data_mover # (
9898
.req_valid(req_valid),
9999
.req_ready(req_ready),
100100
.req_last_burst_length(req_last_burst_length),
101-
.req_sync_transfer_start(req_sync_transer_start),
101+
.req_sync_transfer_start(req_sync_transfer_start),
102+
.req_xlast(1'b0),
102103

103104
.s_axi_ready(ready),
104105
.s_axi_valid(valid),
105106
.s_axi_data(din),
106107
.s_axi_sync(sync),
108+
.s_axi_last(1'b0),
107109

108110
.m_axi_valid(fifo_valid),
109111
.m_axi_data(fifo_data),

0 commit comments

Comments
 (0)