/**************************************
|
/**************************************
|
* Module: iport_regster_base
|
* Module: iport_regster_base
|
* Date:2020-02-21
|
* Date:2020-02-21
|
* Author: alireza
|
* Author: alireza
|
*
|
*
|
* Description:
|
* Description:
|
***************************************/
|
***************************************/
|
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
|
|
module flit_buffer_reg_base #(
|
module flit_buffer_reg_base #(
|
|
parameter NOC_ID = 0,
|
parameter V = 4,
|
parameter V = 4,
|
parameter B = 4, // buffer space :flit per VC
|
parameter B = 4, // buffer space :flit per VC
|
parameter Fpay = 32,
|
parameter Fpay = 32,
|
parameter PCK_TYPE = "MULTI_FLIT",
|
parameter PCK_TYPE = "MULTI_FLIT",
|
parameter DEBUG_EN = 1,
|
parameter DEBUG_EN = 1,
|
parameter C=1,
|
parameter C=1,
|
parameter DSTPw=4,
|
parameter DSTPw=4,
|
parameter SSA_EN="YES" // "YES" , "NO"
|
parameter SSA_EN="YES", // "YES" , "NO"
|
|
parameter CAST_TYPE="UNI_CAST"
|
|
|
)(
|
)(
|
din,
|
din,
|
vc_num_wr,
|
vc_num_wr,
|
wr_en,
|
wr_en,
|
vc_num_rd,
|
vc_num_rd,
|
rd_en,
|
rd_en,
|
dout,
|
dout,
|
vc_not_empty,
|
vc_not_empty,
|
reset,
|
reset,
|
clk,
|
clk,
|
|
|
//header flit dat
|
//header flit dat
|
class_all
|
class_all
|
|
|
);
|
);
|
|
|
function integer log2;
|
function integer log2;
|
input integer number; begin
|
input integer number; begin
|
log2=(number <=1) ? 1: 0;
|
log2=(number <=1) ? 1: 0;
|
while(2**log2<number) begin
|
while(2**log2<number) begin
|
log2=log2+1;
|
log2=log2+1;
|
end
|
end
|
end
|
end
|
endfunction // log2
|
endfunction // log2
|
|
|
localparam
|
localparam
|
Cw = (C>1)? log2(C): 1,
|
Cw = (C>1)? log2(C): 1,
|
Vw = log2(V),
|
Vw = log2(V),
|
REGFw = 2+Fpay, //Fpay + headr flags
|
REGFw = 2+Fpay, //Fpay + headr flags
|
Fw =2+V+Fpay,
|
Fw =2+V+Fpay,
|
VFw = V * Fw,
|
VFw = V * Fw,
|
VCw = V * Cw,
|
VCw = V * Cw,
|
VDSTPw = V * DSTPw;
|
VDSTPw = V * DSTPw;
|
|
|
input [Fw-1 :0] din; // Data in
|
input [Fw-1 :0] din; // Data in
|
input [V-1 :0] vc_num_wr;//write vertual chanel
|
input [V-1 :0] vc_num_wr;//write vertual chanel
|
input wr_en; // Write enable
|
input wr_en; // Write enable
|
|
|
|
|
input [V-1 :0] vc_num_rd;//read vertual chanel
|
input [V-1 :0] vc_num_rd;//read vertual chanel
|
input rd_en; // Read the next word
|
input rd_en; // Read the next word
|
|
|
|
|
output [Fw-1 :0] dout; // Data out
|
output [Fw-1 :0] dout; // Data out
|
output [V-1 :0] vc_not_empty;
|
output [V-1 :0] vc_not_empty;
|
input reset;
|
input reset;
|
input clk;
|
input clk;
|
|
|
output [VCw-1 : 0] class_all;
|
output [VCw-1 : 0] class_all;
|
// output [VDSTPw-1 :0 ] dest_port_encoded_all;
|
// output [VDSTPw-1 :0 ] dest_port_encoded_all;
|
// input [V-1 :0] ssa_rd;
|
// input [V-1 :0] ssa_rd;
|
|
|
wire [Fw-1 :0] dout_all [V-1 : 0]; // Data out
|
wire [Fw-1 :0] dout_all [V-1 : 0]; // Data out
|
wire [VCw-1 : 0] class_vc [V-1 : 0];
|
wire [VCw-1 : 0] class_vc [V-1 : 0];
|
reg [VCw-1 : 0] class_vc_next [V-1 : 0];
|
reg [VCw-1 : 0] class_vc_next [V-1 : 0];
|
wire [REGFw-1 : 0] flit_regs [V-1 : 0]; // a register array save the head of each quque
|
wire [REGFw-1 : 0] flit_regs [V-1 : 0]; // a register array save the head of each quque
|
reg [REGFw-1 : 0] flit_regs_next [V-1 : 0];
|
reg [REGFw-1 : 0] flit_regs_next [V-1 : 0];
|
reg [V-1 : 0] valid,valid_next; // if valid is asseted it shows the VC queue has a flit waiting to be sent
|
reg [V-1 : 0] valid,valid_next; // if valid is asseted it shows the VC queue has a flit waiting to be sent
|
|
|
wire [Fw-1 : 0] bram_dout;
|
wire [Fw-1 : 0] bram_dout;
|
wire [V-1 : 0] bram_not_empty;
|
wire [V-1 : 0] bram_not_empty;
|
wire bram_wr_en;
|
wire bram_wr_en;
|
wire [V-1 : 0] vc_num_wr_en,vc_num_rd_en;
|
wire [V-1 : 0] vc_num_wr_en,vc_num_rd_en;
|
|
|
wire[REGFw-1 : 0] flit_reg_mux_out;
|
wire[REGFw-1 : 0] flit_reg_mux_out;
|
wire flit_reg_mux_sel;
|
wire flit_reg_mux_sel;
|
reg flit_reg_mux_sel_delay;
|
reg flit_reg_mux_sel_delay;
|
wire [V-1 : 0] flit_reg_wr_en,pass_din_to_flit_reg,bram_empty;
|
wire [V-1 : 0] flit_reg_wr_en,pass_din_to_flit_reg,bram_empty;
|
wire [V-1 : 0] bram_out_is_valid;
|
wire [V-1 : 0] bram_out_is_valid;
|
wire bram_rd_en = |(vc_num_rd_en & bram_not_empty);
|
wire bram_rd_en = |(vc_num_rd_en & bram_not_empty);
|
|
|
//header flit info
|
//header flit info
|
wire [Cw-1:0] class_i;
|
wire [Cw-1:0] class_i;
|
wire [DSTPw-1 : 0] destport_i;
|
wire [DSTPw-1 : 0] destport_i;
|
|
|
wire [Vw-1: 0] vc_num_rd_bin;
|
wire [Vw-1: 0] vc_num_rd_bin;
|
reg [Vw-1 : 0] vc_num_rd_bin_delaied;
|
reg [Vw-1 : 0] vc_num_rd_bin_delaied;
|
reg [V-1 : 0] bram_out_is_valid_delaied,pass_din_to_flit_reg_delaied;
|
reg [V-1 : 0] bram_out_is_valid_delaied,pass_din_to_flit_reg_delaied;
|
|
|
reg [Fw-1 :0] din_reg;
|
reg [Fw-1 :0] din_reg;
|
|
|
assign bram_empty = ~bram_not_empty;
|
assign bram_empty = ~bram_not_empty;
|
assign vc_num_wr_en = (wr_en)? vc_num_wr : {V{1'b0}};
|
assign vc_num_wr_en = (wr_en)? vc_num_wr : {V{1'b0}};
|
assign vc_num_rd_en = (rd_en)? vc_num_rd : {V{1'b0}};
|
assign vc_num_rd_en = (rd_en)? vc_num_rd : {V{1'b0}};
|
|
|
assign pass_din_to_flit_reg = (vc_num_wr_en & ~valid)| // a write has been recived while the reg_flit is not valid
|
assign pass_din_to_flit_reg = (vc_num_wr_en & ~valid)| // a write has been recived while the reg_flit is not valid
|
(vc_num_wr_en & valid & bram_empty & vc_num_rd_en); //or its valid but bram is empty and its got a read request
|
(vc_num_wr_en & valid & bram_empty & vc_num_rd_en); //or its valid but bram is empty and its got a read request
|
|
|
|
|
assign flit_reg_mux_sel = | pass_din_to_flit_reg ;// 1 :din, 0: bram
|
assign flit_reg_mux_sel = | pass_din_to_flit_reg ;// 1 :din, 0: bram
|
//2-1 mux. Select between the bram and input flit.
|
//2-1 mux. Select between the bram and input flit.
|
assign flit_reg_mux_out = (flit_reg_mux_sel_delay)? {din[Fw-1:Fw-2],din_reg[Fpay-1:0]} : {bram_dout[Fw-1:Fw-2],bram_dout[Fpay-1:0]};
|
assign flit_reg_mux_out = (flit_reg_mux_sel_delay)? {din[Fw-1:Fw-2],din_reg[Fpay-1:0]} : {bram_dout[Fw-1:Fw-2],bram_dout[Fpay-1:0]};
|
assign bram_wr_en = (flit_reg_mux_sel)? 1'b0 :wr_en ; //make sure not write on the Bram if the reg fifo is empty
|
assign bram_wr_en = (flit_reg_mux_sel)? 1'b0 :wr_en ; //make sure not write on the Bram if the reg fifo is empty
|
|
|
assign flit_reg_wr_en = pass_din_to_flit_reg | bram_out_is_valid;
|
assign flit_reg_wr_en = pass_din_to_flit_reg | bram_out_is_valid;
|
|
|
assign bram_out_is_valid = (bram_rd_en )? (vc_num_rd & bram_not_empty): {V{1'b0}};
|
assign bram_out_is_valid = (bram_rd_en )? (vc_num_rd & bram_not_empty): {V{1'b0}};
|
|
|
|
|
|
|
|
|
one_hot_to_bin #(
|
one_hot_to_bin #(
|
.ONE_HOT_WIDTH(V),
|
.ONE_HOT_WIDTH(V),
|
.BIN_WIDTH(Vw)
|
.BIN_WIDTH(Vw)
|
)
|
)
|
conv
|
conv
|
(
|
(
|
.one_hot_code(vc_num_rd),
|
.one_hot_code(vc_num_rd),
|
.bin_code(vc_num_rd_bin)
|
.bin_code(vc_num_rd_bin)
|
);
|
);
|
|
|
always @(posedge clk) vc_num_rd_bin_delaied<=vc_num_rd_bin;
|
always @(posedge clk) vc_num_rd_bin_delaied<=vc_num_rd_bin;
|
always @(posedge clk) pass_din_to_flit_reg_delaied<=pass_din_to_flit_reg;
|
always @(posedge clk) pass_din_to_flit_reg_delaied<=pass_din_to_flit_reg;
|
assign dout = dout_all[vc_num_rd_bin_delaied];
|
assign dout = dout_all[vc_num_rd_bin_delaied];
|
|
|
|
|
flit_buffer #(
|
flit_buffer #(
|
|
.V(V),
|
.B(B),
|
.B(B),
|
.SSA_EN("NO")// should be "NO" even if SSA is enabled
|
.SSA_EN("NO"),// should be "NO" even if SSA is enabled
|
|
.Fw(Fw),
|
|
.PCK_TYPE(PCK_TYPE),
|
|
.CAST_TYPE(CAST_TYPE),
|
|
.DEBUG_EN(DEBUG_EN)
|
)
|
)
|
flit_buffer
|
flit_buffer
|
(
|
(
|
.din(din),
|
.din(din),
|
.vc_num_wr(vc_num_wr),
|
.vc_num_wr(vc_num_wr),
|
.wr_en(bram_wr_en),
|
.wr_en(bram_wr_en),
|
|
|
.vc_num_rd(vc_num_rd),
|
.vc_num_rd(vc_num_rd),
|
|
|
.rd_en(bram_rd_en),
|
.rd_en(bram_rd_en),
|
.dout(bram_dout),
|
.dout(bram_dout),
|
.vc_not_empty(bram_not_empty),
|
.vc_not_empty(bram_not_empty),
|
.reset(reset),
|
.reset(reset),
|
.clk(clk),
|
.clk(clk),
|
.ssa_rd({V{1'b0}}),
|
.ssa_rd({V{1'b0}}),
|
.multiple_dest(),
|
.multiple_dest(),
|
.sub_rd_ptr_ld(),
|
.sub_rd_ptr_ld(),
|
.flit_is_tail()
|
.flit_is_tail()
|
|
|
|
|
);
|
);
|
|
|
|
|
always @(posedge clk) begin
|
always @(posedge clk) begin
|
if(reset) begin
|
if(reset) begin
|
valid<={V{1'b0}};
|
valid<={V{1'b0}};
|
bram_out_is_valid_delaied<={V{1'b0}};
|
bram_out_is_valid_delaied<={V{1'b0}};
|
// din_reg<={Fw{1'b0}};
|
// din_reg<={Fw{1'b0}};
|
end
|
end
|
else begin
|
else begin
|
valid<=valid_next;
|
valid<=valid_next;
|
bram_out_is_valid_delaied<=bram_out_is_valid;
|
bram_out_is_valid_delaied<=bram_out_is_valid;
|
din_reg<=din;
|
din_reg<=din;
|
flit_reg_mux_sel_delay<=flit_reg_mux_sel;
|
flit_reg_mux_sel_delay<=flit_reg_mux_sel;
|
|
|
end
|
end
|
end
|
end
|
assign vc_not_empty = valid;
|
assign vc_not_empty = valid;
|
|
|
|
|
extract_header_flit_info #(
|
extract_header_flit_info #(
|
|
.NOC_ID(NOC_ID),
|
.DATA_w(0)
|
.DATA_w(0)
|
)
|
) header_extractor (
|
header_extractor
|
|
(
|
|
.flit_in({flit_reg_mux_out[REGFw-1:REGFw-2],flit_reg_wr_en,flit_reg_mux_out[Fpay-1 : 0]}),
|
.flit_in({flit_reg_mux_out[REGFw-1:REGFw-2],flit_reg_wr_en,flit_reg_mux_out[Fpay-1 : 0]}),
|
.flit_in_wr(),
|
.flit_in_wr(),
|
.class_o(class_i),
|
.class_o(class_i),
|
.destport_o(destport_i),
|
.destport_o(destport_i),
|
.dest_e_addr_o( ),
|
.dest_e_addr_o( ),
|
.src_e_addr_o( ),
|
.src_e_addr_o( ),
|
.vc_num_o(),
|
.vc_num_o(),
|
.hdr_flit_wr_o(),
|
.hdr_flit_wr_o(),
|
.hdr_flg_o(),
|
.hdr_flg_o(),
|
.tail_flg_o( ),
|
.tail_flg_o( ),
|
.weight_o( ),
|
.weight_o( ),
|
.be_o( ),
|
.be_o( ),
|
.data_o( )
|
.data_o( )
|
);
|
);
|
|
|
|
|
genvar i;
|
genvar i;
|
generate
|
generate
|
for (i = 0; i < V; i = i + 1) begin : Vblock
|
for (i = 0; i < V; i = i + 1) begin : Vblock
|
// assign dout_all[(i+1)*Fw-1 : i*Fw] = {flit_regs [i][REGFw-1: REGFw-2],i[V-1:0] ,flit_regs[i][Fpay-1:0]};
|
// assign dout_all[(i+1)*Fw-1 : i*Fw] = {flit_regs [i][REGFw-1: REGFw-2],i[V-1:0] ,flit_regs[i][Fpay-1:0]};
|
assign dout_all[i] = {flit_regs [i][REGFw-1: REGFw-2],i[V-1:0] ,flit_regs[i][Fpay-1:0]};
|
assign dout_all[i] = {flit_regs [i][REGFw-1: REGFw-2],i[V-1:0] ,flit_regs[i][Fpay-1:0]};
|
assign class_all[(i+1)*Cw-1 : i*Cw] = class_vc[i];
|
assign class_all[(i+1)*Cw-1 : i*Cw] = class_vc[i];
|
|
|
|
|
pronoc_register #(
|
pronoc_register #(
|
.W(REGFw)
|
.W(REGFw)
|
) reg1 (
|
) reg1 (
|
.in(flit_regs_next[i]),
|
.in(flit_regs_next[i]),
|
.reset(reset),
|
.reset(reset),
|
.clk(clk),
|
.clk(clk),
|
.out(flit_regs[i])
|
.out(flit_regs[i])
|
);
|
);
|
|
|
|
|
pronoc_register #(
|
pronoc_register #(
|
.W(Cw)
|
.W(Cw)
|
) reg2 (
|
) reg2 (
|
.in(class_vc_next[i]),
|
.in(class_vc_next[i]),
|
.reset(reset),
|
.reset(reset),
|
.clk(clk),
|
.clk(clk),
|
.out(class_vc[i])
|
.out(class_vc[i])
|
);
|
);
|
|
|
|
|
|
|
always @ (*)begin
|
always @ (*)begin
|
flit_regs_next[i] = flit_regs[i];
|
flit_regs_next[i] = flit_regs[i];
|
class_vc_next[i] = class_vc[i];
|
class_vc_next[i] = class_vc[i];
|
if(pass_din_to_flit_reg_delaied[i]) flit_regs_next[i] = {din[Fw-1:Fw-2],din_reg[Fpay-1:0]} ;
|
if(pass_din_to_flit_reg_delaied[i]) flit_regs_next[i] = {din[Fw-1:Fw-2],din_reg[Fpay-1:0]} ;
|
if(bram_out_is_valid_delaied[i]) flit_regs_next[i] = {bram_dout[Fw-1:Fw-2],bram_dout[Fpay-1:0]};
|
if(bram_out_is_valid_delaied[i]) flit_regs_next[i] = {bram_dout[Fw-1:Fw-2],bram_dout[Fpay-1:0]};
|
if(flit_reg_wr_en[i] & flit_reg_mux_out[REGFw-1] ) class_vc_next[i] = class_i;// writing header flit
|
if(flit_reg_wr_en[i] & flit_reg_mux_out[REGFw-1] ) class_vc_next[i] = class_i;// writing header flit
|
end
|
end
|
|
|
|
|
|
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
/*
|
/*
|
if( ROUTE_TYPE=="DETERMINISTIC") begin : dtrmn_dest
|
if( ROUTE_TYPE=="DETERMINISTIC") begin : dtrmn_dest
|
always @ (`pronoc_clk_reset_edge )begin
|
always @ (`pronoc_clk_reset_edge )begin
|
if(`pronoc_reset)begin
|
if(`pronoc_reset)begin
|
|
|
end else begin
|
end else begin
|
dest_port_encoded_vc[i]<= destport_in_encoded;
|
dest_port_encoded_vc[i]<= destport_in_encoded;
|
end
|
end
|
end//always
|
end//always
|
end else begin : adptv_dest
|
end else begin : adptv_dest
|
|
|
|
|
*/
|
*/
|
|
|
|
|
|
|
|
|
always @(*) begin
|
always @(*) begin
|
valid_next[i] = valid[i];
|
valid_next[i] = valid[i];
|
if(flit_reg_wr_en[i]) valid_next[i] =1'b1;
|
if(flit_reg_wr_en[i]) valid_next[i] =1'b1;
|
else if( bram_empty[i] & vc_num_rd_en[i]) valid_next[i] =1'b0;
|
else if( bram_empty[i] & vc_num_rd_en[i]) valid_next[i] =1'b0;
|
end
|
end
|
|
|
end //for
|
end //for
|
|
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
// if(TOPOLOGY=="FATTREE" && ROUTE_NAME == "NCA_STRAIGHT_UP") begin : fat
|
// if(TOPOLOGY=="FATTREE" && ROUTE_NAME == "NCA_STRAIGHT_UP") begin : fat
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
/*
|
/*
|
fattree_destport_up_select #(
|
fattree_destport_up_select #(
|
.K(T1),
|
.K(T1),
|
.SW_LOC(SW_LOC)
|
.SW_LOC(SW_LOC)
|
)
|
)
|
static_sel
|
static_sel
|
(
|
(
|
.destport_in(destport_in),
|
.destport_in(destport_in),
|
.destport_o(destport_in_encoded)
|
.destport_o(destport_in_encoded)
|
);
|
);
|
|
|
end else begin : other
|
end else begin : other
|
assign destport_in_encoded = destport_in;
|
assign destport_in_encoded = destport_in;
|
end
|
end
|
|
|
*/
|
*/
|
endgenerate
|
endgenerate
|
|
|
|
|
|
|
// Update header flit info registers
|
// Update header flit info registers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endmodule
|
endmodule
|
|
|
|
|
|
|
|
|