1 |
32 |
redbear |
// (C) 2001-2017 Intel Corporation. All rights reserved.
|
2 |
|
|
// Your use of Intel Corporation's design tools, logic functions and other
|
3 |
|
|
// software and tools, and its AMPP partner logic functions, and any output
|
4 |
40 |
redbear |
// files from any of the foregoing (including device programming or simulation
|
5 |
32 |
redbear |
// files), and any associated documentation or information are expressly subject
|
6 |
|
|
// to the terms and conditions of the Intel Program License Subscription
|
7 |
40 |
redbear |
// Agreement, Intel FPGA IP License Agreement, or other applicable
|
8 |
32 |
redbear |
// license agreement, including, without limitation, that your use is for the
|
9 |
|
|
// sole purpose of programming logic devices manufactured by Intel and sold by
|
10 |
|
|
// Intel or its authorized distributors. Please refer to the applicable
|
11 |
|
|
// agreement for further details.
|
12 |
|
|
|
13 |
|
|
|
14 |
40 |
redbear |
// $Id: //acds/rel/17.1std/ip/merlin/altera_merlin_burst_adapter/new_source/altera_default_burst_converter.sv#1 $
|
15 |
32 |
redbear |
// $Revision: #1 $
|
16 |
40 |
redbear |
// $Date: 2017/07/30 $
|
17 |
32 |
redbear |
// $Author: swbranch $
|
18 |
|
|
|
19 |
|
|
// --------------------------------------------
|
20 |
|
|
// Default Burst Converter
|
21 |
|
|
// Notes:
|
22 |
|
|
// 1) If burst type FIXED and slave is AXI,
|
23 |
|
|
// passthrough the transaction.
|
24 |
|
|
// 2) Else, converts burst into non-bursting
|
25 |
|
|
// transactions (length of 1).
|
26 |
|
|
// --------------------------------------------
|
27 |
|
|
|
28 |
|
|
`timescale 1 ns / 1 ns
|
29 |
|
|
|
30 |
|
|
module altera_default_burst_converter
|
31 |
|
|
#(
|
32 |
|
|
parameter PKT_BURST_TYPE_W = 2,
|
33 |
|
|
parameter PKT_BURSTWRAP_W = 5,
|
34 |
|
|
parameter PKT_ADDR_W = 12,
|
35 |
|
|
parameter PKT_BURST_SIZE_W = 3,
|
36 |
|
|
parameter IS_AXI_SLAVE = 0,
|
37 |
|
|
parameter LEN_W = 2
|
38 |
|
|
)
|
39 |
|
|
(
|
40 |
|
|
input clk,
|
41 |
|
|
input reset,
|
42 |
|
|
input enable,
|
43 |
|
|
|
44 |
|
|
input [PKT_BURST_TYPE_W - 1 : 0] in_bursttype,
|
45 |
|
|
input [PKT_BURSTWRAP_W - 1 : 0] in_burstwrap_reg,
|
46 |
|
|
input [PKT_BURSTWRAP_W - 1 : 0] in_burstwrap_value,
|
47 |
|
|
input [PKT_ADDR_W - 1 : 0] in_addr,
|
48 |
|
|
input [PKT_ADDR_W - 1 : 0] in_addr_reg,
|
49 |
|
|
input [LEN_W - 1 : 0] in_len,
|
50 |
|
|
input [PKT_BURST_SIZE_W - 1 : 0] in_size_value,
|
51 |
|
|
|
52 |
|
|
input in_is_write,
|
53 |
|
|
|
54 |
|
|
output reg [PKT_ADDR_W - 1 : 0] out_addr,
|
55 |
|
|
output reg [LEN_W - 1 : 0] out_len,
|
56 |
|
|
|
57 |
|
|
output reg new_burst
|
58 |
|
|
);
|
59 |
|
|
|
60 |
|
|
// ---------------------------------------------------
|
61 |
|
|
// AXI Burst Type Encoding
|
62 |
|
|
// ---------------------------------------------------
|
63 |
|
|
typedef enum bit [1:0]
|
64 |
|
|
{
|
65 |
|
|
FIXED = 2'b00,
|
66 |
|
|
INCR = 2'b01,
|
67 |
|
|
WRAP = 2'b10,
|
68 |
|
|
RESERVED = 2'b11
|
69 |
|
|
} AxiBurstType;
|
70 |
|
|
|
71 |
|
|
// -------------------------------------------
|
72 |
|
|
// Internal Signals
|
73 |
|
|
// -------------------------------------------
|
74 |
|
|
wire [LEN_W - 1 : 0] unit_len = {{LEN_W - 1 {1'b0}}, 1'b1};
|
75 |
|
|
reg [LEN_W - 1 : 0] next_len;
|
76 |
|
|
reg [LEN_W - 1 : 0] remaining_len;
|
77 |
|
|
reg [PKT_ADDR_W - 1 : 0] next_incr_addr;
|
78 |
|
|
reg [PKT_ADDR_W - 1 : 0] incr_wrapped_addr;
|
79 |
|
|
reg [PKT_ADDR_W - 1 : 0] extended_burstwrap_value;
|
80 |
|
|
reg [PKT_ADDR_W - 1 : 0] addr_incr_variable_size_value;
|
81 |
|
|
|
82 |
|
|
// -------------------------------------------
|
83 |
|
|
// Byte Count Converter
|
84 |
|
|
// -------------------------------------------
|
85 |
|
|
// Avalon Slave: Read/Write, the out_len is always 1 (unit_len).
|
86 |
|
|
// AXI Slave: Read/Write, the out_len is always the in_len (pass through) of a given cycle.
|
87 |
|
|
// If bursttype RESERVED, out_len is always 1 (unit_len).
|
88 |
|
|
generate if (IS_AXI_SLAVE == 1)
|
89 |
|
|
begin : axi_slave_out_len
|
90 |
|
|
always_ff @(posedge clk, posedge reset) begin
|
91 |
|
|
if (reset) begin
|
92 |
|
|
out_len <= {LEN_W{1'b0}};
|
93 |
|
|
end
|
94 |
|
|
else if (enable) begin
|
95 |
|
|
out_len <= (in_bursttype == FIXED) ? in_len : unit_len;
|
96 |
|
|
end
|
97 |
|
|
end
|
98 |
|
|
end
|
99 |
|
|
else // IS_AXI_SLAVE == 0
|
100 |
|
|
begin : non_axi_slave_out_len
|
101 |
|
|
always_comb begin
|
102 |
|
|
out_len = unit_len;
|
103 |
|
|
end
|
104 |
|
|
end
|
105 |
|
|
endgenerate
|
106 |
|
|
|
107 |
|
|
|
108 |
|
|
always_comb begin : proc_extend_burstwrap
|
109 |
|
|
extended_burstwrap_value = {{(PKT_ADDR_W - PKT_BURSTWRAP_W){in_burstwrap_reg[PKT_BURSTWRAP_W - 1]}}, in_burstwrap_value};
|
110 |
|
|
addr_incr_variable_size_value = {{(PKT_ADDR_W - 1){1'b0}}, 1'b1} << in_size_value;
|
111 |
|
|
end
|
112 |
|
|
|
113 |
|
|
// -------------------------------------------
|
114 |
|
|
// Address Converter
|
115 |
|
|
// -------------------------------------------
|
116 |
|
|
// Write: out_addr = in_addr at every cycle (pass through).
|
117 |
|
|
// Read: out_addr = in_addr at every new_burst. Subsequent addresses calculated by converter.
|
118 |
|
|
|
119 |
|
|
always_ff @(posedge clk, posedge reset) begin
|
120 |
|
|
if (reset) begin
|
121 |
|
|
next_incr_addr <= {PKT_ADDR_W{1'b0}};
|
122 |
|
|
out_addr <= {PKT_ADDR_W{1'b0}};
|
123 |
|
|
end
|
124 |
|
|
else if (enable) begin
|
125 |
|
|
next_incr_addr <= next_incr_addr + addr_incr_variable_size_value;
|
126 |
|
|
if (new_burst) begin
|
127 |
|
|
next_incr_addr <= in_addr + addr_incr_variable_size_value;
|
128 |
|
|
end
|
129 |
|
|
out_addr <= incr_wrapped_addr;
|
130 |
|
|
end
|
131 |
|
|
end
|
132 |
|
|
|
133 |
|
|
always_comb begin
|
134 |
|
|
incr_wrapped_addr = in_addr;
|
135 |
|
|
if (!new_burst) begin
|
136 |
|
|
// This formula calculates addresses of WRAP bursts and works perfectly fine for other burst types too.
|
137 |
|
|
incr_wrapped_addr = (in_addr_reg & ~extended_burstwrap_value) | (next_incr_addr & extended_burstwrap_value);
|
138 |
|
|
end
|
139 |
|
|
end
|
140 |
|
|
|
141 |
|
|
// -------------------------------------------
|
142 |
|
|
// Control Signals
|
143 |
|
|
// -------------------------------------------
|
144 |
|
|
|
145 |
|
|
// Determine the min_len.
|
146 |
|
|
// 1) FIXED read to AXI slave: One-time passthrough, therefore the min_len == in_len.
|
147 |
|
|
// 2) FIXED write to AXI slave: min_len == 1.
|
148 |
|
|
// 3) FIXED read/write to Avalon slave: min_len == 1.
|
149 |
|
|
// 4) RESERVED read/write to AXI/Avalon slave: min_len == 1.
|
150 |
|
|
wire [LEN_W - 1 : 0] min_len;
|
151 |
|
|
generate if (IS_AXI_SLAVE == 1)
|
152 |
|
|
begin : axi_slave_min_len
|
153 |
|
|
assign min_len = (!in_is_write && (in_bursttype == FIXED)) ? in_len : unit_len;
|
154 |
|
|
end
|
155 |
|
|
else // IS_AXI_SLAVE == 0
|
156 |
|
|
begin : non_axi_slave_min_len
|
157 |
|
|
assign min_len = unit_len;
|
158 |
|
|
end
|
159 |
|
|
endgenerate
|
160 |
|
|
|
161 |
|
|
// last_beat calculation.
|
162 |
|
|
wire last_beat = (remaining_len == min_len);
|
163 |
|
|
|
164 |
|
|
// next_len calculation.
|
165 |
|
|
always_comb begin
|
166 |
|
|
remaining_len = in_len;
|
167 |
|
|
if (!new_burst) remaining_len = next_len;
|
168 |
|
|
end
|
169 |
|
|
|
170 |
|
|
always_ff @(posedge clk, posedge reset) begin
|
171 |
|
|
if (reset) begin
|
172 |
|
|
next_len <= 1'b0;
|
173 |
|
|
end
|
174 |
|
|
else if (enable) begin
|
175 |
|
|
next_len <= remaining_len - unit_len;
|
176 |
|
|
end
|
177 |
|
|
end
|
178 |
|
|
|
179 |
|
|
// new_burst calculation.
|
180 |
|
|
always_ff @(posedge clk, posedge reset) begin
|
181 |
|
|
if (reset) begin
|
182 |
|
|
new_burst <= 1'b1;
|
183 |
|
|
end
|
184 |
|
|
else if (enable) begin
|
185 |
|
|
new_burst <= last_beat;
|
186 |
|
|
end
|
187 |
|
|
end
|
188 |
|
|
|
189 |
|
|
endmodule
|