212 lines
7.6 KiB
Systemverilog
212 lines
7.6 KiB
Systemverilog
// Copyright © 2019-2023
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
`include "VX_define.vh"
|
|
|
|
`TRACING_OFF
|
|
module VX_avs_adapter #(
|
|
parameter DATA_WIDTH = 1,
|
|
parameter ADDR_WIDTH = 1,
|
|
parameter BURST_WIDTH = 1,
|
|
parameter NUM_BANKS = 1,
|
|
parameter TAG_WIDTH = 1,
|
|
parameter RD_QUEUE_SIZE = 1,
|
|
parameter OUT_REG_REQ = 0,
|
|
parameter OUT_REG_RSP = 0
|
|
) (
|
|
input wire clk,
|
|
input wire reset,
|
|
|
|
// Memory request
|
|
input wire mem_req_valid,
|
|
input wire mem_req_rw,
|
|
input wire [DATA_WIDTH/8-1:0] mem_req_byteen,
|
|
input wire [ADDR_WIDTH-1:0] mem_req_addr,
|
|
input wire [DATA_WIDTH-1:0] mem_req_data,
|
|
input wire [TAG_WIDTH-1:0] mem_req_tag,
|
|
output wire mem_req_ready,
|
|
|
|
// Memory response
|
|
output wire mem_rsp_valid,
|
|
output wire [DATA_WIDTH-1:0] mem_rsp_data,
|
|
output wire [TAG_WIDTH-1:0] mem_rsp_tag,
|
|
input wire mem_rsp_ready,
|
|
|
|
// AVS bus
|
|
output wire [DATA_WIDTH-1:0] avs_writedata [NUM_BANKS],
|
|
input wire [DATA_WIDTH-1:0] avs_readdata [NUM_BANKS],
|
|
output wire [ADDR_WIDTH-1:0] avs_address [NUM_BANKS],
|
|
input wire avs_waitrequest [NUM_BANKS],
|
|
output wire avs_write [NUM_BANKS],
|
|
output wire avs_read [NUM_BANKS],
|
|
output wire [DATA_WIDTH/8-1:0] avs_byteenable [NUM_BANKS],
|
|
output wire [BURST_WIDTH-1:0] avs_burstcount [NUM_BANKS],
|
|
input wire avs_readdatavalid [NUM_BANKS]
|
|
);
|
|
localparam DATA_SIZE = DATA_WIDTH/8;
|
|
localparam RD_QUEUE_ADDR_WIDTH = `CLOG2(RD_QUEUE_SIZE+1);
|
|
localparam BANK_ADDRW = `LOG2UP(NUM_BANKS);
|
|
localparam LOG2_NUM_BANKS = `CLOG2(NUM_BANKS);
|
|
localparam BANK_OFFSETW = ADDR_WIDTH - LOG2_NUM_BANKS;
|
|
|
|
// Requests handling //////////////////////////////////////////////////////
|
|
|
|
wire [NUM_BANKS-1:0] req_queue_push, req_queue_pop;
|
|
wire [NUM_BANKS-1:0][TAG_WIDTH-1:0] req_queue_tag_out;
|
|
wire [NUM_BANKS-1:0] req_queue_going_full;
|
|
wire [NUM_BANKS-1:0][RD_QUEUE_ADDR_WIDTH-1:0] req_queue_size;
|
|
wire [BANK_ADDRW-1:0] req_bank_sel;
|
|
wire [BANK_OFFSETW-1:0] req_bank_off;
|
|
wire [NUM_BANKS-1:0] bank_req_ready;
|
|
|
|
if (NUM_BANKS > 1) begin
|
|
assign req_bank_sel = mem_req_addr[BANK_ADDRW-1:0];
|
|
end else begin
|
|
assign req_bank_sel = '0;
|
|
end
|
|
|
|
assign req_bank_off = mem_req_addr[ADDR_WIDTH-1:LOG2_NUM_BANKS];
|
|
|
|
for (genvar i = 0; i < NUM_BANKS; ++i) begin
|
|
assign req_queue_push[i] = mem_req_valid && ~mem_req_rw && bank_req_ready[i] && (req_bank_sel == i);
|
|
end
|
|
|
|
for (genvar i = 0; i < NUM_BANKS; ++i) begin
|
|
VX_pending_size #(
|
|
.SIZE (RD_QUEUE_SIZE)
|
|
) pending_size (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
.incr (req_queue_push[i]),
|
|
.decr (req_queue_pop[i]),
|
|
.full (req_queue_going_full[i]),
|
|
.size (req_queue_size[i]),
|
|
`UNUSED_PIN (empty)
|
|
);
|
|
`UNUSED_VAR (req_queue_size)
|
|
|
|
VX_fifo_queue #(
|
|
.DATAW (TAG_WIDTH),
|
|
.DEPTH (RD_QUEUE_SIZE)
|
|
) rd_req_queue (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
.push (req_queue_push[i]),
|
|
.pop (req_queue_pop[i]),
|
|
.data_in (mem_req_tag),
|
|
.data_out (req_queue_tag_out[i]),
|
|
`UNUSED_PIN (empty),
|
|
`UNUSED_PIN (full),
|
|
`UNUSED_PIN (alm_empty),
|
|
`UNUSED_PIN (alm_full),
|
|
`UNUSED_PIN (size)
|
|
);
|
|
end
|
|
|
|
for (genvar i = 0; i < NUM_BANKS; ++i) begin
|
|
wire valid_out;
|
|
wire rw_out;
|
|
wire [DATA_SIZE-1:0] byteen_out;
|
|
wire [BANK_OFFSETW-1:0] addr_out;
|
|
wire [DATA_WIDTH-1:0] data_out;
|
|
wire ready_out;
|
|
|
|
wire valid_out_w = mem_req_valid && ~req_queue_going_full[i] && (req_bank_sel == i);
|
|
wire ready_out_w;
|
|
|
|
VX_elastic_buffer #(
|
|
.DATAW (1 + DATA_SIZE + BANK_OFFSETW + DATA_WIDTH),
|
|
.SIZE (`OUT_REG_TO_EB_SIZE(OUT_REG_REQ)),
|
|
.OUT_REG (`OUT_REG_TO_EB_REG(OUT_REG_REQ))
|
|
) req_out_buf (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
.valid_in (valid_out_w),
|
|
.ready_in (ready_out_w),
|
|
.data_in ({mem_req_rw, mem_req_byteen, req_bank_off, mem_req_data}),
|
|
.data_out ({rw_out, byteen_out, addr_out, data_out}),
|
|
.valid_out (valid_out),
|
|
.ready_out (ready_out)
|
|
);
|
|
|
|
assign avs_read[i] = valid_out && ~rw_out;
|
|
assign avs_write[i] = valid_out && rw_out;
|
|
assign avs_address[i] = ADDR_WIDTH'(addr_out);
|
|
assign avs_byteenable[i] = byteen_out;
|
|
assign avs_writedata[i] = data_out;
|
|
assign avs_burstcount[i] = BURST_WIDTH'(1);
|
|
assign ready_out = ~avs_waitrequest[i];
|
|
|
|
assign bank_req_ready[i] = ready_out_w && ~req_queue_going_full[i];
|
|
end
|
|
|
|
if (NUM_BANKS > 1) begin
|
|
assign mem_req_ready = bank_req_ready[req_bank_sel];
|
|
end else begin
|
|
assign mem_req_ready = bank_req_ready;
|
|
end
|
|
|
|
// Responses handling /////////////////////////////////////////////////////
|
|
|
|
wire [NUM_BANKS-1:0] rsp_arb_valid_in;
|
|
wire [NUM_BANKS-1:0][DATA_WIDTH+TAG_WIDTH-1:0] rsp_arb_data_in;
|
|
wire [NUM_BANKS-1:0] rsp_arb_ready_in;
|
|
|
|
wire [NUM_BANKS-1:0][DATA_WIDTH-1:0] rsp_queue_data_out;
|
|
wire [NUM_BANKS-1:0] rsp_queue_empty;
|
|
|
|
for (genvar i = 0; i < NUM_BANKS; ++i) begin
|
|
VX_fifo_queue #(
|
|
.DATAW (DATA_WIDTH),
|
|
.DEPTH (RD_QUEUE_SIZE)
|
|
) rd_rsp_queue (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
.push (avs_readdatavalid[i]),
|
|
.pop (req_queue_pop[i]),
|
|
.data_in (avs_readdata[i]),
|
|
.data_out (rsp_queue_data_out[i]),
|
|
.empty (rsp_queue_empty[i]),
|
|
`UNUSED_PIN (full),
|
|
`UNUSED_PIN (alm_empty),
|
|
`UNUSED_PIN (alm_full),
|
|
`UNUSED_PIN (size)
|
|
);
|
|
end
|
|
|
|
for (genvar i = 0; i < NUM_BANKS; ++i) begin
|
|
assign rsp_arb_valid_in[i] = !rsp_queue_empty[i];
|
|
assign rsp_arb_data_in[i] = {rsp_queue_data_out[i], req_queue_tag_out[i]};
|
|
assign req_queue_pop[i] = rsp_arb_valid_in[i] && rsp_arb_ready_in[i];
|
|
end
|
|
|
|
VX_stream_arb #(
|
|
.NUM_INPUTS (NUM_BANKS),
|
|
.DATAW (DATA_WIDTH + TAG_WIDTH),
|
|
.ARBITER ("R"),
|
|
.OUT_REG (OUT_REG_RSP)
|
|
) rsp_arb (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
.valid_in (rsp_arb_valid_in),
|
|
.data_in (rsp_arb_data_in),
|
|
.ready_in (rsp_arb_ready_in),
|
|
.data_out ({mem_rsp_data, mem_rsp_tag}),
|
|
.valid_out (mem_rsp_valid),
|
|
.ready_out (mem_rsp_ready),
|
|
`UNUSED_PIN (sel_out)
|
|
);
|
|
|
|
endmodule
|
|
`TRACING_ON
|