| // |
| // Copyright (c) 2023 Renesas Electronics Corporation |
| // Copyright (c) 2010-2024 Antmicro |
| // |
| // This file is licensed under the MIT License. |
| // Full license text is available in 'LICENSE'. |
| // |
| |
| `timescale 1ns / 1ps |
| |
| import renode_pkg::renode_runtime, renode_pkg::bus_connection, renode_pkg::LogWarning; |
| |
| module renode_ahb_manager #(int RenodeToCosimIndex = 0) ( |
| ref renode_runtime runtime, |
| renode_ahb_if bus |
| ); |
| import renode_ahb_pkg::*; |
| |
| typedef logic [bus.AddressWidth-1:0] address_t; |
| typedef logic [bus.DataWidth-1:0] data_t; |
| wire clk = bus.hclk; |
| |
| always @(runtime.controllers[RenodeToCosimIndex].reset_assert_request) begin |
| bus.hresetn = 0; |
| bus.haddr = '0; |
| bus.htrans = Idle; |
| repeat (2) @(posedge clk); |
| runtime.controllers[RenodeToCosimIndex].reset_assert_respond(); |
| end |
| |
| always @(runtime.controllers[RenodeToCosimIndex].reset_deassert_request) begin |
| bus.hresetn = 1; |
| repeat (2) @(posedge clk); |
| runtime.controllers[RenodeToCosimIndex].reset_deassert_respond(); |
| end |
| |
| always @(runtime.controllers[RenodeToCosimIndex].read_transaction_request) read_transaction(); |
| always @(runtime.controllers[RenodeToCosimIndex].write_transaction_request) write_transaction(); |
| |
| task static write_transaction(); |
| renode_pkg::valid_bits_e valid_bits; |
| data_t data; |
| bit is_invalid; |
| |
| valid_bits = runtime.controllers[RenodeToCosimIndex].write_transaction_data_bits; |
| data = data_t'(runtime.controllers[RenodeToCosimIndex].write_transaction_data & valid_bits); |
| configure_transfer(runtime.controllers[RenodeToCosimIndex].write_transaction_address, valid_bits, Write, is_invalid); |
| if (is_invalid) begin |
| runtime.controllers[RenodeToCosimIndex].write_respond(is_invalid); |
| return; |
| end |
| |
| bus.hwstrb = bus.transfer_size_to_strobe(bus.valid_bits_to_transfer_size(valid_bits)); |
| bus.hwdata = data; |
| bus.htrans <= Idle; |
| |
| do @(posedge clk); while (!bus.hready); |
| runtime.controllers[RenodeToCosimIndex].write_respond(is_response_error(bus.hresp)); |
| endtask |
| |
| task static read_transaction(); |
| renode_pkg::valid_bits_e valid_bits; |
| data_t data; |
| bit is_invalid; |
| bit is_error; |
| |
| valid_bits = runtime.controllers[RenodeToCosimIndex].read_transaction_data_bits; |
| configure_transfer(runtime.controllers[RenodeToCosimIndex].read_transaction_address, valid_bits, Read, is_invalid); |
| if (is_invalid) begin |
| runtime.controllers[RenodeToCosimIndex].read_respond(renode_pkg::data_t'(0), is_invalid); |
| return; |
| end |
| |
| bus.htrans <= Idle; |
| |
| do @(posedge clk); while (!bus.hready); |
| data = bus.hrdata; |
| is_error = is_response_error(bus.hresp); |
| runtime.controllers[RenodeToCosimIndex].read_respond(renode_pkg::data_t'(data) & valid_bits, is_error); |
| endtask |
| |
| task static configure_transfer(renode_pkg::address_t address, renode_pkg::valid_bits_e valid_bits, transfer_direction_e direction, output logic is_invalid); |
| is_invalid = 0; |
| if (!bus.are_valid_bits_supported(valid_bits)) begin |
| is_invalid = 1; |
| runtime.connection.log(LogWarning, $sformatf("Unsupported transaction width of %d for AHB bus with width %d. No transaction will be performed.", renode_pkg::valid_bits_to_transaction_width(valid_bits), bus.DataWidth)); |
| return; |
| end |
| bus.hwrite = direction; |
| bus.hsize = bus.valid_bits_to_transfer_size(valid_bits); |
| bus.hburst = Single; |
| bus.haddr = address_t'(address); |
| bus.htrans <= NonSequential; |
| do @(posedge clk); while (!bus.hready); |
| endtask |
| |
| function static bit is_response_error(response_t response); |
| if (response == Okay) begin |
| return 0; |
| end |
| runtime.connection.log(LogWarning, $sformatf("Error response from a Subordinate: 'h%h", response)); |
| return 1; |
| endfunction |
| endmodule |