ibex/shared/rtl/bus.sv
Tobias Wölfel 0f2dc5c64a [rtl] Avoid latch creation
Following Verilator warning set default value to avoid the creation of a
latch.
2021-01-11 16:20:33 +01:00

125 lines
4.4 KiB
Systemverilog

// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
/**
* Simplistic Ibex bus implementation
*
* This module is designed for demo and simulation purposes, do not use it in
* a real-world system.
*
* This implementation doesn't handle the full bus protocol, but makes the
* following simplifying assumptions.
*
* - All devices (slaves) must respond in the next cycle after the request.
* - Host (master) arbitration is strictly priority based.
*/
module bus #(
parameter int NrDevices = 1,
parameter int NrHosts = 1,
parameter int DataWidth = 32,
parameter int AddressWidth = 32
) (
input clk_i,
input rst_ni,
// Hosts (masters)
input host_req_i [NrHosts],
output logic host_gnt_o [NrHosts],
input [AddressWidth-1:0] host_addr_i [NrHosts],
input host_we_i [NrHosts],
input [ DataWidth/8-1:0] host_be_i [NrHosts],
input [ DataWidth-1:0] host_wdata_i [NrHosts],
output logic host_rvalid_o [NrHosts],
output logic [ DataWidth-1:0] host_rdata_o [NrHosts],
output logic host_err_o [NrHosts],
// Devices (slaves)
output logic device_req_o [NrDevices],
output logic [AddressWidth-1:0] device_addr_o [NrDevices],
output logic device_we_o [NrDevices],
output logic [ DataWidth/8-1:0] device_be_o [NrDevices],
output logic [ DataWidth-1:0] device_wdata_o [NrDevices],
input device_rvalid_i [NrDevices],
input [ DataWidth-1:0] device_rdata_i [NrDevices],
input device_err_i [NrDevices],
// Device address map
input [AddressWidth-1:0] cfg_device_addr_base [NrDevices],
input [AddressWidth-1:0] cfg_device_addr_mask [NrDevices]
);
localparam int unsigned NumBitsHostSel = NrHosts > 1 ? $clog2(NrHosts) : 1;
localparam int unsigned NumBitsDeviceSel = NrDevices > 1 ? $clog2(NrDevices) : 1;
logic [NumBitsHostSel-1:0] host_sel_req, host_sel_resp;
logic [NumBitsDeviceSel-1:0] device_sel_req, device_sel_resp;
// Master select prio arbiter
always_comb begin
host_sel_req = '0;
for (integer host = NrHosts - 1; host >= 0; host = host - 1) begin
if (host_req_i[host]) begin
host_sel_req = NumBitsHostSel'(host);
end
end
end
// Device select
always_comb begin
device_sel_req = '0;
for (integer device = 0; device < NrDevices; device = device + 1) begin
if ((host_addr_i[host_sel_req] & cfg_device_addr_mask[device])
== cfg_device_addr_base[device]) begin
device_sel_req = NumBitsDeviceSel'(device);
end
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
host_sel_resp <= '0;
device_sel_resp <= '0;
end else begin
// Responses are always expected 1 cycle after the request
device_sel_resp <= device_sel_req;
host_sel_resp <= host_sel_req;
end
end
always_comb begin
for (integer device = 0; device < NrDevices; device = device + 1) begin
if (NumBitsDeviceSel'(device) == device_sel_req) begin
device_req_o[device] = host_req_i[host_sel_req];
device_we_o[device] = host_we_i[host_sel_req];
device_addr_o[device] = host_addr_i[host_sel_req];
device_wdata_o[device] = host_wdata_i[host_sel_req];
device_be_o[device] = host_be_i[host_sel_req];
end else begin
device_req_o[device] = 1'b0;
device_we_o[device] = 1'b0;
device_addr_o[device] = 'b0;
device_wdata_o[device] = 'b0;
device_be_o[device] = 'b0;
end
end
end
always_comb begin
for (integer host = 0; host < NrHosts; host = host + 1) begin
host_gnt_o[host] = 1'b0;
if (NumBitsHostSel'(host) == host_sel_resp) begin
host_rvalid_o[host] = device_rvalid_i[device_sel_resp];
host_err_o[host] = device_err_i[device_sel_resp];
host_rdata_o[host] = device_rdata_i[device_sel_resp];
end else begin
host_rvalid_o[host] = 1'b0;
host_err_o[host] = 1'b0;
host_rdata_o[host] = 'b0;
end
end
host_gnt_o[host_sel_req] = host_req_i[host_sel_req];
end
endmodule