1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
|
//////////////////////////////////////////////////////////////////////////////////
// Copyright Ettus Research LLC
// The ZYNQ FIFO configuration arbiter:
// - holds configuration memory addresses
// - setting and readback for slave state machines
// - stream of memory addresses for master state machines
//////////////////////////////////////////////////////////////////////////////////
module zf_arbiter
#(
parameter STREAMS_WIDTH = 2,
parameter CMDFIFO_DEPTH = 4,
parameter PAGE_WIDTH = 16
)
(
input clk,
input rst,
//------------------------------------------------------------------
//-- settings interface
//------------------------------------------------------------------
input [31:0] set_addr,
input [31:0] set_data,
input set_stb,
//------------------------------------------------------------------
//-- readback interface
//------------------------------------------------------------------
input [31:0] rb_addr,
output [31:0] rb_data,
input rb_stb,
//------------------------------------------------------------------
//-- fifo interactive interface
//------------------------------------------------------------------
output [71:0] cmd_tdata,
output cmd_tvalid,
input cmd_tready,
input [7:0] sts_tdata,
input sts_tvalid,
output sts_tready,
//------------------------------------------------------------------
//-- which stream to process? externally provided
//------------------------------------------------------------------
input [STREAMS_WIDTH-1:0] ext_stream,
input stream_valid,
output [31:0] debug
);
////////////////////////////////////////////////////////////////////////
///////////////////////////// Begin R T L //////////////////////////////
////////////////////////////////////////////////////////////////////////
localparam NUM_STREAMS = (1 << STREAMS_WIDTH);
reg [STREAMS_WIDTH-1:0] which_stream;
//readback mux assignment
reg [31:0] rb_data_i [NUM_STREAMS-1:0];
assign rb_data = rb_data_i[rb_addr[STREAMS_WIDTH+4:5]];
//cmd + sts fifo mux signals
wire [72:0] cmd_data_i [NUM_STREAMS-1:0];
assign cmd_tdata = cmd_data_i[which_stream];
wire cmd_tvalid_i [NUM_STREAMS-1:0];
wire sts_tready_i [NUM_STREAMS-1:0];
////////////////////////////////////////////////////////////////////
// state machine for driving fifo arbitration
////////////////////////////////////////////////////////////////////
localparam STATE_SET_WHICH_STREAM = 0;
localparam STATE_ASSERT_DO_CMD = 1;
localparam STATE_ASSERT_DO_STS = 2;
localparam STATE_SOME_IDLE = 3;
reg [1:0] state;
always @(posedge clk) begin
if (rst) begin
state <= STATE_SET_WHICH_STREAM;
which_stream <= 0;
end
else case (state)
STATE_SET_WHICH_STREAM: begin
if (cmd_tvalid_i[ext_stream]) state <= STATE_ASSERT_DO_CMD;
which_stream <= ext_stream;
end
STATE_ASSERT_DO_CMD: begin
if (cmd_tvalid && cmd_tready) state <= STATE_ASSERT_DO_STS;
end
STATE_ASSERT_DO_STS: begin
if (sts_tvalid && sts_tready) state <= STATE_SOME_IDLE;
end
STATE_SOME_IDLE: begin
state <= STATE_SET_WHICH_STREAM;
end
default: state <= STATE_SET_WHICH_STREAM;
endcase //state
end
////////////////////////////////////////////////////////////////////
// memory map + fifos for the host control/status
////////////////////////////////////////////////////////////////////
wire do_cmd = (state == STATE_ASSERT_DO_CMD);
wire do_sts = (state == STATE_ASSERT_DO_STS);
assign cmd_tvalid = do_cmd && cmd_tvalid_i[which_stream];
assign sts_tready = do_sts && sts_tready_i[which_stream];
genvar i;
generate
for (i=0; i < NUM_STREAMS; i=i+1) begin : stream_circuit
wire [PAGE_WIDTH-3:0] set_addr32 = set_addr[PAGE_WIDTH-1:2];
wire write_clear = set_stb && (set_addr32 == (0 + i*8));
wire write_addr = set_stb && (set_addr32 == (1 + i*8));
wire write_size = set_stb && (set_addr32 == (2 + i*8));
wire write_sts_rdy = set_stb && (set_addr32 == (3 + i*8));
wire write_sts = set_stb && (set_addr32 == (4 + i*8));
wire [PAGE_WIDTH-3:0] rb_addr32 = rb_addr[PAGE_WIDTH-1:2];
wire read_sig = (rb_addr32 == (0 + i*8));
wire read_status = (rb_addr32 == (4 + i*8));
wire read_sts_occupied = (rb_addr32 == (5 + i*8));
wire read_cmd_addr_space = (rb_addr32 == (6 + i*8));
wire read_cmd_size_space = (rb_addr32 == (7 + i*8));
wire [15:0] sts_occupied, cmd_addr_space, cmd_size_space;
wire [7:0] sts_readback;
wire [15:0] this_stream = i;
always @* begin
if (read_sig) rb_data_i[i] <= {16'hACE0, this_stream};
else if (read_status) rb_data_i[i] <= {24'b0, sts_readback};
else if (read_sts_occupied) rb_data_i[i] <= {16'b0, sts_occupied};
else if (read_cmd_addr_space) rb_data_i[i] <= {16'b0, cmd_addr_space};
else if (read_cmd_size_space) rb_data_i[i] <= {16'b0, cmd_size_space};
else rb_data_i[i] <= 32'h12345678;
end
wire [31:0] cmd_addr, cmd_size;
wire cmd_addr_tvalid, cmd_size_tvalid;
assign cmd_data_i[i][32+39:32+36] = 4'b0; //reserved - 0?
assign cmd_data_i[i][32+35:64] = i[3:0]; //tag
assign cmd_data_i[i][63:32] = cmd_addr;
assign cmd_data_i[i][31] = 1'b0; //DRE ReAlignment Request
assign cmd_data_i[i][30] = 1'b1; //always EOF for tlast stream
assign cmd_data_i[i][29:24] = 6'b0; //DRE Stream Alignment
assign cmd_data_i[i][23] = 1'b0; //reserved - 0?
assign cmd_data_i[i][22:0] = cmd_size[22:0];
axi_fifo #(.WIDTH(32), .SIZE(CMDFIFO_DEPTH)) crl_addr_fifo
(
.clk(clk), .reset(rst), .clear(write_clear),
.i_tdata(set_data), .i_tvalid(write_addr), .i_tready(), .space(cmd_addr_space),
.o_tdata(cmd_addr), .o_tvalid(cmd_addr_tvalid), .o_tready(cmd_tready && do_cmd && (which_stream == i)), .occupied()
);
axi_fifo #(.WIDTH(32), .SIZE(CMDFIFO_DEPTH)) crl_size_fifo
(
.clk(clk), .reset(rst), .clear(write_clear),
.i_tdata(set_data), .i_tvalid(write_size), .i_tready(), .space(cmd_size_space),
.o_tdata(cmd_size), .o_tvalid(cmd_size_tvalid), .o_tready(cmd_tready && do_cmd && (which_stream == i)), .occupied()
);
assign cmd_tvalid_i[i] = cmd_addr_tvalid && cmd_size_tvalid && stream_valid;
wire dm_sts_tvalid = sts_tvalid && do_sts && (which_stream == i);
axi_fifo #(.WIDTH(8), .SIZE(CMDFIFO_DEPTH)) sts_fifo
(
.clk(clk), .reset(rst), .clear(),
.i_tdata((write_sts)?set_data[7:0]:sts_tdata), .i_tvalid(dm_sts_tvalid || write_sts), .i_tready(sts_tready_i[i]), .space(),
.o_tdata(sts_readback), .o_tvalid(), .o_tready(write_sts_rdy), .occupied(sts_occupied)
);
end
endgenerate
assign debug[1:0] = state;
assign debug[4] = cmd_tvalid;
assign debug[5] = cmd_tready;
assign debug[6] = sts_tvalid;
assign debug[7] = sts_tready;
assign debug[8] = ext_stream;
assign debug[9] = which_stream;
assign debug[15] = rb_addr[STREAMS_WIDTH+4:5];
endmodule //zf_arbiter
|