`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
|
|
/**************************************
|
/**************************************
|
* Module: debug
|
* Module: debug
|
* Date:2019-04-01
|
* Date:2019-04-01
|
* Author: alireza
|
* Author: alireza
|
*
|
*
|
* Description: this file contain modules which are used for error checking/debiging of the NoC.
|
* Description: this file contain modules which are used for error checking/debiging of the NoC.
|
***************************************/
|
***************************************/
|
|
|
//check if flits are recived in correct order in a VC
|
//check if flits are recived in correct order in a VC
|
|
|
module check_flit_chanel_type_is_in_order #(
|
module check_flit_chanel_type_is_in_order #(
|
parameter V=4,
|
parameter V=4,
|
parameter PCK_TYPE = "SINGLE_FLIT",
|
parameter PCK_TYPE = "SINGLE_FLIT",
|
parameter MIN_PCK_SIZE=2
|
parameter MIN_PCK_SIZE=2
|
)(
|
)(
|
hdr_flg_in,
|
hdr_flg_in,
|
flit_in_wr,
|
flit_in_wr,
|
tail_flg_in,
|
tail_flg_in,
|
vc_num_in,
|
vc_num_in,
|
clk,
|
clk,
|
reset
|
reset
|
|
|
);
|
);
|
|
|
input clk, reset;
|
input clk, reset;
|
input hdr_flg_in, tail_flg_in, flit_in_wr;
|
input hdr_flg_in, tail_flg_in, flit_in_wr;
|
input [V-1 : 0] vc_num_in;
|
input [V-1 : 0] vc_num_in;
|
|
|
|
|
|
|
|
|
wire [V-1 : 0] vc_num_hdr_wr, vc_num_tail_wr,vc_num_bdy_wr ;
|
wire [V-1 : 0] vc_num_hdr_wr, vc_num_tail_wr,vc_num_bdy_wr ;
|
wire [V-1 : 0] hdr_passed;
|
wire [V-1 : 0] hdr_passed;
|
reg [V-1 : 0] hdr_passed_next;
|
reg [V-1 : 0] hdr_passed_next;
|
wire [V-1 : 0] single_flit_pck;
|
wire [V-1 : 0] single_flit_pck;
|
|
|
assign vc_num_hdr_wr =(hdr_flg_in & flit_in_wr) ? vc_num_in : 0;
|
assign vc_num_hdr_wr =(hdr_flg_in & flit_in_wr) ? vc_num_in : 0;
|
assign vc_num_tail_wr =(tail_flg_in & flit_in_wr)? vc_num_in : 0;
|
assign vc_num_tail_wr =(tail_flg_in & flit_in_wr)? vc_num_in : 0;
|
assign vc_num_bdy_wr =({hdr_flg_in,tail_flg_in} == 2'b00 && flit_in_wr)? vc_num_in : 0;
|
assign vc_num_bdy_wr =({hdr_flg_in,tail_flg_in} == 2'b00 && flit_in_wr)? vc_num_in : 0;
|
assign single_flit_pck = vc_num_hdr_wr & vc_num_tail_wr;
|
assign single_flit_pck = vc_num_hdr_wr & vc_num_tail_wr;
|
always @(*)begin
|
always @(*)begin
|
hdr_passed_next = (hdr_passed | vc_num_hdr_wr) & ~vc_num_tail_wr;
|
hdr_passed_next = (hdr_passed | vc_num_hdr_wr) & ~vc_num_tail_wr;
|
end
|
end
|
|
|
// synthesis translate_off
|
// synthesis translate_off
|
|
|
pronoc_register #(
|
pronoc_register #(
|
.W(V)
|
.W(V)
|
) reg2 (
|
) reg2 (
|
.in(hdr_passed_next),
|
.in(hdr_passed_next),
|
.reset(reset),
|
.reset(reset),
|
.clk(clk),
|
.clk(clk),
|
.out(hdr_passed)
|
.out(hdr_passed)
|
);
|
);
|
|
|
|
|
|
|
always @ (posedge clk ) begin
|
always @ (posedge clk ) begin
|
if(( hdr_passed & vc_num_hdr_wr)>0 )begin
|
if(( hdr_passed & vc_num_hdr_wr)>0 )begin
|
$display("%t ERROR: a header flit is received in an active IVC %m",$time);
|
$display("%t ERROR: a header flit is received in an active IVC %m",$time);
|
$finish;
|
$finish;
|
end
|
end
|
if((~hdr_passed & vc_num_tail_wr & ~single_flit_pck )>0 ) begin
|
if((~hdr_passed & vc_num_tail_wr & ~single_flit_pck )>0 ) begin
|
$display("%t ERROR: a tail flit is received in an inactive IVC %m",$time);
|
$display("%t ERROR: a tail flit is received in an inactive IVC %m",$time);
|
$finish;
|
$finish;
|
end
|
end
|
if ((~hdr_passed & vc_num_bdy_wr )>0)begin
|
if ((~hdr_passed & vc_num_bdy_wr )>0)begin
|
$display("%t ERROR: a body flit is received in an inactive IVC %m",$time);
|
$display("%t ERROR: a body flit is received in an inactive IVC %m",$time);
|
$finish;
|
$finish;
|
end
|
end
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
if((PCK_TYPE == "SINGLE_FLIT") & flit_in_wr & ~(hdr_flg_in & tail_flg_in )) begin
|
if((PCK_TYPE == "SINGLE_FLIT") & flit_in_wr & ~(hdr_flg_in & tail_flg_in )) begin
|
$display("%t ERROR: both tail and header flit flags must be asserted in SINGLE_FLIT mode %m",$time);
|
$display("%t ERROR: both tail and header flit flags must be asserted in SINGLE_FLIT mode %m",$time);
|
$finish;
|
$finish;
|
end
|
end
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
if( (MIN_PCK_SIZE !=1) & flit_in_wr & hdr_flg_in & tail_flg_in ) begin
|
if( (MIN_PCK_SIZE !=1) & flit_in_wr & hdr_flg_in & tail_flg_in ) begin
|
$display("%t ERROR: A single flit packet is injected while the minimum packet size is set to %d. %m",$time,MIN_PCK_SIZE);
|
$display("%t ERROR: A single flit packet is injected while the minimum packet size is set to %d. %m",$time,MIN_PCK_SIZE);
|
$finish;
|
$finish;
|
end
|
end
|
//TODO check that the injected packet size meets the MIN_PCK_SIZE
|
//TODO check that the injected packet size meets the MIN_PCK_SIZE
|
|
|
end//always
|
end//always
|
// synthesis translate_on
|
// synthesis translate_on
|
endmodule
|
endmodule
|
|
|
|
|
|
|
|
|
|
|
|
|
module debug_mesh_tori_route_ckeck #(
|
module debug_mesh_tori_route_ckeck #(
|
parameter T1=4,
|
parameter T1=4,
|
parameter T2=4,
|
parameter T2=4,
|
parameter T3=4,
|
parameter T3=4,
|
parameter ROUTE_TYPE = "FULL_ADAPTIVE",
|
parameter ROUTE_TYPE = "FULL_ADAPTIVE",
|
parameter V=4,
|
parameter V=4,
|
parameter AVC_ATOMIC_EN=1,
|
parameter AVC_ATOMIC_EN=1,
|
parameter SW_LOC = 0,
|
parameter SW_LOC = 0,
|
parameter [V-1 : 0] ESCAP_VC_MASK= 4'b0001,
|
parameter [V-1 : 0] ESCAP_VC_MASK= 4'b0001,
|
parameter TOPOLOGY="MESH",
|
parameter TOPOLOGY="MESH",
|
parameter DSTPw=4,
|
parameter DSTPw=4,
|
parameter RAw=4,
|
parameter RAw=4,
|
parameter EAw=4,
|
parameter EAw=4,
|
parameter DAw=EAw
|
parameter DAw=EAw
|
)(
|
)(
|
reset,
|
reset,
|
clk,
|
clk,
|
hdr_flg_in,
|
hdr_flg_in,
|
flit_in_wr,
|
flit_in_wr,
|
flit_is_tail,
|
flit_is_tail,
|
ivc_num_getting_sw_grant,
|
ivc_num_getting_sw_grant,
|
vc_num_in,
|
vc_num_in,
|
current_r_addr,
|
current_r_addr,
|
dest_e_addr_in,
|
dest_e_addr_in,
|
src_e_addr_in,
|
src_e_addr_in,
|
destport_in
|
destport_in
|
);
|
);
|
|
|
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
|
|
|
|
|
input reset,clk;
|
input reset,clk;
|
input hdr_flg_in , flit_in_wr;
|
input hdr_flg_in , flit_in_wr;
|
input [V-1 : 0] vc_num_in, flit_is_tail, ivc_num_getting_sw_grant;
|
input [V-1 : 0] vc_num_in, flit_is_tail, ivc_num_getting_sw_grant;
|
input [RAw-1 : 0] current_r_addr;
|
input [RAw-1 : 0] current_r_addr;
|
input [DAw-1 : 0] dest_e_addr_in;
|
input [DAw-1 : 0] dest_e_addr_in;
|
input [EAw-1 : 0] src_e_addr_in;
|
input [EAw-1 : 0] src_e_addr_in;
|
input [DSTPw-1 : 0] destport_in;
|
input [DSTPw-1 : 0] destport_in;
|
|
|
localparam
|
localparam
|
NX = T1,
|
NX = T1,
|
NY = T2,
|
NY = T2,
|
RXw = log2(NX), // number of node in x axis
|
RXw = log2(NX), // number of node in x axis
|
RYw = log2(NY),
|
RYw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE") ? 1 : log2(NY),
|
EXw = log2(NX), // number of node in x axis
|
EXw = log2(NX), // number of node in x axis
|
EYw = log2(NY); // number of node in y axis
|
EYw = (TOPOLOGY=="RING" || TOPOLOGY == "LINE") ? 1 : log2(NY); // number of node in y axis
|
|
|
|
|
wire [RXw-1 : 0] current_x;
|
wire [RXw-1 : 0] current_x;
|
wire [EXw-1 : 0] x_dst_in,x_src_in;
|
wire [EXw-1 : 0] x_dst_in,x_src_in;
|
wire [RYw-1 : 0] current_y;
|
wire [RYw-1 : 0] current_y;
|
wire [EYw-1 : 0] y_dst_in,y_src_in;
|
wire [EYw-1 : 0] y_dst_in,y_src_in;
|
|
|
mesh_tori_router_addr_decode #(
|
mesh_tori_router_addr_decode #(
|
.TOPOLOGY(TOPOLOGY),
|
.TOPOLOGY(TOPOLOGY),
|
.T1(T1),
|
.T1(T1),
|
.T2(T2),
|
.T2(T2),
|
.T3(T3),
|
.T3(T3),
|
.RAw(RAw)
|
.RAw(RAw)
|
)
|
)
|
r_addr_decode
|
r_addr_decode
|
(
|
(
|
.r_addr(current_r_addr),
|
.r_addr(current_r_addr),
|
.rx(current_x),
|
.rx(current_x),
|
.ry(current_y),
|
.ry(current_y),
|
.valid()
|
.valid()
|
);
|
);
|
|
|
mesh_tori_endp_addr_decode #(
|
mesh_tori_endp_addr_decode #(
|
.TOPOLOGY(TOPOLOGY),
|
.TOPOLOGY(TOPOLOGY),
|
.T1(T1),
|
.T1(T1),
|
.T2(T2),
|
.T2(T2),
|
.T3(T3),
|
.T3(T3),
|
.EAw(EAw)
|
.EAw(EAw)
|
)
|
)
|
dst_addr_decode
|
dst_addr_decode
|
(
|
(
|
.e_addr(dest_e_addr_in),
|
.e_addr(dest_e_addr_in),
|
.ex(x_dst_in),
|
.ex(x_dst_in),
|
.ey(y_dst_in),
|
.ey(y_dst_in),
|
.el( ),
|
.el( ),
|
.valid()
|
.valid()
|
);
|
);
|
|
|
mesh_tori_endp_addr_decode #(
|
mesh_tori_endp_addr_decode #(
|
.TOPOLOGY(TOPOLOGY),
|
.TOPOLOGY(TOPOLOGY),
|
.T1(T1),
|
.T1(T1),
|
.T2(T2),
|
.T2(T2),
|
.T3(T3),
|
.T3(T3),
|
.EAw(EAw)
|
.EAw(EAw)
|
)
|
)
|
src_addr_decode
|
src_addr_decode
|
(
|
(
|
.e_addr(src_e_addr_in),
|
.e_addr(src_e_addr_in),
|
.ex(x_src_in),
|
.ex(x_src_in),
|
.ey(y_src_in),
|
.ey(y_src_in),
|
.el( ),
|
.el( ),
|
.valid()
|
.valid()
|
);
|
);
|
|
|
|
|
localparam
|
localparam
|
LOCAL = 0,
|
LOCAL = 0,
|
NORTH = 2,
|
NORTH = 2,
|
SOUTH = 4;
|
SOUTH = 4;
|
// synthesis translate_off
|
// synthesis translate_off
|
generate
|
generate
|
|
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
if(ROUTE_TYPE == "DETERMINISTIC")begin :dtrmn
|
if(ROUTE_TYPE == "DETERMINISTIC")begin :dtrmn
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
|
|
|
|
always@( posedge clk)begin
|
always@( posedge clk)begin
|
if(flit_in_wr & hdr_flg_in )
|
if(flit_in_wr & hdr_flg_in )
|
if( destport_in[1:0]==2'b11) begin
|
if( destport_in[1:0]==2'b11) begin
|
$display ( "%t\t ERROR: destport port %x is illegal for determistic routing. %m",$time,destport_in );
|
$display ( "%t\t ERROR: destport port %x is illegal for determistic routing. %m",$time,destport_in );
|
$finish;
|
$finish;
|
end
|
end
|
end//if
|
end//if
|
end//always
|
end//always
|
|
|
|
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
if(ROUTE_TYPE == "FULL_ADAPTIVE")begin :full_adpt
|
if(ROUTE_TYPE == "FULL_ADAPTIVE")begin :full_adpt
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
|
|
wire [V-1 : 0] not_empty;
|
wire [V-1 : 0] not_empty;
|
reg [V-1 : 0] not_empty_next;
|
reg [V-1 : 0] not_empty_next;
|
|
|
pronoc_register #(
|
pronoc_register #(
|
.W(V)
|
.W(V)
|
) reg2 (
|
) reg2 (
|
.in(not_empty_next),
|
.in(not_empty_next),
|
.reset(reset),
|
.reset(reset),
|
.clk(clk),
|
.clk(clk),
|
.out(not_empty)
|
.out(not_empty)
|
);
|
);
|
|
|
always@(*) begin
|
always@(*) begin
|
not_empty_next = not_empty;
|
not_empty_next = not_empty;
|
if(hdr_flg_in & flit_in_wr) begin
|
if(hdr_flg_in & flit_in_wr) begin
|
not_empty_next = not_empty | vc_num_in;
|
not_empty_next = not_empty | vc_num_in;
|
end//hdr_wr_in
|
end//hdr_wr_in
|
if((flit_is_tail & ivc_num_getting_sw_grant)>0)begin
|
if((flit_is_tail & ivc_num_getting_sw_grant)>0)begin
|
not_empty_next = not_empty & ~ivc_num_getting_sw_grant;
|
not_empty_next = not_empty & ~ivc_num_getting_sw_grant;
|
end//tail wr out
|
end//tail wr out
|
end//always
|
end//always
|
|
|
always@( posedge clk ) begin
|
always@( posedge clk ) begin
|
if(hdr_flg_in & flit_in_wr) begin
|
if(hdr_flg_in & flit_in_wr) begin
|
if( ((AVC_ATOMIC_EN==1)&& (SW_LOC!= LOCAL)) || (SW_LOC== NORTH) || (SW_LOC== SOUTH) )begin
|
if( ((AVC_ATOMIC_EN==1)&& (SW_LOC!= LOCAL)) || (SW_LOC== NORTH) || (SW_LOC== SOUTH) )begin
|
if((vc_num_in & ~ESCAP_VC_MASK)>0) begin // adaptive VCs
|
if((vc_num_in & ~ESCAP_VC_MASK)>0) begin // adaptive VCs
|
if( (not_empty & vc_num_in)>0) $display("%t :Error AVC allocated nonatomicly in %d port %m",$time,SW_LOC);
|
if( (not_empty & vc_num_in)>0) $display("%t :Error AVC allocated nonatomicly in %d port %m",$time,SW_LOC);
|
end
|
end
|
end//( AVC_ATOMIC_EN || SW_LOC== NORTH || SW_LOC== SOUTH )
|
end//( AVC_ATOMIC_EN || SW_LOC== NORTH || SW_LOC== SOUTH )
|
if((vc_num_in & ESCAP_VC_MASK)>0 && (SW_LOC== SOUTH || SW_LOC== NORTH) ) begin // escape vc
|
if((vc_num_in & ESCAP_VC_MASK)>0 && (SW_LOC== SOUTH || SW_LOC== NORTH) ) begin // escape vc
|
// if (a & b) $display("%t :Error EVC allocation violate subfunction routing rules %m",$time);
|
// if (a & b) $display("%t :Error EVC allocation violate subfunction routing rules %m",$time);
|
if ((current_x - x_dst_in) !=0 && (current_y- y_dst_in) !=0) $display("%t :Error EVC allocation violate subfunction routing rules src_x=%d src_y=%d dst_x%d dst_y=%d %m",$time,x_src_in, y_src_in, x_dst_in,y_dst_in);
|
if ((current_x - x_dst_in) !=0 && (current_y- y_dst_in) !=0) $display("%t :Error EVC allocation violate subfunction routing rules src_x=%d src_y=%d dst_x%d dst_y=%d %m",$time,x_src_in, y_src_in, x_dst_in,y_dst_in);
|
end
|
end
|
end//hdr_wr_in
|
end//hdr_wr_in
|
end//always
|
end//always
|
end //SW_LOC
|
end //SW_LOC
|
|
|
|
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
if(TOPOLOGY=="MESH")begin :mesh
|
if(TOPOLOGY=="MESH")begin :mesh
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
wire [EXw-1 : 0] low_x,high_x;
|
wire [EXw-1 : 0] low_x,high_x;
|
wire [EYw-1 : 0] low_y,high_y;
|
wire [EYw-1 : 0] low_y,high_y;
|
|
|
|
|
|
|
assign low_x = (x_src_in < x_dst_in)? x_src_in : x_dst_in;
|
assign low_x = (x_src_in < x_dst_in)? x_src_in : x_dst_in;
|
assign low_y = (y_src_in < y_dst_in)? y_src_in : y_dst_in;
|
assign low_y = (y_src_in < y_dst_in)? y_src_in : y_dst_in;
|
assign high_x = (x_src_in < x_dst_in)? x_dst_in : x_src_in;
|
assign high_x = (x_src_in < x_dst_in)? x_dst_in : x_src_in;
|
assign high_y = (y_src_in < y_dst_in)? y_dst_in : y_src_in;
|
assign high_y = (y_src_in < y_dst_in)? y_dst_in : y_src_in;
|
|
|
|
|
always@( posedge clk)begin
|
always@( posedge clk)begin
|
if((current_x <low_x) | (current_x > high_x) | (current_y <low_y) | (current_y > high_y) )
|
if((current_x <low_x) | (current_x > high_x) | (current_y <low_y) | (current_y > high_y) )
|
if(flit_in_wr & hdr_flg_in )begin
|
if(flit_in_wr & hdr_flg_in )begin
|
$display ( "%t\t ERROR: non_minimal routing %m",$time );
|
$display ( "%t\t ERROR: non_minimal routing %m",$time );
|
$finish;
|
$finish;
|
end
|
end
|
|
|
end
|
end
|
|
|
|
|
end// mesh
|
end// mesh
|
endgenerate
|
endgenerate
|
|
|
// synthesis translate_on
|
// synthesis translate_on
|
|
|
endmodule
|
endmodule
|
|
|
|
|
module debug_mesh_edges #(
|
module debug_mesh_edges #(
|
parameter T1=2,
|
parameter T1=2,
|
parameter T2=2,
|
parameter T2=2,
|
parameter T3=3,
|
parameter T3=3,
|
parameter T4=3,
|
parameter T4=3,
|
parameter RAw=4,
|
parameter RAw=4,
|
parameter P=5
|
parameter P=5
|
)(
|
)(
|
clk,
|
clk,
|
current_r_addr,
|
current_r_addr,
|
flit_out_wr_all
|
flit_out_wr_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
|
|
|
input clk;
|
input clk;
|
input [RAw-1 : 0] current_r_addr;
|
input [RAw-1 : 0] current_r_addr;
|
input [P-1 : 0] flit_out_wr_all;
|
input [P-1 : 0] flit_out_wr_all;
|
|
|
localparam
|
localparam
|
RXw = log2(T1), // number of node in x axis
|
RXw = log2(T1), // number of node in x axis
|
RYw = log2(T2); // number of node in y axis
|
RYw = log2(T2); // number of node in y axis
|
|
|
|
|
wire [RXw-1 : 0] current_rx;
|
wire [RXw-1 : 0] current_rx;
|
wire [RYw-1 : 0] current_ry;
|
wire [RYw-1 : 0] current_ry;
|
|
|
mesh_tori_router_addr_decode #(
|
mesh_tori_router_addr_decode #(
|
.TOPOLOGY("MESH"),
|
.TOPOLOGY("MESH"),
|
.T1(T1),
|
.T1(T1),
|
.T2(T2),
|
.T2(T2),
|
.T3(T3),
|
.T3(T3),
|
.RAw(RAw)
|
.RAw(RAw)
|
)
|
)
|
addr_decode
|
addr_decode
|
(
|
(
|
.r_addr(current_r_addr),
|
.r_addr(current_r_addr),
|
.rx(current_rx),
|
.rx(current_rx),
|
.ry(current_ry),
|
.ry(current_ry),
|
.valid()
|
.valid()
|
);
|
);
|
|
|
|
|
localparam
|
localparam
|
EAST = 1,
|
EAST = 1,
|
NORTH = 2,
|
NORTH = 2,
|
WEST = 3,
|
WEST = 3,
|
SOUTH = 4;
|
SOUTH = 4;
|
// synthesis translate_off
|
// synthesis translate_off
|
always @(posedge clk) begin
|
always @(posedge clk) begin
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
if(current_rx == {RXw{1'b0}} && flit_out_wr_all[WEST]) $display ( "%t\t ERROR: a packet is going to the WEST in a router located in first column in mesh topology %m",$time );
|
if(current_rx == {RXw{1'b0}} && flit_out_wr_all[WEST]) $display ( "%t\t ERROR: a packet is going to the WEST in a router located in first column in mesh topology %m",$time );
|
if(current_rx == T1-1 && flit_out_wr_all[EAST]) $display ( "%t\t ERROR: a packet is going to the EAST in a router located in last column in mesh topology %m",$time );
|
if(current_rx == T1-1 && flit_out_wr_all[EAST]) $display ( "%t\t ERROR: a packet is going to the EAST in a router located in last column in mesh topology %m",$time );
|
if(current_ry == {RYw{1'b0}} && flit_out_wr_all[NORTH])$display ( "%t\t ERROR: a packet is going to the NORTH in a router located in first row in mesh topology %m",$time );
|
if(current_ry == {RYw{1'b0}} && flit_out_wr_all[NORTH])$display ( "%t\t ERROR: a packet is going to the NORTH in a router located in first row in mesh topology %m",$time );
|
if(current_ry == T2-1 && flit_out_wr_all[SOUTH])$display ( "%t\t ERROR: a packet is going to the SOUTH in a router located in last row in mesh topology %m",$time);
|
if(current_ry == T2-1 && flit_out_wr_all[SOUTH])$display ( "%t\t ERROR: a packet is going to the SOUTH in a router located in last row in mesh topology %m",$time);
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
end//always
|
end//always
|
// synthesis translate_on
|
// synthesis translate_on
|
endmodule
|
endmodule
|
|
|
|
|
/*******************
|
/*******************
|
*
|
*
|
* *****************/
|
* *****************/
|
|
|
module check_destination_addr #(
|
module check_destination_addr #(
|
|
parameter NOC_ID=0,
|
parameter TOPOLOGY = "MESH",
|
parameter TOPOLOGY = "MESH",
|
parameter T1=2,
|
parameter T1=2,
|
parameter T2=2,
|
parameter T2=2,
|
parameter T3=2,
|
parameter T3=2,
|
parameter T4=2,
|
parameter T4=2,
|
parameter EAw=2,
|
parameter EAw=2,
|
parameter DAw=2,
|
parameter DAw=2,
|
parameter SELF_LOOP_EN="NO",
|
parameter SELF_LOOP_EN="NO",
|
parameter CAST_TYPE = "UNICAST",
|
parameter CAST_TYPE = "UNICAST",
|
parameter NE=8
|
parameter NE=8
|
)(
|
)(
|
dest_is_valid,
|
dest_is_valid,
|
dest_e_addr,
|
dest_e_addr,
|
current_e_addr
|
current_e_addr
|
);
|
);
|
|
|
input [DAw-1 : 0] dest_e_addr;
|
input [DAw-1 : 0] dest_e_addr;
|
input [EAw-1 : 0] current_e_addr;
|
input [EAw-1 : 0] current_e_addr;
|
output dest_is_valid;
|
output dest_is_valid;
|
|
|
// general rules
|
// general rules
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
wire valid_dst = (SELF_LOOP_EN == "NO")? dest_e_addr != current_e_addr : 1'b1;
|
wire valid_dst = (SELF_LOOP_EN == "NO")? dest_e_addr != current_e_addr : 1'b1;
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
wire valid;
|
wire valid;
|
generate
|
generate
|
if(CAST_TYPE != "UNICAST") begin
|
if(CAST_TYPE != "UNICAST") begin
|
|
|
wire [NE-1 : 0] dest_mcast_all_endp;
|
wire [NE-1 : 0] dest_mcast_all_endp;
|
|
|
mcast_dest_list_decode decode (
|
mcast_dest_list_decode #(
|
|
.NOC_ID(NOC_ID)
|
|
) decode (
|
.dest_e_addr(dest_e_addr),
|
.dest_e_addr(dest_e_addr),
|
.dest_o(dest_mcast_all_endp),
|
.dest_o(dest_mcast_all_endp),
|
.row_has_any_dest( ),
|
.row_has_any_dest( ),
|
.is_unicast()
|
.is_unicast()
|
);
|
);
|
//wire valid_dst_multi_r1 = (SELF_LOOP_EN == "NO") ? ~(dest_mcast_all_endp[current_e_addr] == 1'b1) : 1'b1;
|
//wire valid_dst_multi_r1 = (SELF_LOOP_EN == "NO") ? ~(dest_mcast_all_endp[current_e_addr] == 1'b1) : 1'b1;
|
wire valid_dst_multi_r2 = ~(dest_mcast_all_endp == {NE{1'b0}}); // there should be atleast one asserted destination
|
wire valid_dst_multi_r2 = ~(dest_mcast_all_endp == {NE{1'b0}}); // there should be atleast one asserted destination
|
|
|
assign dest_is_valid = valid_dst_multi_r2;// & valid_dst_multi_r1 ;
|
assign dest_is_valid = valid_dst_multi_r2;// & valid_dst_multi_r1 ;
|
end else
|
end else
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
if(TOPOLOGY=="MESH" || TOPOLOGY == "TORUS" || TOPOLOGY=="RING" || TOPOLOGY == "LINE") begin : mesh
|
if(TOPOLOGY=="MESH" || TOPOLOGY == "TORUS" || TOPOLOGY=="RING" || TOPOLOGY == "LINE") begin : mesh
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
mesh_tori_endp_addr_decode #(
|
mesh_tori_endp_addr_decode #(
|
.TOPOLOGY(TOPOLOGY),
|
.TOPOLOGY(TOPOLOGY),
|
.T1(T1),
|
.T1(T1),
|
.T2(T2),
|
.T2(T2),
|
.T3(T3),
|
.T3(T3),
|
.EAw(EAw)
|
.EAw(EAw)
|
)
|
)
|
mesh_tori_endp_addr_decode(
|
mesh_tori_endp_addr_decode(
|
.e_addr(dest_e_addr),
|
.e_addr(dest_e_addr),
|
.ex(),
|
.ex(),
|
.ey(),
|
.ey(),
|
.el(),
|
.el(),
|
.valid(valid)
|
.valid(valid)
|
);
|
);
|
assign dest_is_valid = valid_dst & valid;
|
assign dest_is_valid = valid_dst & valid;
|
|
|
end else begin : tree
|
end else begin : tree
|
assign dest_is_valid = valid_dst;
|
assign dest_is_valid = valid_dst;
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
endmodule
|
endmodule
|
|
|
|
|
|
|
module endp_addr_encoder #(
|
module endp_addr_encoder #(
|
parameter TOPOLOGY ="MESH",
|
parameter TOPOLOGY ="MESH",
|
parameter T1=4,
|
parameter T1=4,
|
parameter T2=4,
|
parameter T2=4,
|
parameter T3=4,
|
parameter T3=4,
|
parameter EAw=4,
|
parameter EAw=4,
|
parameter NE=16
|
parameter NE=16
|
)
|
)
|
(
|
(
|
id,
|
id,
|
code
|
code
|
);
|
);
|
|
|
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 NEw= log2(NE);
|
localparam NEw= log2(NE);
|
|
|
input [NEw-1 :0] id;
|
input [NEw-1 :0] id;
|
output [EAw-1 : 0] code;
|
output [EAw-1 : 0] code;
|
|
|
generate
|
generate
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
if(TOPOLOGY == "FATTREE" || TOPOLOGY == "TREE" ) begin : tree
|
if(TOPOLOGY == "FATTREE" || TOPOLOGY == "TREE" ) begin : tree
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
fattree_addr_encoder #(
|
fattree_addr_encoder #(
|
.K(T1),
|
.K(T1),
|
.L(T2)
|
.L(T2)
|
)
|
)
|
addr_encoder
|
addr_encoder
|
(
|
(
|
.id(id),
|
.id(id),
|
.code(code)
|
.code(code)
|
);
|
);
|
|
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
end else if (TOPOLOGY == "MESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin :tori
|
end else if (TOPOLOGY == "MESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin :tori
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
mesh_tori_addr_encoder #(
|
mesh_tori_addr_encoder #(
|
.NX(T1),
|
.NX(T1),
|
.NY(T2),
|
.NY(T2),
|
.NL(T3),
|
.NL(T3),
|
.NE(NE),
|
.NE(NE),
|
.EAw(EAw),
|
.EAw(EAw),
|
.TOPOLOGY(TOPOLOGY)
|
.TOPOLOGY(TOPOLOGY)
|
)
|
)
|
addr_encoder
|
addr_encoder
|
(
|
(
|
.id(id),
|
.id(id),
|
.code(code)
|
.code(code)
|
);
|
);
|
end else if (TOPOLOGY == "FMESH") begin :fmesh
|
end else if (TOPOLOGY == "FMESH") begin :fmesh
|
fmesh_addr_encoder #(
|
fmesh_addr_encoder #(
|
.NX(T1),
|
.NX(T1),
|
.NY(T2),
|
.NY(T2),
|
.NL(T3),
|
.NL(T3),
|
.NE(NE),
|
.NE(NE),
|
.EAw(EAw)
|
.EAw(EAw)
|
)
|
)
|
addr_encoder
|
addr_encoder
|
(
|
(
|
.id(id),
|
.id(id),
|
.code(code)
|
.code(code)
|
);
|
);
|
|
|
end else begin :custom
|
end else begin :custom
|
|
|
assign code =id;
|
assign code =id;
|
|
|
end
|
end
|
endgenerate
|
endgenerate
|
endmodule
|
endmodule
|
|
|
|
|
module endp_addr_decoder #(
|
module endp_addr_decoder #(
|
parameter TOPOLOGY ="MESH",
|
parameter TOPOLOGY ="MESH",
|
parameter T1=4,
|
parameter T1=4,
|
parameter T2=4,
|
parameter T2=4,
|
parameter T3=4,
|
parameter T3=4,
|
parameter EAw=4,
|
parameter EAw=4,
|
parameter NE=16
|
parameter NE=16
|
)
|
)
|
(
|
(
|
id,
|
id,
|
code
|
code
|
);
|
);
|
|
|
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 NEw= log2(NE);
|
localparam NEw= log2(NE);
|
|
|
output [NEw-1 :0] id;
|
output [NEw-1 :0] id;
|
input [EAw-1 : 0] code;
|
input [EAw-1 : 0] code;
|
|
|
generate
|
generate
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
if(TOPOLOGY == "FATTREE" || TOPOLOGY == "TREE" ) begin : tree
|
if(TOPOLOGY == "FATTREE" || TOPOLOGY == "TREE" ) begin : tree
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
fattree_addr_decoder #(
|
fattree_addr_decoder #(
|
.K(T1),
|
.K(T1),
|
.L(T2)
|
.L(T2)
|
|
|
)decoder(
|
)decoder(
|
.id(id),
|
.id(id),
|
.code(code)
|
.code(code)
|
);
|
);
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
end else if (TOPOLOGY == "MESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin :tori
|
end else if (TOPOLOGY == "MESH" || TOPOLOGY == "TORUS" || TOPOLOGY == "RING" || TOPOLOGY == "LINE") begin :tori
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
mesh_tori_addr_coder #(
|
mesh_tori_addr_coder #(
|
|
.TOPOLOGY(TOPOLOGY),
|
.NX (T1 ),
|
.NX (T1 ),
|
.NY (T2 ),
|
.NY (T2 ),
|
.NL (T3 ),
|
.NL (T3 ),
|
.NE (NE ),
|
.NE (NE ),
|
.EAw (EAw )
|
.EAw (EAw )
|
) addr_coder (
|
) addr_coder (
|
.id (id ),
|
.id (id ),
|
.code (code ));
|
.code (code ));
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
end else if (TOPOLOGY == "FMESH") begin :fmesh
|
end else if (TOPOLOGY == "FMESH") begin :fmesh
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
fmesh_addr_coder #(
|
fmesh_addr_coder #(
|
.NX(T1),
|
.NX(T1),
|
.NY(T2),
|
.NY(T2),
|
.NL(T3),
|
.NL(T3),
|
.NE(NE),
|
.NE(NE),
|
.EAw(EAw)
|
.EAw(EAw)
|
)
|
)
|
addr_coder
|
addr_coder
|
(
|
(
|
.id(id),
|
.id(id),
|
.code(code)
|
.code(code)
|
);
|
);
|
|
|
end else begin :custom
|
end else begin :custom
|
|
|
assign id = code;
|
assign id = code;
|
|
|
end
|
end
|
endgenerate
|
endgenerate
|
endmodule
|
endmodule
|
|
|
|
|
module check_pck_size #(
|
module check_pck_size #(
|
|
parameter NOC_ID=0,
|
parameter V=2,
|
parameter V=2,
|
parameter MIN_PCK_SIZE=2,
|
parameter MIN_PCK_SIZE=2,
|
parameter Fw=36,
|
parameter Fw=36,
|
parameter DAw=4,
|
parameter DAw=4,
|
parameter CAST_TYPE="UNICAST",
|
parameter CAST_TYPE="UNICAST",
|
parameter NE=4,
|
parameter NE=4,
|
parameter B=4,
|
parameter B=4,
|
parameter LB=4
|
parameter LB=4
|
)(
|
)(
|
hdr_flg_in,
|
hdr_flg_in,
|
flit_in_wr,
|
flit_in_wr,
|
tail_flg_in,
|
tail_flg_in,
|
vc_num_in,
|
vc_num_in,
|
dest_e_addr_in,
|
dest_e_addr_in,
|
clk,
|
clk,
|
reset
|
reset
|
|
|
);
|
);
|
|
|
input clk, reset;
|
input clk, reset;
|
input hdr_flg_in, tail_flg_in, flit_in_wr;
|
input hdr_flg_in, tail_flg_in, flit_in_wr;
|
input [V-1 : 0] vc_num_in;
|
input [V-1 : 0] vc_num_in;
|
input [DAw-1: 0] dest_e_addr_in;
|
input [DAw-1: 0] dest_e_addr_in;
|
|
|
wire [NE-1 : 0] dest_mcast_all_endp [V-1 : 0];
|
wire [NE-1 : 0] dest_mcast_all_endp [V-1 : 0];
|
wire [31 : 0] pck_size_counter [V-1: 0];
|
wire [31 : 0] pck_size_counter [V-1: 0];
|
reg [31 : 0] pck_size_counter_next [V-1: 0];
|
reg [31 : 0] pck_size_counter_next [V-1: 0];
|
wire [DAw-1 : 0] dest_e_addr [V-1:0];
|
wire [DAw-1 : 0] dest_e_addr [V-1:0];
|
wire [V-1 : 0] vc_hdr_wr_en;
|
wire [V-1 : 0] vc_hdr_wr_en;
|
wire [V-1 : 0] onehot;
|
wire [V-1 : 0] onehot;
|
|
|
localparam MIN_B = (B<LB)? B : LB;
|
localparam MIN_B = (B<LB)? B : LB;
|
|
|
|
|
|
|
|
|
|
|
|
|
genvar i;
|
genvar i;
|
generate
|
generate
|
for (i=0;i<V;i=i+1) begin
|
for (i=0;i<V;i=i+1) begin
|
|
|
always @(*) begin
|
always @(*) begin
|
pck_size_counter_next [i] = pck_size_counter [i];
|
pck_size_counter_next [i] = pck_size_counter [i];
|
if (vc_num_in == i)begin
|
if (vc_num_in == i)begin
|
if(flit_in_wr) begin
|
if(flit_in_wr) begin
|
if(hdr_flg_in) pck_size_counter_next[i]= 1;
|
if(hdr_flg_in) pck_size_counter_next[i]= 1;
|
else pck_size_counter_next[i]=pck_size_counter[i]+1;
|
else pck_size_counter_next[i]=pck_size_counter[i]+1;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
|
|
pronoc_register #(.W(32)) reg1(
|
pronoc_register #(.W(32)) reg1(
|
.in (pck_size_counter_next[i]),
|
.in (pck_size_counter_next[i]),
|
.reset (reset ),
|
.reset (reset ),
|
.clk (clk ),
|
.clk (clk ),
|
.out (pck_size_counter[i] ));
|
.out (pck_size_counter[i] ));
|
|
|
always @(posedge clk) begin
|
always @(posedge clk) begin
|
if (vc_num_in == i)begin
|
if (vc_num_in == i)begin
|
if(flit_in_wr & tail_flg_in) begin
|
if(flit_in_wr & tail_flg_in) begin
|
if( pck_size_counter_next[i] < MIN_PCK_SIZE) begin
|
if( pck_size_counter_next[i] < MIN_PCK_SIZE) begin
|
$display ( "%t\t ERROR: A packet is injected to the router with packet size (%d flits) that is smaller than MIN_PCK_SIZE (%d flits) parameter %m",$time,pck_size_counter_next[i],MIN_PCK_SIZE);
|
$display ( "%t\t ERROR: A packet is injected to the router with packet size (%d flits) that is smaller than MIN_PCK_SIZE (%d flits) parameter %m",$time,pck_size_counter_next[i],MIN_PCK_SIZE);
|
$finish;
|
$finish;
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
if(CAST_TYPE!="UNICAST") begin
|
if(CAST_TYPE!="UNICAST") begin
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
//Check that the size of multicast/broadcast packets <= buffer size
|
//Check that the size of multicast/broadcast packets <= buffer size
|
assign vc_hdr_wr_en [i] = flit_in_wr & hdr_flg_in & (vc_num_in == i);
|
assign vc_hdr_wr_en [i] = flit_in_wr & hdr_flg_in & (vc_num_in == i);
|
pronoc_register_ld_en #(.W(DAw)) reg2(
|
pronoc_register_ld_en #(.W(DAw)) reg2(
|
.in (dest_e_addr_in),
|
.in (dest_e_addr_in),
|
.reset (reset ),
|
.reset (reset ),
|
.clk (clk ),
|
.clk (clk ),
|
.ld (vc_hdr_wr_en [i] ),
|
.ld (vc_hdr_wr_en [i] ),
|
.out (dest_e_addr[i])
|
.out (dest_e_addr[i])
|
);
|
);
|
|
|
|
|
mcast_dest_list_decode decode (
|
mcast_dest_list_decode #(
|
|
.NOC_ID(NOC_ID)
|
|
) decode (
|
.dest_e_addr(dest_e_addr[i]),
|
.dest_e_addr(dest_e_addr[i]),
|
.dest_o(dest_mcast_all_endp[i]),
|
.dest_o(dest_mcast_all_endp[i]),
|
.row_has_any_dest(),
|
.row_has_any_dest(),
|
.is_unicast()
|
.is_unicast()
|
);
|
);
|
|
|
is_onehot0 #(
|
is_onehot0 #(
|
.IN_WIDTH(NE)
|
.IN_WIDTH(NE)
|
)
|
)
|
one_h
|
one_h
|
(
|
(
|
.in(dest_mcast_all_endp[i]),
|
.in(dest_mcast_all_endp[i]),
|
.result(onehot[i])
|
.result(onehot[i])
|
|
|
);
|
);
|
|
|
|
|
|
|
|
|
always @(posedge clk) begin
|
always @(posedge clk) begin
|
if (vc_num_in == i)begin
|
if (vc_num_in == i)begin
|
if(flit_in_wr & ~onehot[i])begin
|
if(flit_in_wr & ~onehot[i])begin
|
if(pck_size_counter_next[i]>MIN_B) begin
|
if(pck_size_counter_next[i]>MIN_B) begin
|
$display ( "%t\t ERROR: A multicast packet is injected to the router with packet size (%d flits) that is larger than the minimum router buffer size (%d flits) parameter %m",$time,pck_size_counter_next[i],MIN_B);
|
$display ( "%t\t ERROR: A multicast packet is injected to the router with packet size (%d flits) that is larger than the minimum router buffer size (%d flits) parameter %m",$time,pck_size_counter_next[i],MIN_B);
|
$finish;
|
$finish;
|
end// size
|
end// size
|
end//flit_wr
|
end//flit_wr
|
end//vc_num
|
end//vc_num
|
end//always
|
end//always
|
|
|
end//multicast
|
end//multicast
|
|
|
|
|
|
|
|
|
end //for
|
end //for
|
endgenerate
|
endgenerate
|
|
|
|
|
|
|
endmodule
|
endmodule
|
|
|
|
|