1// 2// Copyright (c) 2023 Renesas Electronics Corporation 3// Copyright (c) 2010-2024 Antmicro 4// 5// This file is licensed under the MIT License. 6// Full license text is available in 'LICENSE'. 7// 8 9`timescale 1ns / 1ps 10 11import renode_pkg::renode_runtime, renode_pkg::LogWarning; 12 13module renode_ahb_subordinate #(int CosimToRenodeIndex = 0) ( 14 ref renode_runtime runtime, 15 renode_ahb_if bus 16); 17 import renode_ahb_pkg::*; 18 19 typedef logic [bus.AddressWidth-1:0] address_t; 20 typedef logic [bus.DataWidth-1:0] data_t; 21 wire clk = bus.hclk; 22 23 always @(runtime.peripherals[CosimToRenodeIndex].reset_assert_request) begin 24 bus.hresetn = 0; 25 bus.hresp = Okay; 26 bus.hreadyout = 1; 27 repeat (2) @(posedge clk); 28 runtime.peripherals[CosimToRenodeIndex].reset_assert_respond(); 29 end 30 31 always @(runtime.peripherals[CosimToRenodeIndex].reset_deassert_request) begin 32 bus.hresetn = 1; 33 repeat (2) @(posedge clk); 34 runtime.peripherals[CosimToRenodeIndex].reset_deassert_respond(); 35 end 36 37 always @(posedge clk) transaction(); 38 39 task static transaction(); 40 renode_pkg::address_t address; 41 renode_pkg::valid_bits_e valid_bits; 42 renode_pkg::data_t data; 43 bit is_error; 44 bit is_invalid; 45 transfer_direction_e direction; 46 47 wait_for_transfer(address, valid_bits, direction, is_invalid); 48 49 // The runtime.peripherals[CosimToRenodeIndex].read call may consume an unknown number of clock cycles. 50 // To to make the logic simpler both read and write transactions contain at least one cycle with a deasserted ready. 51 // It also ensures that address and data phases don't overlap between transactions. 52 bus.hreadyout <= 0; 53 @(posedge clk); 54 55 if (!is_invalid) begin 56 if (direction == Read) begin 57 runtime.peripherals[CosimToRenodeIndex].read(address, valid_bits, data, is_error); 58 bus.hrdata = data_t'(data & valid_bits); 59 if (is_error) runtime.connection.log(LogWarning, $sformatf("Unable to read data from Renode at address 'h%h", address)); 60 end else begin 61 runtime.peripherals[CosimToRenodeIndex].write(address, valid_bits, renode_pkg::data_t'(bus.hwdata) & valid_bits, is_error); 62 if (is_error) runtime.connection.log(LogWarning, $sformatf("Unable to write data to Renode at address 'h%h", address)); 63 end 64 end 65 66 if (is_invalid || is_error) begin 67 bus.hresp = Error; 68 @(posedge clk); // An error response should last two cycles. 69 bus.hreadyout <= 1; 70 end 71 else begin 72 bus.hresp = Okay; 73 bus.hreadyout <= 1; 74 end 75 endtask 76 77 78 task static wait_for_transfer(output renode_pkg::address_t address, output renode_pkg::valid_bits_e valid_bits, output transfer_direction_e direction, output bit is_invalid); 79 is_invalid = 0; 80 bus.hreadyout <= 1; 81 while (!bus.hready || bus.htrans == Idle || bus.htrans == Busy) @(posedge clk); 82 83 address = bus.haddr; 84 valid_bits = bus.transfer_size_to_valid_bits(bus.hsize); 85 direction = transfer_direction_e'(bus.hwrite); 86 if (!bus.are_valid_bits_supported(valid_bits)) begin 87 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)); 88 is_invalid = 1; 89 end 90 endtask 91endmodule 92