/* I2C_driver_multiplexer.v - Implements a multiplexer for the SoC side of I2C_driver.v This file is part of the 9086 project. Copyright (c) 2024 Efthymios Kritikos This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ module I2C_driver_multiplexer ( input wire clock, input wire reset_n, ////// INPUT 1 /////// input wire [6:0] IN1_ADDRESS, output reg IN1_BUSY, input wire IN1_TRANSACT, input wire IN1_DIR, output reg [15:0] IN1_I2C_DATA_READ, input wire [15:0] IN1_I2C_DATA_WRITE, input IN1_TRANS_WIDTH, input IN1_IGN_ACK, output reg IN1_ERROR, ////// INPUT 2 /////// input wire [6:0] IN2_ADDRESS, output reg IN2_BUSY, input wire IN2_TRANSACT, input wire IN2_DIR, output reg [15:0] IN2_I2C_DATA_READ, input wire [15:0] IN2_I2C_DATA_WRITE, input IN2_TRANS_WIDTH, input IN2_IGN_ACK, output reg IN2_ERROR, ////// OUTPUT /////// output wire [6:0] OUT_ADDRESS, input wire OUT_BUSY, output reg OUT_TRANSACT, output wire OUT_DIR, input wire [15:0] OUT_I2C_DATA_READ, output wire [15:0] OUT_I2C_DATA_WRITE, output OUT_TRANS_WIDTH, output wire OUT_IGN_ACK, input wire OUT_ERROR ); reg select; assign OUT_TRANS_WIDTH = select ? IN1_TRANS_WIDTH : IN2_TRANS_WIDTH; assign OUT_I2C_DATA_WRITE = select ? IN1_I2C_DATA_WRITE : IN2_I2C_DATA_WRITE; assign OUT_ADDRESS = select ? IN1_ADDRESS : IN2_ADDRESS; assign OUT_IGN_ACK = select ? IN1_IGN_ACK : IN2_IGN_ACK; assign OUT_DIR= select ? IN1_DIR : IN2_DIR; reg [1:0] STATE; reg SERVICED; always @(posedge clock)begin if(reset_n==1'b0)begin OUT_TRANSACT<=0; IN1_BUSY<=0; IN2_BUSY<=0; STATE<=2'd0; end else begin case(STATE) 2'd0:begin if(IN1_TRANSACT&&OUT_BUSY==1'b0)begin select<=1'b1; OUT_TRANSACT<=1; STATE<=2'd1; SERVICED<=1'b0; end else if(IN2_TRANSACT&&OUT_BUSY==1'b0)begin select<=1'b0; OUT_TRANSACT<=1; IN1_BUSY<=1; STATE<=2'd1; SERVICED<=1'b1; end if(OUT_BUSY==1'b0)begin IN1_BUSY<=0; IN2_BUSY<=0; end end 2'd1:begin if(OUT_BUSY==1'b1)begin STATE<=2'd0; OUT_TRANSACT<=0; end if(SERVICED==1'b0)begin IN1_BUSY<=1; end else begin IN2_BUSY<=1; end end default:begin STATE<=2'b0; end endcase end end always @(negedge OUT_BUSY)begin if(select)begin IN1_I2C_DATA_READ<=OUT_I2C_DATA_READ; IN1_ERROR<=OUT_ERROR; end else begin IN2_I2C_DATA_READ<=OUT_I2C_DATA_READ; IN2_ERROR<=OUT_ERROR; end end endmodule