mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
125 lines
4.4 KiB
Systemverilog
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
|