Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
// Stream fork: Connects the input stream (ready-valid) handshake to *all* of `NumOup` output stream
// handshakes. For each input stream handshake, every output stream handshakes exactly once. The
// input stream only handshakes when all output streams have handshaked, but the output streams do
// not have to handshake simultaneously.
//
// This module has no data ports because stream data does not need to be forked: the data of the
// input stream can just be applied at all output streams.
`include "common_cells/assertions.svh"
`include "common_cells/registers.svh"
module cc_stream_fork #(
parameter int unsigned NumOup = 1 // Synopsys DC requires a default value for parameters.
) (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic clr_i, // Synchronous clear active high
input logic valid_i,
output logic ready_o,
output logic [NumOup-1:0] valid_o,
input logic [NumOup-1:0] ready_i
);
typedef enum logic {READY, WAIT} state_t;
logic [NumOup-1:0] oup_ready, all_ones;
state_t inp_state_d, inp_state_q;
// Input control FSM
always_comb begin
// ready_o = 1'b0;
inp_state_d = inp_state_q;
unique case (inp_state_q)
READY: begin
if (valid_i) begin
if (valid_o == all_ones && ready_i == all_ones) begin
// If handshake on all outputs, handshake on input.
ready_o = 1'b1;
end else begin
ready_o = 1'b0;
// Otherwise, wait for inputs that did not handshake yet.
inp_state_d = WAIT;
end
end else begin
ready_o = 1'b0;
end
end
WAIT: begin
if (valid_i && oup_ready == all_ones) begin
ready_o = 1'b1;
inp_state_d = READY;
end else begin
ready_o = 1'b0;
end
end
default: begin
inp_state_d = READY;
ready_o = 1'b0;
end
endcase
end
`FFARNC(inp_state_q, inp_state_d, clr_i, READY, clk_i, rst_ni)
// Output control FSM
for (genvar i = 0; i < NumOup; i++) begin: gen_oup_state
state_t oup_state_d, oup_state_q;
always_comb begin
oup_ready[i] = 1'b1;
valid_o[i] = 1'b0;
oup_state_d = oup_state_q;
unique case (oup_state_q)
READY: begin
if (valid_i) begin
valid_o[i] = 1'b1;
if (ready_i[i]) begin // Output handshake
if (!ready_o) begin // No input handshake yet
oup_state_d = WAIT;
end
end else begin // No output handshake
oup_ready[i] = 1'b0;
end
end
end
WAIT: begin
if (valid_i && ready_o) begin // Input handshake
oup_state_d = READY;
end
end
default: begin
oup_state_d = READY;
end
endcase
end
`FFARNC(oup_state_q, oup_state_d, clr_i, READY, clk_i, rst_ni)
end
assign all_ones = '1; // Synthesis fix for Vivado, which does not correctly compute the width
// of the '1 literal when assigned to a port of parametrized width.
`ifndef COMMON_CELLS_ASSERTS_OFF
`ASSERT_INIT(n_oup_0, NumOup >= 1, "Number of outputs must be at least 1!")
`endif
endmodule
4f62c83c0This file is pinned to the selected release. Download the original to open it in your design tool.