forked from pulp-platform/FlooNoC
-
Notifications
You must be signed in to change notification settings - Fork 0
/
floo_cut.sv
99 lines (86 loc) · 3.48 KB
/
floo_cut.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright 2022 ETH Zurich and University of Bologna.
// Solderpad Hardware License, Version 0.51, see LICENSE for details.
// SPDX-License-Identifier: SHL-0.51
//
// Tim Fischer <fischeti@iis.ee.ethz.ch>
`include "common_cells/registers.svh"
/// Spill registers to cut timing paths
module floo_cut #(
parameter int unsigned NumChannels = 32'd2, // 2 for bi-directional channels
parameter int unsigned NumVirtChannels = 32'd1,
parameter int unsigned NumPhysChannels = 32'd1,
parameter int unsigned NumCuts = 32'd1,
parameter type flit_t = logic
) (
input logic clk_i,
input logic rst_ni,
input logic [NumChannels-1:0][NumVirtChannels-1:0] valid_i,
output logic [NumChannels-1:0][NumVirtChannels-1:0] ready_o,
input flit_t[NumChannels-1:0][NumPhysChannels-1:0] data_i,
output logic [NumChannels-1:0][NumVirtChannels-1:0] valid_o,
input logic [NumChannels-1:0][NumVirtChannels-1:0] ready_i,
output flit_t[NumChannels-1:0][NumPhysChannels-1:0] data_o
);
if (NumCuts == 0) begin : gen_no_cuts
// Degenerate case
assign valid_o = valid_i;
assign ready_o = ready_i;
assign data_o = data_i;
end else begin : gen_floo_cuts
flit_t [NumChannels-1:0][NumCuts:0] data;
flit_t [NumChannels-1:0][NumCuts-1:0][NumVirtChannels-1:0] data_virt;
logic [NumChannels-1:0][NumCuts:0][NumVirtChannels-1:0] valid, ready;
logic [NumChannels-1:0][NumCuts-1:0][NumVirtChannels-1:0] valid_virt, ready_virt;
logic [NumChannels-1:0][NumCuts:0] rst_cut_ni;
assign rst_cut_ni[0][0] = rst_ni;
for (genvar c = 0; c < NumCuts; c++) begin : gen_rst_cut
// Reset pipe
`FFARN(rst_cut_ni[0][c+1], rst_cut_ni[0][c], 1'b0, clk_i, rst_ni)
if (NumChannels==2) begin : gen_back_rst_cut
assign rst_cut_ni[1][NumCuts-c] = rst_cut_ni[0][c+1];
end
end
for (genvar n = 0; n < NumChannels; n++) begin : gen_channel
// Assign input to first element
assign valid[n][0] = valid_i[n];
assign data[n][0] = data_i[n];
assign ready_o[n] = ready[n][0];
// Assign output to last element
assign valid_o[n] = valid[n][NumCuts];
assign ready[n][NumCuts] = ready_i[n];
assign data_o[n] = data[n][NumCuts];
for (genvar c = 0; c < NumCuts; c++) begin : gen_cut
for (genvar v = 0; v < NumVirtChannels; v++) begin : gen_virt
spill_register #(
.T ( flit_t ),
.Bypass ( 1'b0 )
) i_floo_spill_reg (
.clk_i ( clk_i ),
.rst_ni ( rst_cut_ni[n][c+1] ),
.valid_i ( valid[n][c][v] ),
.ready_o ( ready[n][c][v] ),
.data_i ( data[n][c] ),
.valid_o ( valid_virt[n][c][v] ),
.ready_i ( ready_virt[n][c][v] ),
.data_o ( data_virt[n][c][v] )
);
end
// TODO(fischeti): Is an arbiter necessary here?
floo_vc_arbiter #(
.NumVirtChannels(NumVirtChannels),
.NumPhysChannels(NumPhysChannels),
.flit_t(flit_t)
) i_floo_vc_arbiter (
.clk_i ( clk_i ),
.rst_ni ( rst_cut_ni[n][c+1] ),
.valid_i ( valid_virt[n][c] ),
.ready_o ( ready_virt[n][c] ),
.data_i ( data_virt[n][c] ),
.data_o ( data[n][c+1] ),
.valid_o ( valid[n][c+1] ),
.ready_i ( ready[n][c+1] )
);
end
end
end
endmodule