//modified cra ring node for altera crossing clock bridge connection.
module modified_cra_ring #(
  parameter integer RING_ADDR_W = 32,
  parameter integer CRA_ADDR_W = 32,
  parameter integer DATA_W = 32,
  parameter integer ID_W = 3,
  parameter logic[ID_W-1:0] ID = 3'd0
)
(
    // clock/reset
    input logic clk,
    input logic rst_n,

    // avalon-master port
    output logic avm_read,
    output logic avm_write,
    output logic [CRA_ADDR_W-1:0] avm_addr,
    output logic [DATA_W/8-1:0] avm_byteena,
    output logic [DATA_W-1:0] avm_writedata,
    input logic [DATA_W-1:0] avm_readdata,
    input logic avm_readdatavalid,
    input logic avm_waitrequest, //extra logic to adapt the crossing clock bridges;
    // ring-in
    input logic ri_read,
    input logic ri_write,
    input logic [RING_ADDR_W+ID_W-1:0] ri_addr,
    input logic [DATA_W-1:0] ri_data,
    input logic [DATA_W/8-1:0] ri_byteena, 
    input logic ri_datavalid,
    
    // ring-out
    output logic ro_read,
    output logic ro_write,
    output logic [RING_ADDR_W+ID_W-1:0] ro_addr,
    output logic [DATA_W-1:0] ro_data,
    output logic [DATA_W/8-1:0] ro_byteena,
    output logic ro_datavalid
);

// The avalon master connection
logic id_match;
generate if(ID_W == 0)
  assign id_match = 1'b1;
else
  assign id_match = (ri_addr[RING_ADDR_W+ID_W-1:RING_ADDR_W] == ID);
endgenerate

//Notice: fifo of the clock bridge is a 
always@(posedge clk or negedge rst_n) begin
  if(rst_n == 1'b0) begin
    avm_read <= 1'b0;
    avm_write <= 1'b0;
    avm_addr <= 'x;
    avm_byteena <= 'x;
    avm_writedata <= 'x;
  end else begin
    // When avm_waitrequest is asserted, control signals must be constant:
    avm_read <= avm_waitrequest ? avm_read : ( ri_read && id_match );
    avm_write <= avm_waitrequest ? avm_write : ( ri_write && id_match );
    avm_addr <= ri_addr[CRA_ADDR_W-1:0]; // Throw away upper address bits
    avm_byteena <= ri_byteena;
    avm_writedata <= ri_data; //if avm waitrequest is 1, just holds; vice versa.
  end
end

// The ring output
//Since we add waitrequest, we need to prevent the cra rings from the previous logic to transfer data during the hold state:
//in cra_root module, wait request is asserted if ri_datavalid is false;
//Hence our avm_waitrequest should be used to control ro_datavalid!
always@(posedge clk or negedge rst_n) begin
  if(rst_n == 1'b0) begin
    ro_read <= 1'b0;
    ro_write <= 1'b0;
    ro_datavalid <= 1'b0;
    ro_addr <= 'x;
    ro_data <= 'x;
    ro_byteena <= 'x;
  end else begin
    //One thing to think about is the period between the assertion of the waitrequest and the deassertion of signals at the last ring.
    //If we have N rings, the period will be N clk cycles. Data and address will be propagated until the same. This is true if both 
    //crossing bridges hold at the same time.
    //What would happen if original N rings contain N different data and addresses? Hence data and address need holding during waitrequest;
    ro_read <= ri_read && !id_match;  
    ro_write <= ri_write && !id_match;
    ro_addr <= avm_waitrequest ? ro_addr : ri_addr;
    ro_data <= avm_waitrequest ? ro_data : ( avm_readdatavalid ? avm_readdata : ri_data ); 
    ro_byteena <= ri_byteena;
    ro_datavalid <= (avm_readdatavalid | ri_datavalid) && !avm_waitrequest; //Here we modify the ro_datavalid
  end
end
endmodule