mirror of
https://github.com/aolofsson/oh.git
synced 2025-01-17 20:02:53 +08:00
cedb494636
- Should really be parameter, for now it's 0x808
5655 lines
212 KiB
Verilog
5655 lines
212 KiB
Verilog
`define CFG_FAKECLK 1 /*stupid verilator doesn't get clock gating*/
|
|
`define CFG_MDW 32 /*Width of mesh network*/
|
|
`define CFG_DW 32 /*Width of datapath*/
|
|
`define CFG_AW 32 /*Width of address space*/
|
|
`define CFG_LW 8 /*Link port width*/
|
|
`define CFG_NW 13 /*Number of bytes in the transmission*/
|
|
|
|
|
|
module e16_arbiter_priority(/*AUTOARG*/
|
|
// Outputs
|
|
grant, arb_wait,
|
|
// Inputs
|
|
clk, clk_en, reset, hold, request
|
|
);
|
|
|
|
parameter ARW=99;
|
|
|
|
input clk;
|
|
input clk_en;
|
|
input reset;
|
|
|
|
input hold;
|
|
input [ARW-1:0] request;
|
|
|
|
output [ARW-1:0] grant;
|
|
output [ARW-1:0] arb_wait;
|
|
|
|
|
|
//wires
|
|
wire [ARW-1:0] grant_mask;
|
|
wire [ARW-1:0] request_mask;
|
|
|
|
//regs
|
|
reg [ARW-1:0] grant_hold;
|
|
|
|
//hold circuit
|
|
always @ (posedge clk or posedge reset)
|
|
if(reset)
|
|
grant_hold[ARW-1:0] <= {(ARW){1'b0}};
|
|
else if(clk_en)
|
|
grant_hold[ARW-1:0] <= grant[ARW-1:0] & {(ARW){hold}};
|
|
|
|
//request blocking based on held previous requests
|
|
genvar i;
|
|
generate
|
|
for(i=0;i<ARW-1;i=i+1) begin : gen_block
|
|
assign request_mask[i]=request[i] & ~(|grant_hold[ARW-1:i+1]);
|
|
end
|
|
assign request_mask[ARW-1]=request[ARW-1];//awlays on, loses on priority
|
|
endgenerate
|
|
|
|
genvar j;
|
|
assign grant_mask[0] = 1'b0;
|
|
generate for (j=ARW-1; j>=1; j=j-1) begin : gen_arbiter
|
|
assign grant_mask[j] = |request_mask[j-1:0];
|
|
end
|
|
endgenerate
|
|
|
|
//grant circuit
|
|
assign grant[ARW-1:0] = request_mask[ARW-1:0] & ~grant_mask[ARW-1:0];
|
|
|
|
//wait circuit
|
|
assign arb_wait[ARW-1:0] = request[ARW-1:0] & ({(ARW){hold}} | ~grant[ARW-1:0]);
|
|
|
|
|
|
//makes sure we hold request one cycle after wait is gone!!!
|
|
// synthesis translate_off
|
|
always @*
|
|
if((|(grant_hold[ARW-1:0] & ~request[ARW-1:0])) & ~reset & $time> 0)
|
|
begin
|
|
$display("ERROR>>Request not held steady in cell %m at time %0d", $time);
|
|
end
|
|
// synthesis translate_on
|
|
|
|
endmodule // arbiter_priority
|
|
|
|
|
|
|
|
module e16_arbiter_roundrobin(/*AUTOARG*/
|
|
// Outputs
|
|
grants,
|
|
// Inputs
|
|
clk, clk_en, reset, en_rotate, requests
|
|
);
|
|
|
|
/************************************************************/
|
|
/*PARAMETERS */
|
|
/************************************************************/
|
|
parameter ARW = 5;
|
|
|
|
|
|
/************************************************************/
|
|
/*BASIC INTERFACE */
|
|
/****I*******************************************************/
|
|
input clk;
|
|
input clk_en; //2nd level manual clock gater
|
|
input reset;
|
|
|
|
/************************************************************/
|
|
/*ARBITRATION INTERFACE */
|
|
/****I*******************************************************/
|
|
input en_rotate;//enable mask rotation, makes arbiter more flexible
|
|
//in mesh there should be a way to control freq of rotation
|
|
|
|
input [ARW-1:0] requests;
|
|
output [ARW-1:0] grants;
|
|
|
|
//loop variable
|
|
integer m;
|
|
|
|
//Masks
|
|
reg [ARW-1:0] request_mask; //rotating mask
|
|
|
|
|
|
//Wires
|
|
reg [2*ARW-1:0] grants_rotate_buffer;
|
|
reg [ARW-1:0] grants; //output grants
|
|
wire [ARW-1:0] shifted_requests[ARW-1:0];
|
|
wire [ARW-1:0] shifted_grants[ARW-1:0];
|
|
wire [2*ARW-1:0] requests_rotate_buffer;
|
|
|
|
/********************************************************************/
|
|
/*Rotating Mask Pointer On Every Clock Cycle */
|
|
/********************************************************************/
|
|
//request vector[7:0]-->regular
|
|
//hold vector[7:0] -->sets the priority to the request when it wins
|
|
// there can be multiple bits set
|
|
// the only one active is the one where the
|
|
// mask is currently located.
|
|
// en_rotate=~(hold_vec[7:0] & requeste_mask[7:0])
|
|
|
|
//every request should also be able to send a "start/stop" signal
|
|
//instead of having an en_rotate signal, we have
|
|
//if then en-rotate signal is low
|
|
|
|
always @ ( posedge clk or posedge reset)
|
|
if(reset)
|
|
request_mask[ARW-1:0] <= {{(ARW-1){1'b0}},1'b1};
|
|
else if(clk_en)
|
|
if(en_rotate)
|
|
request_mask[ARW-1:0] <= {request_mask[ARW-2:0],request_mask[ARW-1]};
|
|
|
|
/********************************************************************/
|
|
/*Creating Shifted Request Vectors */
|
|
/********************************************************************/
|
|
assign requests_rotate_buffer[2*ARW-1:0]={requests[ARW-1:0],requests[ARW-1:0]};
|
|
|
|
genvar i;
|
|
generate
|
|
for (i=0;i<ARW;i=i+1) begin: gen_requests
|
|
assign shifted_requests[i]=requests_rotate_buffer[ARW-1+i:i];
|
|
end
|
|
endgenerate
|
|
|
|
/********************************************************************/
|
|
/*Priority Encoders For Each Vector */
|
|
/********************************************************************/
|
|
//Priority Encoders For Each Vector
|
|
genvar k;
|
|
generate
|
|
for (k=0;k<ARW;k=k+1) begin: gen_arbiter
|
|
e16_arbiter_priority #(.ARW(ARW)) simple_arbiter(
|
|
.clk (clk),
|
|
.clk_en (clk_en),
|
|
.reset (reset),
|
|
.hold (1'b0),
|
|
.request (shifted_requests[k]),
|
|
.arb_wait (),
|
|
.grant (shifted_grants[k])
|
|
);
|
|
end
|
|
endgenerate
|
|
|
|
/********************************************************************/
|
|
/*One Hot Mux */
|
|
/********************************************************************/
|
|
//Note that grants have to be rotate back to their right positiona again.
|
|
always @*
|
|
begin
|
|
grants[ARW-1:0] = {(ARW){1'b0}};
|
|
for(m=0;m<ARW;m=m+1)
|
|
begin
|
|
grants_rotate_buffer[2*ARW-1:0]={shifted_grants[m],shifted_grants[m]};
|
|
grants[ARW-1:0] =grants[ARW-1:0] |
|
|
({(ARW){request_mask[m]}} &
|
|
grants_rotate_buffer[2*ARW-1-m-:ARW]
|
|
);
|
|
end
|
|
end
|
|
|
|
/********************************************************************/
|
|
/*Checkers */
|
|
/********************************************************************/
|
|
/*
|
|
|
|
// synthesis translate_off
|
|
always @*
|
|
begin
|
|
if((|(grants[ARW-1:0]&~requests[ARW-1:0])) & $time>0)
|
|
$display("ERROR>>Grant granted with out request in cell %m at time %0d",$time);
|
|
if((~(|grants[ARW-1:0]) & (|requests[ARW-1:0])) & $time>0)
|
|
$display("ERROR>>Zero granted when there was a request in cell %m at time %0d",$time);
|
|
end
|
|
// synthesis translate_on
|
|
*/
|
|
|
|
endmodule // arbiter_roundrobin
|
|
// ###############################################################
|
|
// # FUNCTION: Synchronous clock divider that divides by integer
|
|
// # NOTE: Combinatorial output becomes new clock
|
|
// ###############################################################
|
|
|
|
module e16_clock_divider(/*AUTOARG*/
|
|
// Outputs
|
|
clk_out, clk_out90,
|
|
// Inputs
|
|
clk_in, reset, div_cfg
|
|
);
|
|
|
|
|
|
input clk_in; // Input clock
|
|
input reset;
|
|
input [3:0] div_cfg; // Divide factor
|
|
|
|
output clk_out; // Divided clock phase aligned with clk_in
|
|
output clk_out90; // Divided clock with 90deg phase shift with clk_out
|
|
|
|
|
|
reg clk_out_reg;
|
|
//reg clk_out90_reg;
|
|
//reg clk90_div2_reg;
|
|
reg [5:0] counter;
|
|
reg [5:0] div_cfg_dec;
|
|
|
|
wire div2_sel;
|
|
wire posedge_match;
|
|
wire negedge_match;
|
|
wire posedge90_match;
|
|
wire negedge90_match;
|
|
|
|
wire clk_out90_div2;
|
|
wire clk_out90_div4;
|
|
wire clk_out90_div2_in;
|
|
wire clk_out90_div4_in;
|
|
// ###################
|
|
// # Decode div_cfg
|
|
// ###################
|
|
|
|
always @ (div_cfg[3:0])
|
|
begin
|
|
casez (div_cfg[3:0])
|
|
4'b0000 : div_cfg_dec[5:0] = 6'b000010; // Divide by 2
|
|
4'b0001 : div_cfg_dec[5:0] = 6'b000100; // Divide by 4
|
|
4'b0010 : div_cfg_dec[5:0] = 6'b001000; // Divide by 8
|
|
4'b0011 : div_cfg_dec[5:0] = 6'b010000; // Divide by 16
|
|
4'b01?? : div_cfg_dec[5:0] = 6'b100000; // A lof of different ratios
|
|
4'b1??? : div_cfg_dec[5:0] = 6'b100000; // Divide by 32
|
|
default : div_cfg_dec[5:0] = 6'b000000;
|
|
endcase // casez (div_cfg[3:0])
|
|
end // always @ (div_cfg[3:0])
|
|
|
|
assign div2_sel = div_cfg[3:0]==4'b0;
|
|
|
|
|
|
//Counter For Generating Toggling Edges
|
|
//always @ (posedge clk_in or posedge reset)
|
|
//if(reset)
|
|
//counter[5:0] <= 6'b000001;// Reset value
|
|
|
|
always @ (posedge clk_in or posedge reset)
|
|
if (reset)
|
|
counter[5:0] <= 6'b000001;
|
|
else if(posedge_match)
|
|
counter[5:0] <= 6'b000001;// Self resetting
|
|
else
|
|
counter[5:0] <= (counter[5:0]+6'b000001);
|
|
|
|
assign posedge_match = (counter[5:0]==div_cfg_dec[5:0]);
|
|
assign negedge_match = (counter[5:0]=={1'b0,div_cfg_dec[5:1]});
|
|
assign posedge90_match = (counter[5:0]==({2'b00,div_cfg_dec[5:2]}));
|
|
assign negedge90_match = (counter[5:0]==({2'b00,div_cfg_dec[5:2]}+{1'b0,div_cfg_dec[5:1]}));
|
|
|
|
//Divided clock
|
|
//always @ (posedge clk_in or posedge reset)
|
|
//if(reset)
|
|
//clk_out_reg <= 1'b0;
|
|
always @ (posedge clk_in)
|
|
if(posedge_match)
|
|
clk_out_reg <= 1'b1;
|
|
else if(negedge_match)
|
|
clk_out_reg <= 1'b0;
|
|
|
|
assign clk_out = clk_out_reg;
|
|
|
|
/**********************************************************************/
|
|
/*Divide by 2 Clock
|
|
/**********************************************************************/
|
|
//always @ (posedge clk_in or posedge reset)
|
|
//if(reset)
|
|
//clk_out90_reg <= 1'b0;
|
|
//always @ (posedge clk_in)
|
|
// if(posedge90_match)
|
|
// clk_out90_reg <= 1'b1;
|
|
// else if(negedge90_match)
|
|
// clk_out90_reg <= 1'b0;
|
|
|
|
assign clk_out90_div4_in = posedge90_match ? 1'b1 :
|
|
negedge90_match ? 1'b0 :
|
|
clk_out90_div4;
|
|
|
|
DFFQX4A12TR clk90_flop (.CK(clk_in),
|
|
.D(clk_out90_div4_in),
|
|
.Q(clk_out90_div4)
|
|
);
|
|
|
|
//always @ (negedge clk_in)
|
|
// if(negedge_match)
|
|
// clk90_div2_reg <= 1'b1;
|
|
// else if(posedge_match)
|
|
// clk90_div2_reg <= 1'b0;
|
|
|
|
assign clk_out90_div2_in = negedge_match ? 1'b1 :
|
|
posedge_match ? 1'b0 :
|
|
clk_out90_div2;
|
|
|
|
|
|
|
|
DFFNQX3A12TR clk90_div2_flop (.CKN(clk_in),
|
|
.D(clk_out90_div2_in),
|
|
.Q(clk_out90_div2)
|
|
);
|
|
|
|
|
|
//assign clk_out90 = div2_sel ? clk90_div2_reg : clk_out90_reg;
|
|
MX2X4A12TR clk90_mux2 (.A(clk_out90_div4),
|
|
.B(clk_out90_div2),
|
|
.S0(div2_sel),
|
|
.Y(clk_out90)
|
|
);
|
|
|
|
|
|
|
|
|
|
endmodule // clock_divider
|
|
|
|
|
|
|
|
|
|
module e16_mesh_interface(/*AUTOARG*/
|
|
// Outputs
|
|
wait_out, access_out, write_out, datamode_out, ctrlmode_out,
|
|
data_out, dstaddr_out, srcaddr_out, access_reg, write_reg,
|
|
datamode_reg, ctrlmode_reg, data_reg, dstaddr_reg, srcaddr_reg,
|
|
// Inputs
|
|
clk, clk_en, reset, wait_in, access_in, write_in, datamode_in,
|
|
ctrlmode_in, data_in, dstaddr_in, srcaddr_in, wait_int, access,
|
|
write, datamode, ctrlmode, data, dstaddr, srcaddr
|
|
);
|
|
|
|
parameter DW = `CFG_DW;
|
|
parameter AW = `CFG_AW;
|
|
|
|
//###########
|
|
//# INPUTS
|
|
//###########
|
|
input clk;
|
|
input clk_en; //2nd level manual clock gater
|
|
input reset;
|
|
|
|
//# from the mesh
|
|
input wait_in;
|
|
input access_in;
|
|
input write_in;
|
|
input [1:0] datamode_in;
|
|
input [3:0] ctrlmode_in;
|
|
input [DW-1:0] data_in;
|
|
input [AW-1:0] dstaddr_in;
|
|
input [AW-1:0] srcaddr_in;
|
|
|
|
//# from the internal control
|
|
input wait_int;
|
|
input access;
|
|
input write;
|
|
input [1:0] datamode;
|
|
input [3:0] ctrlmode;
|
|
input [DW-1:0] data;
|
|
input [AW-1:0] dstaddr;
|
|
input [AW-1:0] srcaddr;
|
|
|
|
//###########
|
|
//# OUTPUTS
|
|
//###########
|
|
|
|
//# to the mesh
|
|
output wait_out;
|
|
output access_out;
|
|
output write_out;
|
|
output [1:0] datamode_out;
|
|
output [3:0] ctrlmode_out;
|
|
output [DW-1:0] data_out;
|
|
output [AW-1:0] dstaddr_out;
|
|
output [AW-1:0] srcaddr_out;
|
|
|
|
//# to the internal control
|
|
output access_reg;
|
|
output write_reg;
|
|
output [1:0] datamode_reg;
|
|
output [3:0] ctrlmode_reg;
|
|
output [DW-1:0] data_reg;
|
|
output [AW-1:0] dstaddr_reg;
|
|
output [AW-1:0] srcaddr_reg;
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
//#########
|
|
//# REGS
|
|
//#########
|
|
reg wait_out;
|
|
reg access_out;
|
|
reg write_out;
|
|
reg [1:0] datamode_out;
|
|
reg [3:0] ctrlmode_out;
|
|
reg [DW-1:0] data_out;
|
|
reg [AW-1:0] dstaddr_out;
|
|
reg [AW-1:0] srcaddr_out;
|
|
|
|
reg access_reg;
|
|
reg write_reg;
|
|
reg [1:0] datamode_reg;
|
|
reg [3:0] ctrlmode_reg;
|
|
reg [DW-1:0] data_reg;
|
|
reg [AW-1:0] dstaddr_reg;
|
|
reg [AW-1:0] srcaddr_reg;
|
|
|
|
//#########
|
|
//# WIRES
|
|
//#########
|
|
|
|
//##########################
|
|
//# mesh input busses
|
|
//##########################
|
|
|
|
always @ (posedge clk or posedge reset)
|
|
if(reset)
|
|
access_reg <= 1'b0;
|
|
else if(clk_en)
|
|
if(~wait_int)
|
|
access_reg <= access_in;
|
|
|
|
always @ (posedge clk)
|
|
if(clk_en)
|
|
if(~wait_int & access_in)
|
|
begin
|
|
write_reg <= write_in;
|
|
datamode_reg[1:0] <= datamode_in[1:0];
|
|
ctrlmode_reg[3:0] <= ctrlmode_in[3:0];
|
|
data_reg[DW-1:0] <= data_in[DW-1:0];
|
|
dstaddr_reg[AW-1:0] <= dstaddr_in[AW-1:0];
|
|
srcaddr_reg[AW-1:0] <= srcaddr_in[AW-1:0];
|
|
end
|
|
|
|
//##########################
|
|
//# mesh output busses
|
|
//##########################
|
|
|
|
always @ (posedge clk or posedge reset)
|
|
if(reset)
|
|
access_out <= 1'b0;
|
|
else if(clk_en)
|
|
if(!wait_in)
|
|
access_out <= access;
|
|
|
|
always @ (posedge clk)
|
|
if (clk_en)
|
|
if(!wait_in & access)
|
|
begin
|
|
srcaddr_out[AW-1:0] <= srcaddr[AW-1:0];
|
|
data_out[DW-1:0] <= data[DW-1:0];
|
|
write_out <= write;
|
|
datamode_out[1:0] <= datamode[1:0];
|
|
dstaddr_out[AW-1:0] <= dstaddr[AW-1:0];
|
|
ctrlmode_out[3:0] <= ctrlmode[3:0];
|
|
end
|
|
|
|
//#####################
|
|
//# Wait out control
|
|
//#####################
|
|
always @ (posedge clk or posedge reset)
|
|
if(reset)
|
|
wait_out <= 1'b0;
|
|
else if(clk_en)
|
|
wait_out <= wait_int;
|
|
|
|
endmodule // mesh_interface
|
|
|
|
|
|
|
|
module e16_mux7(/*AUTOARG*/
|
|
// Outputs
|
|
out,
|
|
// Inputs
|
|
in0, in1, in2, in3, in4, in5, in6, sel0, sel1, sel2, sel3, sel4,
|
|
sel5, sel6
|
|
);
|
|
|
|
parameter DW=99;
|
|
|
|
|
|
//data inputs
|
|
input [DW-1:0] in0;
|
|
input [DW-1:0] in1;
|
|
input [DW-1:0] in2;
|
|
input [DW-1:0] in3;
|
|
input [DW-1:0] in4;
|
|
input [DW-1:0] in5;
|
|
input [DW-1:0] in6;
|
|
|
|
//select inputs
|
|
input sel0;
|
|
input sel1;
|
|
input sel2;
|
|
input sel3;
|
|
input sel4;
|
|
input sel5;
|
|
input sel6;
|
|
|
|
|
|
output [DW-1:0] out;
|
|
|
|
|
|
assign out[DW-1:0] = ({(DW){sel0}} & in0[DW-1:0] |
|
|
{(DW){sel1}} & in1[DW-1:0] |
|
|
{(DW){sel2}} & in2[DW-1:0] |
|
|
{(DW){sel3}} & in3[DW-1:0] |
|
|
{(DW){sel4}} & in4[DW-1:0] |
|
|
{(DW){sel5}} & in5[DW-1:0] |
|
|
{(DW){sel6}} & in6[DW-1:0]);
|
|
|
|
|
|
// synthesis translate_off
|
|
always @*
|
|
if((sel0+sel1+sel2+sel3+sel4+sel5+sel6>1) & $time>0)
|
|
$display("ERROR>>Arbitration failure in cell %m");
|
|
// synthesis translate_on
|
|
|
|
|
|
endmodule // mux7
|
|
|
|
module e16_pulse2pulse(/*AUTOARG*/
|
|
// Outputs
|
|
out,
|
|
// Inputs
|
|
inclk, outclk, in, reset
|
|
);
|
|
|
|
|
|
//clocks
|
|
input inclk;
|
|
input outclk;
|
|
|
|
|
|
input in;
|
|
output out;
|
|
|
|
//reset
|
|
input reset; //do we need this???
|
|
|
|
|
|
|
|
wire intoggle;
|
|
wire insync;
|
|
|
|
|
|
//pulse to toggle
|
|
pulse2toggle pulse2toggle(
|
|
// Outputs
|
|
.out (intoggle),
|
|
// Inputs
|
|
.clk (inclk),
|
|
.in (in),
|
|
.reset (reset));
|
|
|
|
//metastability synchronizer
|
|
synchronizer #(1) synchronizer(
|
|
// Outputs
|
|
.out (insync),
|
|
// Inputs
|
|
.in (intoggle),
|
|
.clk (outclk),
|
|
.reset (reset));
|
|
|
|
|
|
//toogle to pulse
|
|
toggle2pulse toggle2pulse(
|
|
// Outputs
|
|
.out (out),
|
|
// Inputs
|
|
.clk (outclk),
|
|
.in (insync),
|
|
.reset (reset));
|
|
|
|
|
|
|
|
endmodule // pulse2pulse
|
|
|
|
|
|
|
|
module e16_pulse2toggle(/*AUTOARG*/
|
|
// Outputs
|
|
out,
|
|
// Inputs
|
|
clk, in, reset
|
|
);
|
|
|
|
|
|
//clocks
|
|
input clk;
|
|
|
|
input in;
|
|
output out;
|
|
|
|
//reset
|
|
input reset; //do we need this???
|
|
|
|
|
|
reg out;
|
|
wire toggle;
|
|
|
|
//if input goes high, toggle output
|
|
//note1: input can only be high for one clock cycle
|
|
//note2: be careful with clock gating
|
|
|
|
assign toggle = in ? ~out :
|
|
out;
|
|
|
|
|
|
always @ (posedge clk or posedge reset)
|
|
if(reset)
|
|
out <= 1'b0;
|
|
else
|
|
out <= toggle;
|
|
|
|
endmodule // pulse2toggle
|
|
|
|
|
|
|
|
|
|
module e16_synchronizer #(parameter DW=32) (/*AUTOARG*/
|
|
// Outputs
|
|
out,
|
|
// Inputs
|
|
in, clk, reset
|
|
);
|
|
|
|
|
|
//Input Side
|
|
input [DW-1:0] in;
|
|
input clk;
|
|
input reset;//asynchronous signal
|
|
|
|
|
|
//Output Side
|
|
output [DW-1:0] out;
|
|
|
|
reg [DW-1:0] sync_reg0;
|
|
reg [DW-1:0] sync_reg1;
|
|
reg [DW-1:0] out;
|
|
|
|
//Synchronization between clock domain
|
|
//We use two flip-flops for metastability improvement
|
|
always @ (posedge clk or posedge reset)
|
|
if(reset)
|
|
begin
|
|
sync_reg0[DW-1:0] <= {(DW){1'b0}};
|
|
sync_reg1[DW-1:0] <= {(DW){1'b0}};
|
|
out[DW-1:0] <= {(DW){1'b0}};
|
|
end
|
|
else
|
|
begin
|
|
sync_reg0[DW-1:0] <= in[DW-1:0];
|
|
sync_reg1[DW-1:0] <= sync_reg0[DW-1:0];
|
|
out[DW-1:0] <= sync_reg1[DW-1:0];
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endmodule // clock_synchronizer
|
|
|
|
//goes high for one clock cycle on every input transition
|
|
module e16_toggle2pulse(/*AUTOARG*/
|
|
// Outputs
|
|
out,
|
|
// Inputs
|
|
clk, in, reset
|
|
);
|
|
|
|
|
|
//clocks
|
|
input clk;
|
|
|
|
input in;
|
|
output out;
|
|
|
|
//reset
|
|
input reset;
|
|
reg out_reg;
|
|
|
|
always @ (posedge clk or posedge reset)
|
|
if(reset)
|
|
out_reg <= 1'b0;
|
|
else
|
|
out_reg <= in;
|
|
|
|
assign out = in ^ out_reg;
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
|
|
|
|
module elink_e16 (/*AUTOARG*/
|
|
// Outputs
|
|
rxi_rd_wait, rxi_wr_wait, txo_data, txo_lclk, txo_frame,
|
|
c0_mesh_access_out, c0_mesh_write_out, c0_mesh_dstaddr_out,
|
|
c0_mesh_srcaddr_out, c0_mesh_data_out, c0_mesh_datamode_out,
|
|
c0_mesh_ctrlmode_out, c0_emesh_wait_out, c0_mesh_wait_out,
|
|
// Inputs
|
|
reset, c0_clk_in, c1_clk_in, c2_clk_in, c3_clk_in, rxi_data,
|
|
rxi_lclk, rxi_frame, txo_rd_wait, txo_wr_wait, c0_mesh_access_in,
|
|
c0_mesh_write_in, c0_mesh_dstaddr_in, c0_mesh_srcaddr_in,
|
|
c0_mesh_data_in, c0_mesh_datamode_in, c0_mesh_ctrlmode_in,
|
|
c0_mesh_wait_in
|
|
);
|
|
|
|
parameter DW = `CFG_DW ;//data width
|
|
parameter AW = `CFG_AW ;//address width
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
|
|
|
|
|
|
//Reset/core clock
|
|
input reset;
|
|
input c0_clk_in;
|
|
input c1_clk_in;
|
|
input c2_clk_in;
|
|
input c3_clk_in;
|
|
|
|
|
|
// # IO Signals
|
|
input [LW-1:0] rxi_data; // Byte word
|
|
input rxi_lclk; // receive clock (adjusted)
|
|
input rxi_frame; // indicates new transmission
|
|
input txo_rd_wait; // wait indicator on read transactions
|
|
input txo_wr_wait; // wait indicator on write transactions
|
|
output rxi_rd_wait; // wait indicator on read transaction
|
|
output rxi_wr_wait; // wait indicator on write transaction
|
|
output [LW-1:0] txo_data; // Byte word
|
|
output txo_lclk; // transmit clock
|
|
output txo_frame; // indicates new transmission
|
|
|
|
|
|
|
|
// # MESH
|
|
// # core0 (external corners and multicast)
|
|
input c0_mesh_access_in; // access control from the mesh
|
|
input c0_mesh_write_in; // write control from the mesh
|
|
input [AW-1:0] c0_mesh_dstaddr_in; // destination address from the mesh
|
|
input [AW-1:0] c0_mesh_srcaddr_in; // source address from the mesh
|
|
input [DW-1:0] c0_mesh_data_in; // data from the mesh
|
|
input [1:0] c0_mesh_datamode_in;// data mode from the mesh
|
|
input [3:0] c0_mesh_ctrlmode_in;// ctrl mode from the mesh
|
|
input c0_mesh_wait_in; // wait
|
|
|
|
|
|
|
|
// ##############
|
|
// # Outputs
|
|
// ##############
|
|
|
|
|
|
// # MESH (write transactions internal and external corners)
|
|
// # core0
|
|
output c0_mesh_access_out; // access control to the mesh
|
|
output c0_mesh_write_out; // write control to the mesh
|
|
output [AW-1:0] c0_mesh_dstaddr_out; // destination address to the mesh
|
|
output [AW-1:0] c0_mesh_srcaddr_out; // source address to the mesh
|
|
output [DW-1:0] c0_mesh_data_out; // data to the mesh
|
|
output [1:0] c0_mesh_datamode_out;// data mode to the mesh
|
|
output [3:0] c0_mesh_ctrlmode_out;// ctrl mode to the mesh
|
|
|
|
|
|
// # Waits
|
|
output c0_emesh_wait_out; // wait to the emesh
|
|
output c0_mesh_wait_out; // wait to the mesh
|
|
|
|
|
|
//TODO: NOTRE FIXED COORDINATE
|
|
wire [3:0] ext_yid_k=4'h8;
|
|
wire [3:0] ext_xid_k=4'h2;
|
|
wire vertical_k=1'b1; // specifies if block is vertical or horizontal
|
|
wire [3:0] who_am_i=4'b0100; // (north,east,south,west)
|
|
wire cfg_extcomp_dis=1'b0;// Disable external coordinates comparison
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
|
wire c0_emesh_frame_out; // From link_port of link_port.v
|
|
wire [2*LW-1:0] c0_emesh_tran_out; // From link_port of link_port.v
|
|
wire c0_rdmesh_frame_out; // From link_port of link_port.v
|
|
wire [2*LW-1:0] c0_rdmesh_tran_out; // From link_port of link_port.v
|
|
wire c0_rdmesh_wait_out; // From link_port of link_port.v
|
|
wire c1_emesh_wait_out; // From link_port of link_port.v
|
|
wire c1_rdmesh_frame_out; // From link_port of link_port.v
|
|
wire [2*LW-1:0] c1_rdmesh_tran_out; // From link_port of link_port.v
|
|
wire c1_rdmesh_wait_out; // From link_port of link_port.v
|
|
wire c2_emesh_wait_out; // From link_port of link_port.v
|
|
wire c2_rdmesh_frame_out; // From link_port of link_port.v
|
|
wire [2*LW-1:0] c2_rdmesh_tran_out; // From link_port of link_port.v
|
|
wire c2_rdmesh_wait_out; // From link_port of link_port.v
|
|
wire c3_emesh_frame_out; // From link_port of link_port.v
|
|
wire [2*LW-1:0] c3_emesh_tran_out; // From link_port of link_port.v
|
|
wire c3_emesh_wait_out; // From link_port of link_port.v
|
|
wire c3_mesh_access_out; // From link_port of link_port.v
|
|
wire [3:0] c3_mesh_ctrlmode_out; // From link_port of link_port.v
|
|
wire [DW-1:0] c3_mesh_data_out; // From link_port of link_port.v
|
|
wire [1:0] c3_mesh_datamode_out; // From link_port of link_port.v
|
|
wire [AW-1:0] c3_mesh_dstaddr_out; // From link_port of link_port.v
|
|
wire [AW-1:0] c3_mesh_srcaddr_out; // From link_port of link_port.v
|
|
wire c3_mesh_wait_out; // From link_port of link_port.v
|
|
wire c3_mesh_write_out; // From link_port of link_port.v
|
|
wire c3_rdmesh_frame_out; // From link_port of link_port.v
|
|
wire [2*LW-1:0] c3_rdmesh_tran_out; // From link_port of link_port.v
|
|
wire c3_rdmesh_wait_out; // From link_port of link_port.v
|
|
// End of automatics
|
|
|
|
/* link_port AUTO_TEMPLATE (.\(.*\)_rdmesh_tran_in (16'b0),
|
|
.\(.*\)_rdmesh_frame_in (1'b0),
|
|
.\(.*\)_emesh_tran_in (16'b0),
|
|
.\(.*\)_emesh_frame_in (1'b0),
|
|
);
|
|
*/
|
|
|
|
|
|
wire c0_emesh_wait_in=1'b0;
|
|
wire c0_rdmesh_wait_in=1'b0;
|
|
wire c1_rdmesh_wait_in=1'b0;
|
|
wire c2_rdmesh_wait_in=1'b0;
|
|
wire c3_emesh_wait_in=1'b0;
|
|
wire c3_mesh_wait_in=1'b0;
|
|
wire c3_rdmesh_wait_in=1'b0;
|
|
wire [5:0] txo_cfg_reg=6'b0;
|
|
|
|
|
|
link_port link_port (.c3_mesh_access_in(1'b0),
|
|
.c3_mesh_write_in(1'b0),
|
|
.c3_mesh_dstaddr_in(32'b0),
|
|
.c3_mesh_srcaddr_in(32'b0),
|
|
.c3_mesh_data_in(32'b0),
|
|
.c3_mesh_datamode_in(2'b0),
|
|
.c3_mesh_ctrlmode_in(4'b0),
|
|
/*AUTOINST*/
|
|
// Outputs
|
|
.rxi_rd_wait (rxi_rd_wait),
|
|
.rxi_wr_wait (rxi_wr_wait),
|
|
.txo_data (txo_data[LW-1:0]),
|
|
.txo_lclk (txo_lclk),
|
|
.txo_frame (txo_frame),
|
|
.c0_emesh_frame_out(c0_emesh_frame_out),
|
|
.c0_emesh_tran_out(c0_emesh_tran_out[2*LW-1:0]),
|
|
.c3_emesh_frame_out(c3_emesh_frame_out),
|
|
.c3_emesh_tran_out(c3_emesh_tran_out[2*LW-1:0]),
|
|
.c0_rdmesh_frame_out(c0_rdmesh_frame_out),
|
|
.c0_rdmesh_tran_out(c0_rdmesh_tran_out[2*LW-1:0]),
|
|
.c1_rdmesh_frame_out(c1_rdmesh_frame_out),
|
|
.c1_rdmesh_tran_out(c1_rdmesh_tran_out[2*LW-1:0]),
|
|
.c2_rdmesh_frame_out(c2_rdmesh_frame_out),
|
|
.c2_rdmesh_tran_out(c2_rdmesh_tran_out[2*LW-1:0]),
|
|
.c3_rdmesh_frame_out(c3_rdmesh_frame_out),
|
|
.c3_rdmesh_tran_out(c3_rdmesh_tran_out[2*LW-1:0]),
|
|
.c0_mesh_access_out(c0_mesh_access_out),
|
|
.c0_mesh_write_out(c0_mesh_write_out),
|
|
.c0_mesh_dstaddr_out(c0_mesh_dstaddr_out[AW-1:0]),
|
|
.c0_mesh_srcaddr_out(c0_mesh_srcaddr_out[AW-1:0]),
|
|
.c0_mesh_data_out(c0_mesh_data_out[DW-1:0]),
|
|
.c0_mesh_datamode_out(c0_mesh_datamode_out[1:0]),
|
|
.c0_mesh_ctrlmode_out(c0_mesh_ctrlmode_out[3:0]),
|
|
.c3_mesh_access_out(c3_mesh_access_out),
|
|
.c3_mesh_write_out(c3_mesh_write_out),
|
|
.c3_mesh_dstaddr_out(c3_mesh_dstaddr_out[AW-1:0]),
|
|
.c3_mesh_srcaddr_out(c3_mesh_srcaddr_out[AW-1:0]),
|
|
.c3_mesh_data_out(c3_mesh_data_out[DW-1:0]),
|
|
.c3_mesh_datamode_out(c3_mesh_datamode_out[1:0]),
|
|
.c3_mesh_ctrlmode_out(c3_mesh_ctrlmode_out[3:0]),
|
|
.c0_emesh_wait_out(c0_emesh_wait_out),
|
|
.c1_emesh_wait_out(c1_emesh_wait_out),
|
|
.c2_emesh_wait_out(c2_emesh_wait_out),
|
|
.c3_emesh_wait_out(c3_emesh_wait_out),
|
|
.c0_rdmesh_wait_out(c0_rdmesh_wait_out),
|
|
.c1_rdmesh_wait_out(c1_rdmesh_wait_out),
|
|
.c2_rdmesh_wait_out(c2_rdmesh_wait_out),
|
|
.c3_rdmesh_wait_out(c3_rdmesh_wait_out),
|
|
.c0_mesh_wait_out(c0_mesh_wait_out),
|
|
.c3_mesh_wait_out(c3_mesh_wait_out),
|
|
// Inputs
|
|
.reset (reset),
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.txo_cfg_reg (txo_cfg_reg[5:0]),
|
|
.vertical_k (vertical_k),
|
|
.who_am_i (who_am_i[3:0]),
|
|
.cfg_extcomp_dis(cfg_extcomp_dis),
|
|
.rxi_data (rxi_data[LW-1:0]),
|
|
.rxi_lclk (rxi_lclk),
|
|
.rxi_frame (rxi_frame),
|
|
.txo_rd_wait (txo_rd_wait),
|
|
.txo_wr_wait (txo_wr_wait),
|
|
.c0_clk_in (c0_clk_in),
|
|
.c1_clk_in (c1_clk_in),
|
|
.c2_clk_in (c2_clk_in),
|
|
.c3_clk_in (c3_clk_in),
|
|
.c0_emesh_tran_in(16'b0), // Templated
|
|
.c0_emesh_frame_in(1'b0), // Templated
|
|
.c1_emesh_tran_in(16'b0), // Templated
|
|
.c1_emesh_frame_in(1'b0), // Templated
|
|
.c2_emesh_tran_in(16'b0), // Templated
|
|
.c2_emesh_frame_in(1'b0), // Templated
|
|
.c3_emesh_tran_in(16'b0), // Templated
|
|
.c3_emesh_frame_in(1'b0), // Templated
|
|
.c0_rdmesh_tran_in(16'b0), // Templated
|
|
.c0_rdmesh_frame_in(1'b0), // Templated
|
|
.c1_rdmesh_tran_in(16'b0), // Templated
|
|
.c1_rdmesh_frame_in(1'b0), // Templated
|
|
.c2_rdmesh_tran_in(16'b0), // Templated
|
|
.c2_rdmesh_frame_in(1'b0), // Templated
|
|
.c3_rdmesh_tran_in(16'b0), // Templated
|
|
.c3_rdmesh_frame_in(1'b0), // Templated
|
|
.c0_mesh_access_in(c0_mesh_access_in),
|
|
.c0_mesh_write_in(c0_mesh_write_in),
|
|
.c0_mesh_dstaddr_in(c0_mesh_dstaddr_in[AW-1:0]),
|
|
.c0_mesh_srcaddr_in(c0_mesh_srcaddr_in[AW-1:0]),
|
|
.c0_mesh_data_in(c0_mesh_data_in[DW-1:0]),
|
|
.c0_mesh_datamode_in(c0_mesh_datamode_in[1:0]),
|
|
.c0_mesh_ctrlmode_in(c0_mesh_ctrlmode_in[3:0]),
|
|
.c0_emesh_wait_in(c0_emesh_wait_in),
|
|
.c3_emesh_wait_in(c3_emesh_wait_in),
|
|
.c0_mesh_wait_in(c0_mesh_wait_in),
|
|
.c3_mesh_wait_in(c3_mesh_wait_in),
|
|
.c0_rdmesh_wait_in(c0_rdmesh_wait_in),
|
|
.c1_rdmesh_wait_in(c1_rdmesh_wait_in),
|
|
.c2_rdmesh_wait_in(c2_rdmesh_wait_in),
|
|
.c3_rdmesh_wait_in(c3_rdmesh_wait_in));
|
|
|
|
endmodule // elink_e16
|
|
|
|
module link_port(/*AUTOARG*/
|
|
// Outputs
|
|
rxi_rd_wait, rxi_wr_wait, txo_data, txo_lclk, txo_frame,
|
|
c0_emesh_frame_out, c0_emesh_tran_out, c3_emesh_frame_out,
|
|
c3_emesh_tran_out, c0_rdmesh_frame_out, c0_rdmesh_tran_out,
|
|
c1_rdmesh_frame_out, c1_rdmesh_tran_out, c2_rdmesh_frame_out,
|
|
c2_rdmesh_tran_out, c3_rdmesh_frame_out, c3_rdmesh_tran_out,
|
|
c0_mesh_access_out, c0_mesh_write_out, c0_mesh_dstaddr_out,
|
|
c0_mesh_srcaddr_out, c0_mesh_data_out, c0_mesh_datamode_out,
|
|
c0_mesh_ctrlmode_out, c3_mesh_access_out, c3_mesh_write_out,
|
|
c3_mesh_dstaddr_out, c3_mesh_srcaddr_out, c3_mesh_data_out,
|
|
c3_mesh_datamode_out, c3_mesh_ctrlmode_out, c0_emesh_wait_out,
|
|
c1_emesh_wait_out, c2_emesh_wait_out, c3_emesh_wait_out,
|
|
c0_rdmesh_wait_out, c1_rdmesh_wait_out, c2_rdmesh_wait_out,
|
|
c3_rdmesh_wait_out, c0_mesh_wait_out, c3_mesh_wait_out,
|
|
// Inputs
|
|
reset, ext_yid_k, ext_xid_k, txo_cfg_reg, vertical_k, who_am_i,
|
|
cfg_extcomp_dis, rxi_data, rxi_lclk, rxi_frame, txo_rd_wait,
|
|
txo_wr_wait, c0_clk_in, c1_clk_in, c2_clk_in, c3_clk_in,
|
|
c0_emesh_tran_in, c0_emesh_frame_in, c1_emesh_tran_in,
|
|
c1_emesh_frame_in, c2_emesh_tran_in, c2_emesh_frame_in,
|
|
c3_emesh_tran_in, c3_emesh_frame_in, c0_rdmesh_tran_in,
|
|
c0_rdmesh_frame_in, c1_rdmesh_tran_in, c1_rdmesh_frame_in,
|
|
c2_rdmesh_tran_in, c2_rdmesh_frame_in, c3_rdmesh_tran_in,
|
|
c3_rdmesh_frame_in, c0_mesh_access_in, c0_mesh_write_in,
|
|
c0_mesh_dstaddr_in, c0_mesh_srcaddr_in, c0_mesh_data_in,
|
|
c0_mesh_datamode_in, c0_mesh_ctrlmode_in, c3_mesh_access_in,
|
|
c3_mesh_write_in, c3_mesh_dstaddr_in, c3_mesh_srcaddr_in,
|
|
c3_mesh_data_in, c3_mesh_datamode_in, c3_mesh_ctrlmode_in,
|
|
c0_emesh_wait_in, c3_emesh_wait_in, c0_mesh_wait_in,
|
|
c3_mesh_wait_in, c0_rdmesh_wait_in, c1_rdmesh_wait_in,
|
|
c2_rdmesh_wait_in, c3_rdmesh_wait_in
|
|
);
|
|
|
|
parameter DW = `CFG_DW ;//data width
|
|
parameter AW = `CFG_AW ;//address width
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
|
|
// #########
|
|
// # Inputs
|
|
// #########
|
|
|
|
input reset; //reset input
|
|
input [3:0] ext_yid_k; //external y-id
|
|
input [3:0] ext_xid_k; //external x-id
|
|
|
|
input [5:0] txo_cfg_reg;// Link configuration register
|
|
input vertical_k; // specifies if block is vertical or horizontal
|
|
input [3:0] who_am_i; // specifies what link is that (north,east,south,west)
|
|
input cfg_extcomp_dis;// Disable external coordinates comparison
|
|
// Every input transaction is received by the chip
|
|
// # Vertical_k usage:
|
|
// # West/East link port is "vertical", i.e. sends transactions to the cores
|
|
// # horizontally, according to the row_k[2:0] index
|
|
// # North/South link port is "horizontal", i.e. sends transactions to the cores
|
|
// # vertically, according to the col_k[2:0] index
|
|
// # In order to distinguish between West/East and North/South,
|
|
// # vertical_k index is used.
|
|
|
|
// # Receiver
|
|
input [LW-1:0] rxi_data; // Byte word
|
|
input rxi_lclk; // receive clock (adjusted to the frame/data)
|
|
input rxi_frame; // indicates new transmission
|
|
|
|
// # Transmitter
|
|
input txo_rd_wait; // wait indicator on read transactions
|
|
input txo_wr_wait; // wait indicator on write transactions
|
|
|
|
// # Clocks
|
|
input c0_clk_in; // clock of the core
|
|
input c1_clk_in; // clock of the core
|
|
input c2_clk_in; // clock of the core
|
|
input c3_clk_in; // clock of the core
|
|
|
|
// # EMESH
|
|
input [2*LW-1:0] c0_emesh_tran_in; // serialized transaction
|
|
input c0_emesh_frame_in; // transaction frame
|
|
input [2*LW-1:0] c1_emesh_tran_in; // serialized transaction
|
|
input c1_emesh_frame_in; // transaction frame
|
|
input [2*LW-1:0] c2_emesh_tran_in; // serialized transaction
|
|
input c2_emesh_frame_in; // transaction frame
|
|
input [2*LW-1:0] c3_emesh_tran_in; // serialized transaction
|
|
input c3_emesh_frame_in; // transaction frame
|
|
// # RDMESH
|
|
input [2*LW-1:0] c0_rdmesh_tran_in; // serialized transaction
|
|
input c0_rdmesh_frame_in; // transaction frame
|
|
input [2*LW-1:0] c1_rdmesh_tran_in; // serialized transaction
|
|
input c1_rdmesh_frame_in; // transaction frame
|
|
input [2*LW-1:0] c2_rdmesh_tran_in; // serialized transaction
|
|
input c2_rdmesh_frame_in; // transaction frame
|
|
input [2*LW-1:0] c3_rdmesh_tran_in; // serialized transaction
|
|
input c3_rdmesh_frame_in; // transaction frame
|
|
// # MESH
|
|
// # core0 (external corners and multicast)
|
|
input c0_mesh_access_in; // access control from the mesh
|
|
input c0_mesh_write_in; // write control from the mesh
|
|
input [AW-1:0] c0_mesh_dstaddr_in; // destination address from the mesh
|
|
input [AW-1:0] c0_mesh_srcaddr_in; // source address from the mesh
|
|
input [DW-1:0] c0_mesh_data_in; // data from the mesh
|
|
input [1:0] c0_mesh_datamode_in;// data mode from the mesh
|
|
input [3:0] c0_mesh_ctrlmode_in;// ctrl mode from the mesh
|
|
// # core3 (external corners only)
|
|
input c3_mesh_access_in; // access control from the mesh
|
|
input c3_mesh_write_in; // write control from the mesh
|
|
input [AW-1:0] c3_mesh_dstaddr_in; // destination address from the mesh
|
|
input [AW-1:0] c3_mesh_srcaddr_in; // source address from the mesh
|
|
input [DW-1:0] c3_mesh_data_in; // data from the mesh
|
|
input [1:0] c3_mesh_datamode_in;// data mode from the mesh
|
|
input [3:0] c3_mesh_ctrlmode_in;// ctrl mode from the mesh
|
|
|
|
//# Waits
|
|
input c0_emesh_wait_in; // wait
|
|
input c3_emesh_wait_in; // wait
|
|
input c0_mesh_wait_in; // wait
|
|
input c3_mesh_wait_in; // wait
|
|
input c0_rdmesh_wait_in; // wait
|
|
input c1_rdmesh_wait_in; // wait
|
|
input c2_rdmesh_wait_in; // wait
|
|
input c3_rdmesh_wait_in; // wait
|
|
|
|
// ##############
|
|
// # Outputs
|
|
// ##############
|
|
|
|
// # Receiver
|
|
output rxi_rd_wait; // wait indicator on read transaction
|
|
output rxi_wr_wait; // wait indicator on write transaction
|
|
|
|
// # Transmitter
|
|
output [LW-1:0] txo_data; // Byte word
|
|
output txo_lclk; // transmit clock (adjusted to the frame/data)
|
|
output txo_frame; // indicates new transmission
|
|
|
|
//# EMESH (write transactions with the off chip destination)
|
|
output c0_emesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c0_emesh_tran_out; // serialized transaction
|
|
output c3_emesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c3_emesh_tran_out; // serialized transaction
|
|
// # RDMESH (any read transaction)
|
|
output c0_rdmesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c0_rdmesh_tran_out; // serialized transaction
|
|
output c1_rdmesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c1_rdmesh_tran_out; // serialized transaction
|
|
output c2_rdmesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c2_rdmesh_tran_out; // serialized transaction
|
|
output c3_rdmesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c3_rdmesh_tran_out; // serialized transaction
|
|
// # MESH (write transactions internal and external corners)
|
|
// # core0
|
|
output c0_mesh_access_out; // access control to the mesh
|
|
output c0_mesh_write_out; // write control to the mesh
|
|
output [AW-1:0] c0_mesh_dstaddr_out; // destination address to the mesh
|
|
output [AW-1:0] c0_mesh_srcaddr_out; // source address to the mesh
|
|
output [DW-1:0] c0_mesh_data_out; // data to the mesh
|
|
output [1:0] c0_mesh_datamode_out;// data mode to the mesh
|
|
output [3:0] c0_mesh_ctrlmode_out;// ctrl mode to the mesh
|
|
// # core3
|
|
output c3_mesh_access_out; // access control to the mesh
|
|
output c3_mesh_write_out; // write control to the mesh
|
|
output [AW-1:0] c3_mesh_dstaddr_out; // destination address to the mesh
|
|
output [AW-1:0] c3_mesh_srcaddr_out; // source address to the mesh
|
|
output [DW-1:0] c3_mesh_data_out; // data to the mesh
|
|
output [1:0] c3_mesh_datamode_out;// data mode to the mesh
|
|
output [3:0] c3_mesh_ctrlmode_out;// ctrl mode to the mesh
|
|
|
|
// # Waits
|
|
output c0_emesh_wait_out; // wait to the emesh
|
|
output c1_emesh_wait_out; // wait to the emesh
|
|
output c2_emesh_wait_out; // wait to the emesh
|
|
output c3_emesh_wait_out; // wait to the emesh
|
|
|
|
output c0_rdmesh_wait_out; // wait to the rdmesh
|
|
output c1_rdmesh_wait_out; // wait to the rdmesh
|
|
output c2_rdmesh_wait_out; // wait to the rdmesh
|
|
output c3_rdmesh_wait_out; // wait to the rdmesh
|
|
|
|
output c0_mesh_wait_out; // wait to the mesh
|
|
output c3_mesh_wait_out; // wait to the mesh
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
// #########################
|
|
// # Receiver instantiation
|
|
// #########################
|
|
|
|
link_receiver link_receiver(/*AUTOINST*/
|
|
// Outputs
|
|
.rxi_wr_wait (rxi_wr_wait),
|
|
.rxi_rd_wait (rxi_rd_wait),
|
|
.c0_emesh_frame_out(c0_emesh_frame_out),
|
|
.c0_emesh_tran_out(c0_emesh_tran_out[2*LW-1:0]),
|
|
.c3_emesh_frame_out(c3_emesh_frame_out),
|
|
.c3_emesh_tran_out(c3_emesh_tran_out[2*LW-1:0]),
|
|
.c0_rdmesh_frame_out(c0_rdmesh_frame_out),
|
|
.c0_rdmesh_tran_out(c0_rdmesh_tran_out[2*LW-1:0]),
|
|
.c1_rdmesh_frame_out(c1_rdmesh_frame_out),
|
|
.c1_rdmesh_tran_out(c1_rdmesh_tran_out[2*LW-1:0]),
|
|
.c2_rdmesh_frame_out(c2_rdmesh_frame_out),
|
|
.c2_rdmesh_tran_out(c2_rdmesh_tran_out[2*LW-1:0]),
|
|
.c3_rdmesh_frame_out(c3_rdmesh_frame_out),
|
|
.c3_rdmesh_tran_out(c3_rdmesh_tran_out[2*LW-1:0]),
|
|
.c0_mesh_access_out(c0_mesh_access_out),
|
|
.c0_mesh_write_out(c0_mesh_write_out),
|
|
.c0_mesh_dstaddr_out(c0_mesh_dstaddr_out[AW-1:0]),
|
|
.c0_mesh_srcaddr_out(c0_mesh_srcaddr_out[AW-1:0]),
|
|
.c0_mesh_data_out(c0_mesh_data_out[DW-1:0]),
|
|
.c0_mesh_datamode_out(c0_mesh_datamode_out[1:0]),
|
|
.c0_mesh_ctrlmode_out(c0_mesh_ctrlmode_out[3:0]),
|
|
.c3_mesh_access_out(c3_mesh_access_out),
|
|
.c3_mesh_write_out(c3_mesh_write_out),
|
|
.c3_mesh_dstaddr_out(c3_mesh_dstaddr_out[AW-1:0]),
|
|
.c3_mesh_srcaddr_out(c3_mesh_srcaddr_out[AW-1:0]),
|
|
.c3_mesh_data_out(c3_mesh_data_out[DW-1:0]),
|
|
.c3_mesh_datamode_out(c3_mesh_datamode_out[1:0]),
|
|
.c3_mesh_ctrlmode_out(c3_mesh_ctrlmode_out[3:0]),
|
|
// Inputs
|
|
.reset (reset),
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.vertical_k (vertical_k),
|
|
.who_am_i (who_am_i[3:0]),
|
|
.cfg_extcomp_dis(cfg_extcomp_dis),
|
|
.rxi_data (rxi_data[LW-1:0]),
|
|
.rxi_lclk (rxi_lclk),
|
|
.rxi_frame (rxi_frame),
|
|
.c0_clk_in (c0_clk_in),
|
|
.c1_clk_in (c1_clk_in),
|
|
.c2_clk_in (c2_clk_in),
|
|
.c3_clk_in (c3_clk_in),
|
|
.c0_emesh_wait_in(c0_emesh_wait_in),
|
|
.c3_emesh_wait_in(c3_emesh_wait_in),
|
|
.c0_mesh_wait_in(c0_mesh_wait_in),
|
|
.c3_mesh_wait_in(c3_mesh_wait_in),
|
|
.c0_rdmesh_wait_in(c0_rdmesh_wait_in),
|
|
.c1_rdmesh_wait_in(c1_rdmesh_wait_in),
|
|
.c2_rdmesh_wait_in(c2_rdmesh_wait_in),
|
|
.c3_rdmesh_wait_in(c3_rdmesh_wait_in));
|
|
|
|
|
|
// ############################
|
|
// # Transmitter instantiation
|
|
// ############################
|
|
|
|
link_transmitter link_transmitter(.txo_lclk90 (txo_lclk),
|
|
/*AUTOINST*/
|
|
// Outputs
|
|
.txo_data (txo_data[LW-1:0]),
|
|
.txo_frame (txo_frame),
|
|
.c0_emesh_wait_out(c0_emesh_wait_out),
|
|
.c1_emesh_wait_out(c1_emesh_wait_out),
|
|
.c2_emesh_wait_out(c2_emesh_wait_out),
|
|
.c3_emesh_wait_out(c3_emesh_wait_out),
|
|
.c0_rdmesh_wait_out(c0_rdmesh_wait_out),
|
|
.c1_rdmesh_wait_out(c1_rdmesh_wait_out),
|
|
.c2_rdmesh_wait_out(c2_rdmesh_wait_out),
|
|
.c3_rdmesh_wait_out(c3_rdmesh_wait_out),
|
|
.c0_mesh_wait_out (c0_mesh_wait_out),
|
|
.c3_mesh_wait_out (c3_mesh_wait_out),
|
|
// Inputs
|
|
.reset (reset),
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.who_am_i (who_am_i[3:0]),
|
|
.txo_cfg_reg (txo_cfg_reg[5:0]),
|
|
.txo_wr_wait (txo_wr_wait),
|
|
.txo_rd_wait (txo_rd_wait),
|
|
.c0_clk_in (c0_clk_in),
|
|
.c1_clk_in (c1_clk_in),
|
|
.c2_clk_in (c2_clk_in),
|
|
.c3_clk_in (c3_clk_in),
|
|
.c0_mesh_access_in(c0_mesh_access_in),
|
|
.c0_mesh_write_in (c0_mesh_write_in),
|
|
.c0_mesh_dstaddr_in(c0_mesh_dstaddr_in[AW-1:0]),
|
|
.c0_mesh_srcaddr_in(c0_mesh_srcaddr_in[AW-1:0]),
|
|
.c0_mesh_data_in (c0_mesh_data_in[DW-1:0]),
|
|
.c0_mesh_datamode_in(c0_mesh_datamode_in[1:0]),
|
|
.c0_mesh_ctrlmode_in(c0_mesh_ctrlmode_in[3:0]),
|
|
.c3_mesh_access_in(c3_mesh_access_in),
|
|
.c3_mesh_write_in (c3_mesh_write_in),
|
|
.c3_mesh_dstaddr_in(c3_mesh_dstaddr_in[AW-1:0]),
|
|
.c3_mesh_srcaddr_in(c3_mesh_srcaddr_in[AW-1:0]),
|
|
.c3_mesh_data_in (c3_mesh_data_in[DW-1:0]),
|
|
.c3_mesh_datamode_in(c3_mesh_datamode_in[1:0]),
|
|
.c3_mesh_ctrlmode_in(c3_mesh_ctrlmode_in[3:0]));
|
|
|
|
endmodule // link_port
|
|
|
|
|
|
module link_receiver(/*AUTOARG*/
|
|
// Outputs
|
|
rxi_wr_wait, rxi_rd_wait, c0_emesh_frame_out, c0_emesh_tran_out,
|
|
c3_emesh_frame_out, c3_emesh_tran_out, c0_rdmesh_frame_out,
|
|
c0_rdmesh_tran_out, c1_rdmesh_frame_out, c1_rdmesh_tran_out,
|
|
c2_rdmesh_frame_out, c2_rdmesh_tran_out, c3_rdmesh_frame_out,
|
|
c3_rdmesh_tran_out, c0_mesh_access_out, c0_mesh_write_out,
|
|
c0_mesh_dstaddr_out, c0_mesh_srcaddr_out, c0_mesh_data_out,
|
|
c0_mesh_datamode_out, c0_mesh_ctrlmode_out, c3_mesh_access_out,
|
|
c3_mesh_write_out, c3_mesh_dstaddr_out, c3_mesh_srcaddr_out,
|
|
c3_mesh_data_out, c3_mesh_datamode_out, c3_mesh_ctrlmode_out,
|
|
// Inputs
|
|
reset, ext_yid_k, ext_xid_k, vertical_k, who_am_i, cfg_extcomp_dis,
|
|
rxi_data, rxi_lclk, rxi_frame, c0_clk_in, c1_clk_in, c2_clk_in,
|
|
c3_clk_in, c0_emesh_wait_in, c3_emesh_wait_in, c0_mesh_wait_in,
|
|
c3_mesh_wait_in, c0_rdmesh_wait_in, c1_rdmesh_wait_in,
|
|
c2_rdmesh_wait_in, c3_rdmesh_wait_in
|
|
);
|
|
|
|
parameter LW = `CFG_LW;//lvds tranceiver pairs per side
|
|
parameter DW = `CFG_DW;//data width
|
|
parameter AW = `CFG_AW;//address width
|
|
|
|
// #########
|
|
// # Inputs
|
|
// #########
|
|
|
|
input reset; // reset input
|
|
input [3:0] ext_yid_k; // external y-id
|
|
input [3:0] ext_xid_k; // external x-id
|
|
input vertical_k;// specifies if block is vertical or horizontal
|
|
input [3:0] who_am_i; // specifies what link is that (north,east,south,west)
|
|
input cfg_extcomp_dis;// Disable external coordinates comparison
|
|
// Every input transaction is received by the chip
|
|
|
|
input [LW-1:0] rxi_data; // Byte word
|
|
input rxi_lclk; // receive clock (adjusted to the frame/data)
|
|
input rxi_frame; // indicates new transmission
|
|
|
|
// # Sync clocks
|
|
input c0_clk_in; // clock of the core
|
|
input c1_clk_in; // clock of the core
|
|
input c2_clk_in; // clock of the core
|
|
input c3_clk_in; // clock of the core
|
|
|
|
// # Wait indicators
|
|
input c0_emesh_wait_in; // wait
|
|
input c3_emesh_wait_in; // wait
|
|
input c0_mesh_wait_in; // wait
|
|
input c3_mesh_wait_in; // wait
|
|
input c0_rdmesh_wait_in; // wait
|
|
input c1_rdmesh_wait_in; // wait
|
|
input c2_rdmesh_wait_in; // wait
|
|
input c3_rdmesh_wait_in; // wait
|
|
|
|
// ##########
|
|
// # Outputs
|
|
// ##########
|
|
|
|
output rxi_wr_wait; //wait indicator for write transactions
|
|
output rxi_rd_wait; //wait indicator for read transactions
|
|
|
|
//# EMESH (write transactions with the off chip destination)
|
|
output c0_emesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c0_emesh_tran_out; // serialized transaction
|
|
output c3_emesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c3_emesh_tran_out; // serialized transaction
|
|
// # RDMESH (any read transaction)
|
|
output c0_rdmesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c0_rdmesh_tran_out; // serialized transaction
|
|
output c1_rdmesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c1_rdmesh_tran_out; // serialized transaction
|
|
output c2_rdmesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c2_rdmesh_tran_out; // serialized transaction
|
|
output c3_rdmesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c3_rdmesh_tran_out; // serialized transaction
|
|
// # MESH (write transactions internal and external corners)
|
|
// # core0
|
|
output c0_mesh_access_out; // access control to the mesh
|
|
output c0_mesh_write_out; // write control to the mesh
|
|
output [AW-1:0] c0_mesh_dstaddr_out; // destination address to the mesh
|
|
output [AW-1:0] c0_mesh_srcaddr_out; // source address to the mesh
|
|
output [DW-1:0] c0_mesh_data_out; // data to the mesh
|
|
output [1:0] c0_mesh_datamode_out;// data mode to the mesh
|
|
output [3:0] c0_mesh_ctrlmode_out;// ctrl mode to the mesh
|
|
// # core3
|
|
output c3_mesh_access_out; // access control to the mesh
|
|
output c3_mesh_write_out; // write control to the mesh
|
|
output [AW-1:0] c3_mesh_dstaddr_out; // destination address to the mesh
|
|
output [AW-1:0] c3_mesh_srcaddr_out; // source address to the mesh
|
|
output [DW-1:0] c3_mesh_data_out; // data to the mesh
|
|
output [1:0] c3_mesh_datamode_out;// data mode to the mesh
|
|
output [3:0] c3_mesh_ctrlmode_out;// ctrl mode to the mesh
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
//#################################
|
|
//# Write Transactions Receiver
|
|
//#################################
|
|
|
|
link_rxi_wr link_rxi_wr(/*AUTOINST*/
|
|
// Outputs
|
|
.rxi_wr_wait (rxi_wr_wait),
|
|
.c0_emesh_frame_out (c0_emesh_frame_out),
|
|
.c0_emesh_tran_out (c0_emesh_tran_out[2*LW-1:0]),
|
|
.c3_emesh_frame_out (c3_emesh_frame_out),
|
|
.c3_emesh_tran_out (c3_emesh_tran_out[2*LW-1:0]),
|
|
.c0_mesh_access_out (c0_mesh_access_out),
|
|
.c0_mesh_write_out (c0_mesh_write_out),
|
|
.c0_mesh_dstaddr_out (c0_mesh_dstaddr_out[AW-1:0]),
|
|
.c0_mesh_srcaddr_out (c0_mesh_srcaddr_out[AW-1:0]),
|
|
.c0_mesh_data_out (c0_mesh_data_out[DW-1:0]),
|
|
.c0_mesh_datamode_out(c0_mesh_datamode_out[1:0]),
|
|
.c0_mesh_ctrlmode_out(c0_mesh_ctrlmode_out[3:0]),
|
|
.c3_mesh_access_out (c3_mesh_access_out),
|
|
.c3_mesh_write_out (c3_mesh_write_out),
|
|
.c3_mesh_dstaddr_out (c3_mesh_dstaddr_out[AW-1:0]),
|
|
.c3_mesh_srcaddr_out (c3_mesh_srcaddr_out[AW-1:0]),
|
|
.c3_mesh_data_out (c3_mesh_data_out[DW-1:0]),
|
|
.c3_mesh_datamode_out(c3_mesh_datamode_out[1:0]),
|
|
.c3_mesh_ctrlmode_out(c3_mesh_ctrlmode_out[3:0]),
|
|
// Inputs
|
|
.reset (reset),
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.vertical_k (vertical_k),
|
|
.who_am_i (who_am_i[3:0]),
|
|
.cfg_extcomp_dis (cfg_extcomp_dis),
|
|
.rxi_data (rxi_data[LW-1:0]),
|
|
.rxi_lclk (rxi_lclk),
|
|
.rxi_frame (rxi_frame),
|
|
.c0_clk_in (c0_clk_in),
|
|
.c3_clk_in (c3_clk_in),
|
|
.c0_emesh_wait_in (c0_emesh_wait_in),
|
|
.c3_emesh_wait_in (c3_emesh_wait_in),
|
|
.c0_mesh_wait_in (c0_mesh_wait_in),
|
|
.c3_mesh_wait_in (c3_mesh_wait_in));
|
|
|
|
//#################################
|
|
//# Read Transactions Receiver
|
|
//#################################
|
|
|
|
link_rxi_rd link_rxi_rd(/*AUTOINST*/
|
|
// Outputs
|
|
.rxi_rd_wait (rxi_rd_wait),
|
|
.c0_rdmesh_frame_out (c0_rdmesh_frame_out),
|
|
.c0_rdmesh_tran_out (c0_rdmesh_tran_out[2*LW-1:0]),
|
|
.c1_rdmesh_frame_out (c1_rdmesh_frame_out),
|
|
.c1_rdmesh_tran_out (c1_rdmesh_tran_out[2*LW-1:0]),
|
|
.c2_rdmesh_frame_out (c2_rdmesh_frame_out),
|
|
.c2_rdmesh_tran_out (c2_rdmesh_tran_out[2*LW-1:0]),
|
|
.c3_rdmesh_frame_out (c3_rdmesh_frame_out),
|
|
.c3_rdmesh_tran_out (c3_rdmesh_tran_out[2*LW-1:0]),
|
|
// Inputs
|
|
.reset (reset),
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.vertical_k (vertical_k),
|
|
.who_am_i (who_am_i[3:0]),
|
|
.cfg_extcomp_dis (cfg_extcomp_dis),
|
|
.rxi_data (rxi_data[LW-1:0]),
|
|
.rxi_lclk (rxi_lclk),
|
|
.rxi_frame (rxi_frame),
|
|
.c0_clk_in (c0_clk_in),
|
|
.c1_clk_in (c1_clk_in),
|
|
.c2_clk_in (c2_clk_in),
|
|
.c3_clk_in (c3_clk_in),
|
|
.c0_rdmesh_wait_in (c0_rdmesh_wait_in),
|
|
.c1_rdmesh_wait_in (c1_rdmesh_wait_in),
|
|
.c2_rdmesh_wait_in (c2_rdmesh_wait_in),
|
|
.c3_rdmesh_wait_in (c3_rdmesh_wait_in));
|
|
|
|
|
|
|
|
endmodule // link_receiver
|
|
|
|
//############################################################################
|
|
//# The input data stream is of the following structure:
|
|
//#
|
|
//# --- --- --- --- --- ---
|
|
//# lclk _| |___| |___| |___| |___| |___| |_
|
|
//#
|
|
//# -------------------------------
|
|
//# frame ______/
|
|
//# --- --- --- --- ---
|
|
//# data XXXXXXX 0 X 1 X 2 X 3 X 4 X .....
|
|
//# --- --- --- --- ---
|
|
//#
|
|
//# byte0 (the byte received on the rising edge of the clock the
|
|
//# same cycle the frame's rising edge is detected) holds the
|
|
//# information of the transmitted transaction.
|
|
//#
|
|
//# byte0 | transaction type
|
|
//# ----------------- | ----------------
|
|
//# 8'b??_??_?0_<cid> | New transaction with incremental bursting address
|
|
//# 8'b??_??_?1_<cid> | New transaction with the same bursting address
|
|
//#
|
|
//# cid[1:0] - channel id (for now for debugging usage only)
|
|
//#
|
|
//# New transaction structure:
|
|
//# -------------------------
|
|
//# byte1 -> ctrlmode[3:0],dstaddr[31:28]
|
|
//# byte2 -> dstaddr[27:20]
|
|
//# byte3 -> dstaddr[19:12]
|
|
//# byte4 -> dstaddr[11:4]
|
|
//# byte5 -> dstaddr[3:0],datamode[1:0],write,access
|
|
//# byte6 -> data[31:24] (or srcaddr[31:24] if read transaction)
|
|
//# byte7 -> data[23:16] (or srcaddr[23:16] if read transaction)
|
|
//# byte8 -> data[15:8] (or srcaddr[15:8] if read transaction)
|
|
//# *byte9 -> data[7:0] (or srcaddr[7:0] if read transaction)
|
|
//# byte10 -> data[63:56]
|
|
//# byte11 -> data[55:48]
|
|
//# byte12 -> data[47:40]
|
|
//# byte13 -> data[39:32]
|
|
//# **byte14 -> data[31:24]
|
|
//# ...
|
|
//# ...
|
|
//# ...
|
|
//#
|
|
//# * byte9 is the last byte of 32 bit write or read transaction
|
|
//#
|
|
//# ** if 64 bit write transaction, data of byte14 is the first data byte of
|
|
//# bursting transaction
|
|
//#
|
|
//# -- The data is transmitted MSB first but in 32bits resolution. If we want
|
|
//# to transmit 64 bits it will be [31:0] (msb first) and then [63:32] (msb first)
|
|
//#
|
|
//# !!!
|
|
//# !!! According to the above scheme, any new transaction (burst or not)
|
|
//# !!! will take at least four cycles to be transmitted.
|
|
//# !!! There are some internal mechanisms in the transmitter-receiver logic
|
|
//# !!! which are implemented considering this assumption true.
|
|
//# !!! Any change to this assumption (transaction takes at least four cycles)
|
|
//# !!! should be carefully reviewed with its implications on the internal
|
|
//# !!! implementation
|
|
//# !!!
|
|
//#
|
|
//#####################################################################
|
|
module link_rxi_assembler (/*AUTOARG*/
|
|
// Outputs
|
|
rxi_assembled_tran, rxi_c0_access, rxi_c1_access, rxi_c2_access,
|
|
rxi_c3_access,
|
|
// Inputs
|
|
reset, rxi_lclk, vertical_k, ext_yid_k, ext_xid_k, fifo_data_reg,
|
|
fifo_data_val, start_tran, cfg_extcomp_dis
|
|
);
|
|
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
parameter DW = `CFG_DW ;//data width
|
|
parameter AW = `CFG_AW ;//address width
|
|
|
|
// #########
|
|
// # INPUTS
|
|
// #########
|
|
input reset; //reset input
|
|
input rxi_lclk; //receive clock (adjusted to the frame/data)
|
|
|
|
input vertical_k; //specifies if block is vertical or horizontal
|
|
input [3:0] ext_yid_k; //external y-id
|
|
input [3:0] ext_xid_k; //external x-id
|
|
|
|
input [2*LW-1:0] fifo_data_reg;// output of the input receiver fifo
|
|
input fifo_data_val;// fifo_data_reg is valid
|
|
input start_tran; // Start transaction bit
|
|
|
|
input cfg_extcomp_dis;// Disable external coordinates comparison
|
|
// Every input transaction is received by the chip
|
|
// ##########
|
|
// # OUTPUTS
|
|
// ##########
|
|
output [14*LW-1:0] rxi_assembled_tran; // data to be transferred to secondary fifos
|
|
output rxi_c0_access; //transfering to c0_fifo
|
|
output rxi_c1_access; //transfering to c1_fifo
|
|
output rxi_c2_access; //transfering to c2_fifo
|
|
output rxi_c3_access; //transfering to c3_fifo
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
// #########
|
|
// # REGS
|
|
// #########
|
|
reg [LW-1:0] tran_byte0;
|
|
reg [2:0] rxi_assemble_cnt;
|
|
reg [3:0] ctrlmode;
|
|
reg [AW-1:0] dstaddr_int;
|
|
reg [1:0] datamode;
|
|
reg write;
|
|
reg access;
|
|
reg [DW-1:0] data;
|
|
reg [AW-1:0] srcaddr;
|
|
reg rxi_cx_access;
|
|
|
|
// #########
|
|
// # WIRES
|
|
// #########
|
|
wire byte0_inc8; // Address of the burst transaction should be incremented
|
|
wire dstaddr_2712_en;
|
|
wire dstaddr_1100_en;
|
|
wire datamode_en;
|
|
wire write_en;
|
|
wire access_en;
|
|
wire data_3116_en;
|
|
wire data_1500_en;
|
|
wire srcaddr_3116_en;
|
|
wire srcaddr_1500_en;
|
|
wire [2:0] rxi_assemble_cnt_next; // Next value of the assembly counter
|
|
wire [2:0] rxi_assemble_cnt_inc; // Incremented value of the assembly counter
|
|
wire rxi_assemble_cnt_max; // Maximum value of the counter
|
|
wire burst_tran; // detected burst transaction
|
|
wire [AW-1:0] dstaddr_inc; // Incremented value of burst transaction dstaddr
|
|
wire [AW-1:0] dstaddr_in; // Input to the next destination address FF
|
|
wire single_write; // single write transaction
|
|
wire single_write_complete; // single write transaction is complete
|
|
wire read_jump; // read transaction "jumps" over data part
|
|
wire tran_assembled; // transaction is assembled
|
|
wire [5:0] comp_addr;
|
|
wire [5:0] chip_addr;
|
|
wire [5:0] comp_low;
|
|
wire carry_low;
|
|
wire zero_low;
|
|
wire [5:0] comp_high;
|
|
wire carry_high;
|
|
wire c0_match;
|
|
wire c1_match;
|
|
wire c2_match;
|
|
wire c3_match;
|
|
wire multicast_match;
|
|
wire [AW-1:0] dstaddr;
|
|
|
|
//##############################
|
|
//# Assembled data and controls
|
|
//##############################
|
|
|
|
assign rxi_assembled_tran[14*LW-1:0]={
|
|
srcaddr[7:0],{(LW){1'b0}},
|
|
srcaddr[23:8],
|
|
data[7:0],srcaddr[31:24],
|
|
data[23:8],
|
|
dstaddr[3:0],datamode[1:0],write,access,data[31:24],
|
|
dstaddr[19:4],
|
|
ctrlmode[3:0],dstaddr[31:20]
|
|
};
|
|
|
|
//####################
|
|
//# Byte0 detection
|
|
//####################
|
|
|
|
always @ (posedge rxi_lclk)
|
|
if(fifo_data_val & start_tran)
|
|
begin
|
|
tran_byte0[LW-1:0] <= fifo_data_reg[2*LW-1:LW];
|
|
ctrlmode[3:0] <= fifo_data_reg[7:4];
|
|
end
|
|
|
|
//# byte0 decode
|
|
//# bit[2] is the only one in use for now
|
|
assign byte0_inc8 = ~tran_byte0[2];
|
|
|
|
//##########################
|
|
//# Transaction assembly
|
|
//##########################
|
|
|
|
//# destination address
|
|
//# There is a special mode set in the Link Bypass Configuration Register
|
|
//# which forces the chip to receive all of the transactions entering the chip
|
|
//# In this case we just replace the external coordinates of the destination
|
|
//# address with the chip coordinates.
|
|
// assign dstaddr[31:29] = cfg_extcomp_dis ? ext_yid_k[2:0] : dstaddr_int[31:29];
|
|
// assign dstaddr[28:26] = cfg_extcomp_dis ? ext_xid_k[2:0] : dstaddr_int[28:26];
|
|
// assign dstaddr[25:0] = dstaddr_int[25:0];
|
|
assign dstaddr[31:28] = cfg_extcomp_dis ? ext_yid_k[3:0] : dstaddr_int[31:28];
|
|
assign dstaddr[25:22] = cfg_extcomp_dis ? ext_xid_k[3:0] : dstaddr_int[25:22];
|
|
assign dstaddr[27:26] = dstaddr_int[27:26];
|
|
assign dstaddr[21:0] = dstaddr_int[21:0];
|
|
|
|
// assign comp_addr[5:0] = vertical_k ? {dstaddr[31:29],dstaddr[25:23]} :
|
|
// {dstaddr[28:26],dstaddr[22:20]} ;
|
|
|
|
// assign chip_addr[2:0] = vertical_k ? ext_yid_k[2:0] : ext_xid_k[2:0];
|
|
|
|
//# destination address is updated on the beginning of burst transaction
|
|
//# while datamode, write, access and control mode are unchanged
|
|
assign dstaddr_inc[AW-1:0] = dstaddr[AW-1:0] + {{(AW-4){1'b0}},byte0_inc8,3'b000};
|
|
|
|
assign dstaddr_in[31:28] = burst_tran ? dstaddr_inc[31:28] : fifo_data_reg[3:0];
|
|
assign dstaddr_in[27:12] = burst_tran ? dstaddr_inc[27:12] : fifo_data_reg[2*LW-1:0];
|
|
assign dstaddr_in[11:0] = burst_tran ? dstaddr_inc[11:0] : fifo_data_reg[2*LW-1:4];
|
|
|
|
always @ (posedge rxi_lclk)
|
|
if(fifo_data_val & (start_tran | burst_tran))
|
|
dstaddr_int[31:28] <= dstaddr_in[31:28];
|
|
|
|
always @ (posedge rxi_lclk)
|
|
if(fifo_data_val & (dstaddr_2712_en | burst_tran))
|
|
dstaddr_int[27:12] <= dstaddr_in[27:12];
|
|
|
|
always @ (posedge rxi_lclk)
|
|
if(fifo_data_val & (dstaddr_1100_en | burst_tran))
|
|
dstaddr_int[11:0] <= dstaddr_in[11:0];
|
|
|
|
//# data mode
|
|
always @ (posedge rxi_lclk)
|
|
if(fifo_data_val & datamode_en)
|
|
datamode[1:0] <= fifo_data_reg[3:2];
|
|
|
|
//# write
|
|
always @ (posedge rxi_lclk)
|
|
if(fifo_data_val & write_en)
|
|
write <= fifo_data_reg[1];
|
|
|
|
//# access
|
|
always @ (posedge rxi_lclk)
|
|
if(fifo_data_val & access_en)
|
|
access <= fifo_data_reg[0];
|
|
|
|
//# data
|
|
always @ (posedge rxi_lclk)
|
|
if(fifo_data_val & (data_3116_en | burst_tran))
|
|
data[31:16] <= fifo_data_reg[2*LW-1:0];
|
|
|
|
always @ (posedge rxi_lclk)
|
|
if(fifo_data_val & data_1500_en)
|
|
data[15:0] <= fifo_data_reg[2*LW-1:0];
|
|
|
|
//# srcaddr
|
|
always @ (posedge rxi_lclk)
|
|
if(fifo_data_val & srcaddr_3116_en)
|
|
srcaddr[31:16] <= fifo_data_reg[2*LW-1:0];
|
|
|
|
always @ (posedge rxi_lclk)
|
|
if(fifo_data_val & srcaddr_1500_en)
|
|
srcaddr[15:0] <= fifo_data_reg[2*LW-1:0];
|
|
|
|
|
|
//###################################################################
|
|
//# Order of the transaction fields in the fifo
|
|
//# -------------------------------------------
|
|
//# Entry "n+6" srcaddr[15:0]
|
|
//# Entry "n+5" srcaddr[31:16],
|
|
//# Entry "n+4" data[15:0],
|
|
//# Entry "n+3" data[31:16],
|
|
//# Entry "n+2" dstaddr[11:0],datamode[1:0],write,access,
|
|
//# Entry "n+1" dstaddr[27:12],
|
|
//# Entry "n" byte0[7:0],ctrlmode[3:0],dstaddr[31:28],
|
|
//# --------------------------------------------
|
|
//####################################################################
|
|
|
|
assign dstaddr_2712_en = (rxi_assemble_cnt[2:0] == 3'b001);
|
|
assign dstaddr_1100_en = (rxi_assemble_cnt[2:0] == 3'b010);
|
|
assign datamode_en = (rxi_assemble_cnt[2:0] == 3'b010);
|
|
assign write_en = (rxi_assemble_cnt[2:0] == 3'b010);
|
|
assign access_en = (rxi_assemble_cnt[2:0] == 3'b010);
|
|
assign data_3116_en = (rxi_assemble_cnt[2:0] == 3'b011);
|
|
assign data_1500_en = (rxi_assemble_cnt[2:0] == 3'b100);
|
|
assign srcaddr_3116_en = (rxi_assemble_cnt[2:0] == 3'b101);
|
|
assign srcaddr_1500_en = (rxi_assemble_cnt[2:0] == 3'b110);
|
|
|
|
//# Assemble counter
|
|
assign rxi_assemble_cnt_inc[2:0] = rxi_assemble_cnt[2:0] + 3'b001;
|
|
|
|
assign rxi_assemble_cnt_next[2:0] = burst_tran ? 3'b100 :
|
|
tran_assembled ? 3'b000 :
|
|
read_jump ? 3'b101 :
|
|
rxi_assemble_cnt_inc[2:0];
|
|
always @ (posedge rxi_lclk or posedge reset)
|
|
if (reset)
|
|
rxi_assemble_cnt[2:0] <= 3'b000;
|
|
else if(fifo_data_val)
|
|
rxi_assemble_cnt[2:0] <= rxi_assemble_cnt_next[2:0];
|
|
|
|
//# single write transaction completion
|
|
// assign single_write = access & write & ~(&(datamode[1:0]));
|
|
assign single_write = 1'b0; // no special treatment for single writes
|
|
assign single_write_complete = single_write & (rxi_assemble_cnt[2:0] == 3'b100);
|
|
|
|
//# read transaction "jumps" over data part of the counter
|
|
//assign read_jump = ~fifo_data_reg[1] & (rxi_assemble_cnt[2:0] == 3'b010);
|
|
//# read transaction "jump" feature is disabled because of the test-and-set inst
|
|
assign read_jump = 1'b0;
|
|
|
|
//# transaction completion
|
|
assign rxi_assemble_cnt_max = (rxi_assemble_cnt[2:0] == 3'b110);
|
|
assign tran_assembled = fifo_data_val & (single_write_complete | rxi_assemble_cnt_max);
|
|
|
|
//# burst transaction detection
|
|
assign burst_tran = (rxi_assemble_cnt[2:0] == 3'b000) & ~start_tran;
|
|
|
|
//###########################################
|
|
//# Secondary-FIFOs transaction distribution
|
|
//###########################################
|
|
|
|
always @ (posedge rxi_lclk or posedge reset)
|
|
if(reset)
|
|
rxi_cx_access <= 1'b0;
|
|
else
|
|
rxi_cx_access <= tran_assembled;
|
|
|
|
assign rxi_c0_access = (c0_match | multicast_match) & rxi_cx_access;
|
|
assign rxi_c1_access = (c1_match & ~multicast_match) & rxi_cx_access;
|
|
assign rxi_c2_access = (c2_match & ~multicast_match) & rxi_cx_access;
|
|
assign rxi_c3_access = (c3_match & ~multicast_match) & rxi_cx_access;
|
|
|
|
//# address preparation for comparison based on the links position (horiz or vert)
|
|
// assign comp_addr[5:0] = vertical_k ? {dstaddr[31:29],dstaddr[25:23]} :
|
|
// {dstaddr[28:26],dstaddr[22:20]} ;
|
|
assign comp_addr[5:0] = vertical_k ? dstaddr[31:26] : dstaddr[25:20];
|
|
|
|
// assign chip_addr[2:0] = vertical_k ? ext_yid_k[2:0] : ext_xid_k[2:0];
|
|
assign chip_addr[5:2] = vertical_k ? ext_yid_k[3:0] : ext_xid_k[3:0];
|
|
assign chip_addr[1:0] = 2'b11;
|
|
// assign chip_addr_n[3:0] =~chip_addr[3:0];
|
|
//# high comparison
|
|
// assign {carry_high,comp_high[5:0]} = comp_addr[5:0] + {chip_addr_n[2:0],3'b101};
|
|
assign {carry_high,comp_high[5:0]} = {1'b0,comp_addr[5:0]} - {1'b0,chip_addr[5:0]};
|
|
//# channels matching
|
|
assign c0_match = carry_high; // chip addr is bigger
|
|
assign c1_match = (comp_addr[5:0] == {chip_addr[5:2],3'b01});//EQ
|
|
assign c2_match = (comp_addr[5:0] == {chip_addr[5:2],3'b10});//EQ
|
|
assign c3_match = ~(c0_match | c1_match | c2_match);
|
|
//# multicast tran detection
|
|
assign multicast_match = write &
|
|
(ctrlmode[1:0]==2'b11) & ~(datamode[1:0] == 2'b11);
|
|
|
|
|
|
|
|
|
|
endmodule // link_rxi_assembler
|
|
module link_rxi_buffer (/*AUTOARG*/
|
|
// Outputs
|
|
rxi_wait, rxi_assembled_tran, rxi_c0_access, rxi_c1_access,
|
|
rxi_c2_access, rxi_c3_access,
|
|
// Inputs
|
|
reset, vertical_k, ext_yid_k, ext_xid_k, rxi_data, rxi_lclk,
|
|
rxi_frame, rxi_rd, cfg_extcomp_dis, c0_fifo_full, c1_fifo_full,
|
|
c2_fifo_full, c3_fifo_full
|
|
);
|
|
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
parameter NC = 32;// Number of cycles for save TXO-RXI "transaction interface"
|
|
parameter FAD = 5; // Number of bits to access all the entries (2^FAD + 1) > NC
|
|
localparam MD = 1<<FAD;
|
|
|
|
// #########
|
|
// # INPUTS
|
|
// #########
|
|
|
|
input reset; //reset input
|
|
input vertical_k; //specifies if block is vertical or horizontal
|
|
input [3:0] ext_yid_k; //external y-id
|
|
input [3:0] ext_xid_k; //external x-id
|
|
|
|
input [LW-1:0] rxi_data; //Byte word
|
|
input rxi_lclk; //receive clock (adjusted to the frame/data)
|
|
input rxi_frame; //indicates new transmission
|
|
|
|
input rxi_rd; // this is read transactions rxi_buffer
|
|
input cfg_extcomp_dis;// Disable external coordinates comparison
|
|
// Every input transaction is received by the chip
|
|
|
|
input c0_fifo_full;
|
|
input c1_fifo_full;
|
|
input c2_fifo_full;
|
|
input c3_fifo_full;
|
|
|
|
// ##########
|
|
// # OUTPUTS
|
|
// ##########
|
|
|
|
output rxi_wait; //wait indicator
|
|
|
|
output [14*LW-1:0] rxi_assembled_tran; // data to be transferred to secondary fifos
|
|
output rxi_c0_access; //transfering to c0_fifo
|
|
output rxi_c1_access; //transfering to c1_fifo
|
|
output rxi_c2_access; //transfering to c2_fifo
|
|
output rxi_c3_access; //transfering to c3_fifo
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
// #########
|
|
// # Regs
|
|
// #########
|
|
|
|
reg rd_tran;
|
|
reg [2*LW:0] fifo_mem[MD-1:0];
|
|
reg frame_reg;
|
|
reg frame_reg_del;
|
|
reg [LW-1:0] data_even_reg;
|
|
reg [LW-1:0] data_odd_reg;
|
|
reg [FAD:0] wr_binary_pointer;
|
|
reg [FAD:0] rd_binary_pointer;
|
|
reg fifo_read;
|
|
reg rxi_wait;
|
|
reg start_tran;
|
|
reg fifo_data_val;
|
|
reg [2*LW-1:0] fifo_data_reg;
|
|
|
|
// #########
|
|
// # Wires
|
|
// #########
|
|
|
|
wire my_tran; // this transaction is dedicated to current rxi_buffer
|
|
wire new_tran; // first cycle of the new transaction
|
|
wire [2*LW:0] fifo_data_in; // even and odd bytes combined into short words for fifo
|
|
wire [2*LW:0] fifo_data_out;// output of the fifo
|
|
wire [FAD:0] wr_binary_next; // next value of the write pointer
|
|
wire [FAD:0] rd_binary_next; // next value of the read pointer
|
|
wire fifo_write; // write into the fifo
|
|
wire [FAD-1:0] wr_addr; // write address of the fifo
|
|
wire [FAD-1:0] rd_addr; // read address of the fifo
|
|
wire fifo_empty; // indication of the empty fifo
|
|
wire stop_fifo_read; //one of the secondary fifos is full (stop reading)
|
|
|
|
// ####################################################
|
|
// # Sample input transaction
|
|
// # The positive edge FFs work all the time
|
|
// # while the negative edge FFs can be disabled
|
|
// # by the state of the detected frame (to save power)
|
|
// ####################################################
|
|
|
|
//# frame
|
|
always @ (posedge rxi_lclk or posedge reset)
|
|
if(reset)
|
|
begin
|
|
frame_reg <= 1'b0;
|
|
frame_reg_del <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
frame_reg <= rxi_frame;
|
|
frame_reg_del <= frame_reg;
|
|
end
|
|
|
|
//# even bytes
|
|
always @ (posedge rxi_lclk)
|
|
data_even_reg[LW-1:0] <= rxi_data[LW-1:0];
|
|
|
|
//# odd bytes
|
|
always @ (negedge rxi_lclk)
|
|
data_odd_reg[LW-1:0] <= rxi_data[LW-1:0];
|
|
|
|
//##################################################
|
|
//# We should differentiate between read and write
|
|
//# transactions since link_rxi_buffer can accept
|
|
//# the transactions of one type only.
|
|
//# The indication of the type of the transaction
|
|
//# is sent in the byte0 of the transaction.
|
|
//##################################################
|
|
|
|
assign my_tran = ~(rd_tran ^ rxi_rd);
|
|
always @ (posedge rxi_lclk)
|
|
if(~frame_reg) //will stop sampling when byte0 is received
|
|
rd_tran <= rxi_data[7];
|
|
|
|
//# frame rising edge detection
|
|
assign new_tran = my_tran & frame_reg & ~frame_reg_del;
|
|
|
|
//# bytes packaging into short words + new transaction indication
|
|
assign fifo_data_in[2*LW:0] = {new_tran,data_even_reg[LW-1:0],data_odd_reg[LW-1:0]};
|
|
|
|
//###############################################################################
|
|
//# Wait indication to the transmitter
|
|
//# When one of the secondary fifos becomes full we send wait indication
|
|
//# to the transmitter.
|
|
//# There is some uncertainty regarding how long it will take for the wait
|
|
//# control to stop the transmitter (we have synchronization on the way,
|
|
//# which may cause +/-1 cycle of uncertainty).
|
|
//# Our main fifo on the input port of the receiver is robust enough
|
|
//# (has enough entries) to receive all of the transactions sent during the
|
|
//# time of "wait traveling" without loosing any information.
|
|
//# But the uncertainty mentioned above forces us to start from empty fifo
|
|
//# every time after wait indication is raised in order to ensure that
|
|
//# the number of available entries won't be reduced.
|
|
//###############################################################################
|
|
|
|
assign stop_fifo_read = c0_fifo_full | c1_fifo_full | c2_fifo_full | c3_fifo_full;
|
|
|
|
always @ (posedge rxi_lclk or posedge reset)
|
|
if(reset)
|
|
rxi_wait <= 1'b0;
|
|
else if(stop_fifo_read)
|
|
rxi_wait <= 1'b1;
|
|
else if(fifo_empty)
|
|
rxi_wait <= 1'b0;
|
|
|
|
//##################################
|
|
//# Input FIFO of the receiver
|
|
//##################################
|
|
|
|
always @ (posedge rxi_lclk)
|
|
if (fifo_write)
|
|
fifo_mem[wr_addr[FAD-1:0]] <= fifo_data_in[2*LW:0];
|
|
|
|
//# Read from fifo
|
|
assign fifo_data_out[2*LW:0] = fifo_mem[rd_addr[FAD-1:0]];
|
|
|
|
//# Since the size of the FIFO is parametrized I prefer to sample the output
|
|
//# data to prevent timing issues for the big number of entries (big mux on read)
|
|
//# This shouldn't add any performance loss just latency increase
|
|
|
|
always @ (posedge rxi_lclk or posedge reset)
|
|
if(reset)
|
|
start_tran <= 1'b0;
|
|
else if(fifo_read)
|
|
start_tran <= fifo_data_out[2*LW];
|
|
|
|
always @ (posedge rxi_lclk)
|
|
if(fifo_read)
|
|
fifo_data_reg[2*LW-1:0] <= fifo_data_out[2*LW-1:0];
|
|
|
|
always @ (posedge rxi_lclk or posedge reset)
|
|
if(reset)
|
|
fifo_data_val <= 1'b0;
|
|
else
|
|
fifo_data_val <= fifo_read;
|
|
|
|
//#####################################################################
|
|
//# FIFO Write State Machine
|
|
//# !!!
|
|
//# This FIFO will write the data in every time the FRAME IS HIGH and
|
|
//# INDEPENDENT of the read out of the FIFO "frequency"
|
|
//# !!!
|
|
//# When the data cannot be read out of the FIFO, the indication will
|
|
//# be sent to the transmitter to stop sending new transactions and the
|
|
//# frame signal will be deasserted.
|
|
//# The number of entries in the FIFO sould be big enough to receive
|
|
//# all of the transactions sent by the transmitter in that case.
|
|
//######################################################################
|
|
|
|
assign fifo_write = my_tran & frame_reg;
|
|
|
|
always @(posedge rxi_lclk or posedge reset)
|
|
if(reset)
|
|
wr_binary_pointer[FAD:0] <= {(FAD+1){1'b0}};
|
|
else if(fifo_write)
|
|
wr_binary_pointer[FAD:0] <= wr_binary_next[FAD:0];
|
|
|
|
assign wr_addr[FAD-1:0] = wr_binary_pointer[FAD-1:0];
|
|
assign wr_binary_next[FAD:0] = wr_binary_pointer[FAD:0] + {{(FAD){1'b0}},fifo_write};
|
|
|
|
//#############################
|
|
//# FIFO Read State Machine
|
|
//#############################
|
|
|
|
always @(posedge rxi_lclk or posedge reset)
|
|
if(reset)
|
|
fifo_read <= 1'b0;
|
|
else
|
|
fifo_read <= ~(fifo_empty | stop_fifo_read);
|
|
|
|
always @(posedge rxi_lclk or posedge reset)
|
|
if(reset)
|
|
rd_binary_pointer[FAD:0] <= {(FAD+1){1'b0}};
|
|
else if(fifo_read)
|
|
rd_binary_pointer[FAD:0] <= rd_binary_next[FAD:0];
|
|
|
|
assign rd_addr[FAD-1:0] = rd_binary_pointer[FAD-1:0];
|
|
assign rd_binary_next[FAD:0] = rd_binary_pointer[FAD:0] + {{(FAD){1'b0}},fifo_read};
|
|
|
|
assign fifo_empty = (rd_binary_next[FAD:0] == wr_binary_next[FAD:0]);
|
|
|
|
//########################################
|
|
//# Transaction assembly and distribution
|
|
//########################################
|
|
|
|
link_rxi_assembler link_rxi_assembler(/*AUTOINST*/
|
|
// Outputs
|
|
.rxi_assembled_tran (rxi_assembled_tran[14*LW-1:0]),
|
|
.rxi_c0_access (rxi_c0_access),
|
|
.rxi_c1_access (rxi_c1_access),
|
|
.rxi_c2_access (rxi_c2_access),
|
|
.rxi_c3_access (rxi_c3_access),
|
|
// Inputs
|
|
.reset (reset),
|
|
.rxi_lclk (rxi_lclk),
|
|
.vertical_k (vertical_k),
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.fifo_data_reg (fifo_data_reg[2*LW-1:0]),
|
|
.fifo_data_val (fifo_data_val),
|
|
.start_tran (start_tran),
|
|
.cfg_extcomp_dis (cfg_extcomp_dis));
|
|
|
|
|
|
endmodule // link_rxi_buffer
|
|
module link_rxi_channel (/*AUTOARG*/
|
|
// Outputs
|
|
fifo_full_rlc, rdmesh_tran_out, rdmesh_frame_out,
|
|
// Inputs
|
|
reset, cclk, cclk_en, rxi_lclk, cfg_extcomp_dis,
|
|
rxi_assembled_tran_rlc, fifo_access_rlc, rdmesh_wait_in
|
|
);
|
|
|
|
parameter LW = `CFG_LW;//lvds tranceiver pairs per side
|
|
|
|
//#########
|
|
//# INPUTS
|
|
//#########
|
|
|
|
input reset; //reset input
|
|
input cclk; //core clock
|
|
input cclk_en; // clock enable
|
|
input rxi_lclk;//receiver link clock
|
|
input cfg_extcomp_dis;// Disable external coordinates comparison
|
|
// Every input transaction is received by the chip
|
|
|
|
input [14*LW-1:0] rxi_assembled_tran_rlc; // assembled data from the main fifo
|
|
input fifo_access_rlc; // fifo is accessed
|
|
|
|
input rdmesh_wait_in; //wait indication from rdmesh
|
|
|
|
//##########
|
|
//# OUTPUTS
|
|
//##########
|
|
output fifo_full_rlc;//fifo full push back indicator
|
|
|
|
//# transaction to rdmesh
|
|
output [2*LW-1:0] rdmesh_tran_out; // transaction data
|
|
output rdmesh_frame_out; // core frame
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
|
|
|
|
endmodule // link_rxi_channel
|
|
module link_rxi_ctrl(/*AUTOARG*/
|
|
// Outputs
|
|
lclk,
|
|
// Inputs
|
|
io_lclk, rxi_cfg_reg
|
|
);
|
|
|
|
parameter DW = `CFG_DW;
|
|
|
|
|
|
//Input clock
|
|
input io_lclk; //link clock from IO
|
|
input [DW-1:0] rxi_cfg_reg;//used to deskew clock input
|
|
|
|
//Should we have a monitor pin for locking the timing?
|
|
|
|
|
|
//Delay Control word
|
|
//1 for rise
|
|
//1 for fall
|
|
|
|
///Output clocks to reciever block
|
|
|
|
output lclk; //buffered clock without delay
|
|
|
|
|
|
|
|
//Need to insert delay elements here
|
|
//How to insert delay with cts?
|
|
|
|
assign lclk = io_lclk;
|
|
|
|
|
|
|
|
endmodule // link_clock
|
|
|
|
|
|
//#############################################
|
|
//# This block is a "common" channel for both
|
|
//# mesh (multicast) and emesh transactions
|
|
//#############################################
|
|
module link_rxi_double_channel (/*AUTOARG*/
|
|
// Outputs
|
|
fifo_full_rlc, emesh_tran_out, emesh_frame_out, mesh_access_out,
|
|
mesh_write_out, mesh_dstaddr_out, mesh_srcaddr_out, mesh_data_out,
|
|
mesh_datamode_out, mesh_ctrlmode_out,
|
|
// Inputs
|
|
reset, cclk, cclk_en, ext_yid_k, ext_xid_k, rxi_lclk, who_am_i,
|
|
cfg_extcomp_dis, rxi_assembled_tran_rlc, fifo_access_rlc,
|
|
emesh_wait_in, mesh_wait_in
|
|
);
|
|
|
|
parameter LW = `CFG_LW;//lvds tranceiver pairs per side
|
|
parameter DW = `CFG_DW;//data width
|
|
parameter AW = `CFG_AW;//address width
|
|
|
|
//#########
|
|
//# INPUTS
|
|
//#########
|
|
|
|
input reset; //reset input
|
|
input cclk; //core clock
|
|
input cclk_en; // clock enable
|
|
input [3:0] ext_yid_k;//external y-id
|
|
input [3:0] ext_xid_k;//external x-id
|
|
input rxi_lclk;//receiver link clock
|
|
input [3:0] who_am_i;// specifies what link is that (north,east,south,west)
|
|
input cfg_extcomp_dis;// Disable external coordinates comparison
|
|
// Every input transaction is received by the chip
|
|
|
|
input [14*LW-1:0] rxi_assembled_tran_rlc; // assembled data from the main fifo
|
|
input fifo_access_rlc; // fifo is accessed
|
|
|
|
input emesh_wait_in; //wait indication from emesh
|
|
input mesh_wait_in; //wait indication from mesh
|
|
|
|
//##########
|
|
//# OUTPUTS
|
|
//##########
|
|
output fifo_full_rlc;//fifo full push back indicator
|
|
|
|
//# transaction to the emesh (transactions coming out off the chip)
|
|
output [2*LW-1:0] emesh_tran_out; // transaction data
|
|
output emesh_frame_out; // core frame
|
|
|
|
//# transaction to the mesh
|
|
output mesh_access_out; // access control to the mesh
|
|
output mesh_write_out; // write control to the mesh
|
|
output [AW-1:0] mesh_dstaddr_out; // destination address to the mesh
|
|
output [AW-1:0] mesh_srcaddr_out; // source address to the mesh
|
|
output [DW-1:0] mesh_data_out; // data to the mesh
|
|
output [1:0] mesh_datamode_out;// data mode to the mesh
|
|
output [3:0] mesh_ctrlmode_out;// ctrl mode to the mesh
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
|
wire access; // From link_rxi_mesh_launcher of link_rxi_mesh_launcher.v
|
|
wire [3:0] ctrlmode; // From link_rxi_mesh_launcher of link_rxi_mesh_launcher.v
|
|
wire [DW-1:0] data; // From link_rxi_mesh_launcher of link_rxi_mesh_launcher.v
|
|
wire [1:0] datamode; // From link_rxi_mesh_launcher of link_rxi_mesh_launcher.v
|
|
wire [AW-1:0] dstaddr; // From link_rxi_mesh_launcher of link_rxi_mesh_launcher.v
|
|
wire emesh_tran_dis; // From link_rxi_mesh_launcher of link_rxi_mesh_launcher.v
|
|
wire fifo_empty; // From link_rxi_fifo of link_rxi_fifo.v
|
|
wire [14*LW-1:0] fifo_tran_out; // From link_rxi_fifo of link_rxi_fifo.v
|
|
wire mesh_fifo_read; // From link_rxi_mesh_launcher of link_rxi_mesh_launcher.v
|
|
wire [AW-1:0] srcaddr; // From link_rxi_mesh_launcher of link_rxi_mesh_launcher.v
|
|
wire write; // From link_rxi_mesh_launcher of link_rxi_mesh_launcher.v
|
|
// End of automatics
|
|
|
|
// #########
|
|
// # WIRES
|
|
// #########
|
|
wire fifo_read;
|
|
wire emesh_fifo_empty;
|
|
|
|
//#########
|
|
//# FIFO
|
|
//#########
|
|
assign fifo_read = mesh_fifo_read;
|
|
|
|
link_rxi_fifo link_rxi_fifo (/*AUTOINST*/
|
|
// Outputs
|
|
.fifo_full_rlc (fifo_full_rlc),
|
|
.fifo_tran_out (fifo_tran_out[14*LW-1:0]),
|
|
.fifo_empty (fifo_empty),
|
|
// Inputs
|
|
.reset (reset),
|
|
.cclk (cclk),
|
|
.cclk_en (cclk_en),
|
|
.rxi_lclk (rxi_lclk),
|
|
.rxi_assembled_tran_rlc(rxi_assembled_tran_rlc[14*LW-1:0]),
|
|
.fifo_access_rlc(fifo_access_rlc),
|
|
.fifo_read (fifo_read));
|
|
|
|
|
|
//###################################
|
|
//# Transaction Launcher to Mesh
|
|
//###################################
|
|
|
|
link_rxi_mesh_launcher link_rxi_mesh_launcher(/*AUTOINST*/
|
|
// Outputs
|
|
.mesh_fifo_read (mesh_fifo_read),
|
|
.emesh_tran_dis (emesh_tran_dis),
|
|
.access (access),
|
|
.write (write),
|
|
.datamode (datamode[1:0]),
|
|
.ctrlmode (ctrlmode[3:0]),
|
|
.data (data[DW-1:0]),
|
|
.dstaddr (dstaddr[AW-1:0]),
|
|
.srcaddr (srcaddr[AW-1:0]),
|
|
// Inputs
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.who_am_i (who_am_i[3:0]),
|
|
.cfg_extcomp_dis (cfg_extcomp_dis),
|
|
.fifo_tran_out (fifo_tran_out[14*LW-1:0]),
|
|
.fifo_empty (fifo_empty),
|
|
.mesh_wait_in (mesh_wait_in));
|
|
|
|
|
|
|
|
//##################################
|
|
//# Interface with mesh
|
|
//# on output transactions only
|
|
//# * input from the mesh is driven
|
|
//# by a diferent block
|
|
//##################################
|
|
|
|
/* e16_mesh_interface AUTO_TEMPLATE (
|
|
.clk (cclk),
|
|
.clk_en (cclk_en),
|
|
.access_in (1'b0),
|
|
.write_in (1'b0),
|
|
.datamode_in (2'b00),
|
|
.ctrlmode_in (4'b0000),
|
|
.data_in ({(DW){1'b0}}),
|
|
.dstaddr_in ({(AW){1'b0}}),
|
|
.srcaddr_in ({(AW){1'b0}}),
|
|
.wait_int (1'b0),
|
|
.emesh_core_wait (1'b0),
|
|
.emesh_core_clk_en ({(11){1'b1}}),
|
|
.emesh_tran_sel (1'b0),
|
|
.wait_in (mesh_wait_in),
|
|
.\(.*\)_reg (),
|
|
.wait_out (),
|
|
.\(.*\)_out (mesh_\1_out[]),
|
|
);
|
|
*/
|
|
e16_mesh_interface mesh_interface(/*AUTOINST*/
|
|
// Outputs
|
|
.wait_out (), // Templated
|
|
.access_out (mesh_access_out), // Templated
|
|
.write_out (mesh_write_out), // Templated
|
|
.datamode_out (mesh_datamode_out[1:0]), // Templated
|
|
.ctrlmode_out (mesh_ctrlmode_out[3:0]), // Templated
|
|
.data_out (mesh_data_out[DW-1:0]), // Templated
|
|
.dstaddr_out (mesh_dstaddr_out[AW-1:0]), // Templated
|
|
.srcaddr_out (mesh_srcaddr_out[AW-1:0]), // Templated
|
|
.access_reg (), // Templated
|
|
.write_reg (), // Templated
|
|
.datamode_reg (), // Templated
|
|
.ctrlmode_reg (), // Templated
|
|
.data_reg (), // Templated
|
|
.dstaddr_reg (), // Templated
|
|
.srcaddr_reg (), // Templated
|
|
// Inputs
|
|
.clk (cclk), // Templated
|
|
.clk_en (cclk_en), // Templated
|
|
.reset (reset),
|
|
.wait_in (mesh_wait_in), // Templated
|
|
.access_in (1'b0), // Templated
|
|
.write_in (1'b0), // Templated
|
|
.datamode_in (2'b00), // Templated
|
|
.ctrlmode_in (4'b0000), // Templated
|
|
.data_in ({(DW){1'b0}}), // Templated
|
|
.dstaddr_in ({(AW){1'b0}}), // Templated
|
|
.srcaddr_in ({(AW){1'b0}}), // Templated
|
|
.wait_int (1'b0), // Templated
|
|
.access (access),
|
|
.write (write),
|
|
.datamode (datamode[1:0]),
|
|
.ctrlmode (ctrlmode[3:0]),
|
|
.data (data[DW-1:0]),
|
|
.dstaddr (dstaddr[AW-1:0]),
|
|
.srcaddr (srcaddr[AW-1:0]));
|
|
|
|
|
|
endmodule // link_rxi_double_channel
|
|
|
|
//##############################################################################
|
|
//#
|
|
//# This is a FOUR entries (FAD=2) receiver FIFO with the main function of
|
|
//# synchronization between RXI link clock domain and core clock domain
|
|
//# It seems that for the FIFO to function without "build in" push back
|
|
//# we will need at least THREE entries, so choosing FOUR entries puts us
|
|
//# in a safer position.
|
|
//#
|
|
//# * This FIFO will function even with a single entry (with some modifications)
|
|
//# but if the number of entries is not sufficient for the synchronization
|
|
//# the "build in" push back will be driven on every new write control.
|
|
//#
|
|
//################################################################################
|
|
|
|
module link_rxi_fifo (/*AUTOARG*/
|
|
// Outputs
|
|
fifo_full_rlc, fifo_tran_out, fifo_empty,
|
|
// Inputs
|
|
reset, cclk, cclk_en, rxi_lclk, rxi_assembled_tran_rlc,
|
|
fifo_access_rlc, fifo_read
|
|
);
|
|
|
|
parameter LW = `CFG_LW;//lvds tranceiver pairs per side
|
|
parameter FAD = 2; // Number of bits to access all the entries
|
|
localparam MD = 1<<FAD;
|
|
|
|
//#########
|
|
//# INPUTS
|
|
//#########
|
|
|
|
input reset; //reset input
|
|
input cclk; //core clock
|
|
input cclk_en; // clock enable
|
|
input rxi_lclk;//receiver link clock
|
|
|
|
input [14*LW-1:0] rxi_assembled_tran_rlc; // assembled data from the main fifo
|
|
input fifo_access_rlc; // fifo is accessed
|
|
//# from the launcher
|
|
input fifo_read;
|
|
//##########
|
|
//# OUTPUTS
|
|
//##########
|
|
|
|
output fifo_full_rlc;//fifo full push back indicator
|
|
//# to the launcher
|
|
output [14*LW-1:0] fifo_tran_out;
|
|
output fifo_empty;
|
|
|
|
//##########
|
|
//# REGS
|
|
//##########
|
|
|
|
reg [14*LW-1:0] fifo_mem[MD-1:0];
|
|
reg [FAD:0] wr_binary_pointer_rlc;
|
|
reg [FAD:0] wr_gray_pointer_rlc;
|
|
reg fifo_full_rlc;
|
|
|
|
reg [FAD:0] rd_binary_pointer;
|
|
reg [FAD:0] rd_gray_pointer;
|
|
reg fifo_empty;
|
|
|
|
//#########
|
|
//# WIRES
|
|
//#########
|
|
|
|
wire wr_write_rlc; // FIFO write control
|
|
wire [FAD-1:0] wr_addr_rlc;
|
|
wire [FAD:0] wr_binary_next_rlc;
|
|
wire [FAD:0] wr_gray_next_rlc;
|
|
wire fifo_full_next_rlc;
|
|
wire [FAD:0] rd_gray_pointer_rlc;
|
|
|
|
wire [FAD-1:0] rd_addr;
|
|
wire [FAD:0] rd_binary_next;
|
|
wire [FAD:0] rd_gray_next;
|
|
wire fifo_empty_next;
|
|
wire [FAD:0] wr_gray_pointer;
|
|
|
|
/*AUTOWIRE*/
|
|
/*AUTOINPUT*/
|
|
|
|
//##################################################################
|
|
//# Write control generation:
|
|
//#
|
|
//# FIFO is being written according to the state of fifo_access_rlc
|
|
//# control driven by main fifo and independent on the current
|
|
//# state of the FIFO.
|
|
//# We do mask this control with fifo full signal but this mask
|
|
//# is really redundant.
|
|
//# The reason for that is the following:
|
|
//# The FASTEST THROUGHPUT the transaction can be dispatched from
|
|
//# the main fifo here is ONE TRANSACTION IN EVERY FOUR CYCLES.
|
|
//# FIFO full indication is sent back on the first cycle after
|
|
//# receiving the transaction causing the fifo to be full.
|
|
//# This indication is sampled two more times in the main fifo
|
|
//# and then prevents new transaction to be dispatched.
|
|
//# So it takes THREE CYCLES to stop new transaction versus
|
|
//# FOUR CYCLES to dispatch new one and therefore we are save.
|
|
//####################################################################
|
|
|
|
assign wr_write_rlc = fifo_access_rlc & ~fifo_full_rlc;
|
|
|
|
//#################################
|
|
//# FIFO data
|
|
//#################################
|
|
|
|
//# Write
|
|
always @ (posedge rxi_lclk)
|
|
if (wr_write_rlc)
|
|
fifo_mem[wr_addr_rlc[FAD-1:0]] <= rxi_assembled_tran_rlc[14*LW-1:0];
|
|
|
|
//# Read (for dispatch)
|
|
assign fifo_tran_out[14*LW-1:0] = fifo_mem[rd_addr[FAD-1:0]];
|
|
|
|
//#####################################
|
|
//# FIFO Write State Machine
|
|
//#####################################
|
|
|
|
//# While for the actual address calculation we use [FAD-1:0] bits only,
|
|
//# the bit FAD of the counter is needed in order to distinguish
|
|
//# between the fifo entry currently being written and the one
|
|
//# written in the previous "round" (FAD is a carry-out bit and is
|
|
//# switched every "round")
|
|
always @(posedge rxi_lclk or posedge reset)
|
|
if(reset)
|
|
begin
|
|
wr_binary_pointer_rlc[FAD:0] <= {(FAD+1){1'b0}};
|
|
wr_gray_pointer_rlc[FAD:0] <= {(FAD+1){1'b0}};
|
|
end
|
|
else if(wr_write_rlc)
|
|
begin
|
|
wr_binary_pointer_rlc[FAD:0] <= wr_binary_next_rlc[FAD:0];
|
|
wr_gray_pointer_rlc[FAD:0] <= wr_gray_next_rlc[FAD:0];
|
|
end
|
|
|
|
assign wr_addr_rlc[FAD-1:0] = wr_binary_pointer_rlc[FAD-1:0];
|
|
assign wr_binary_next_rlc[FAD:0] = wr_binary_pointer_rlc[FAD:0] +
|
|
{{(FAD){1'b0}},wr_write_rlc};
|
|
|
|
//# Gray Pointer Conversion (for more reliable synchronization)!
|
|
assign wr_gray_next_rlc[FAD:0] = {1'b0,wr_binary_next_rlc[FAD:1]} ^
|
|
wr_binary_next_rlc[FAD:0];
|
|
|
|
//# FIFO full indication
|
|
assign fifo_full_next_rlc =
|
|
(wr_gray_next_rlc[FAD-2:0] == rd_gray_pointer_rlc[FAD-2:0]) &
|
|
(wr_gray_next_rlc[FAD] ^ rd_gray_pointer_rlc[FAD]) &
|
|
(wr_gray_next_rlc[FAD-1] ^ rd_gray_pointer_rlc[FAD-1]);
|
|
|
|
always @ (posedge rxi_lclk or posedge reset)
|
|
if(reset)
|
|
fifo_full_rlc <= 1'b0;
|
|
else
|
|
fifo_full_rlc <= fifo_full_next_rlc;
|
|
|
|
//#############################
|
|
//# FIFO Read State Machine
|
|
//#############################
|
|
|
|
always @(posedge cclk or posedge reset)
|
|
if(reset)
|
|
begin
|
|
rd_binary_pointer[FAD:0] <= {(FAD+1){1'b0}};
|
|
rd_gray_pointer[FAD:0] <= {(FAD+1){1'b0}};
|
|
end
|
|
else if(cclk_en)
|
|
if(fifo_read)
|
|
begin
|
|
rd_binary_pointer[FAD:0] <= rd_binary_next[FAD:0];
|
|
rd_gray_pointer[FAD:0] <= rd_gray_next[FAD:0];
|
|
end
|
|
|
|
assign rd_addr[FAD-1:0] = rd_binary_pointer[FAD-1:0];
|
|
assign rd_binary_next[FAD:0] = rd_binary_pointer[FAD:0] + {{(FAD){1'b0}},fifo_read};
|
|
|
|
//# Gray Pointer Conversion (for more reliable synchronization)!
|
|
assign rd_gray_next[FAD:0] = {1'b0,rd_binary_next[FAD:1]} ^ rd_binary_next[FAD:0];
|
|
|
|
//# FIFO empty indication
|
|
assign fifo_empty_next = (rd_gray_next[FAD:0]==wr_gray_pointer[FAD:0]);
|
|
|
|
always @ (posedge cclk or posedge reset)
|
|
if(reset)
|
|
fifo_empty <= 1'b1;
|
|
else if(cclk_en)
|
|
fifo_empty <= fifo_empty_next;
|
|
|
|
//####################################################
|
|
//# Synchronization between rd/wr domains
|
|
//####################################################
|
|
|
|
e16_synchronizer #(.DW(FAD+1)) sync_rd2wr (.out (rd_gray_pointer_rlc[FAD:0]),
|
|
.in (rd_gray_pointer[FAD:0]),
|
|
.clk (rxi_lclk),
|
|
.reset (reset));
|
|
|
|
e16_synchronizer #(.DW(FAD+1)) sync_wr2rd (.out (wr_gray_pointer[FAD:0]),
|
|
.in (wr_gray_pointer_rlc[FAD:0]),
|
|
.clk (cclk),
|
|
.reset (reset));
|
|
|
|
|
|
|
|
endmodule // link_rxi_fifo
|
|
module link_rxi_launcher (/*AUTOARG*/
|
|
// Outputs
|
|
fifo_read, emesh_tran, emesh_frame,
|
|
// Inputs
|
|
reset, cclk, cclk_en, fifo_tran_out, fifo_empty, emesh_wait_in
|
|
);
|
|
|
|
parameter LW = `CFG_LW;//lvds tranceiver pairs per side
|
|
|
|
//#########
|
|
//# INPUTS
|
|
//#########
|
|
|
|
input reset; // reset input
|
|
input cclk; // core clock
|
|
input cclk_en; // clock enable
|
|
|
|
//# from the fifo
|
|
input [14*LW-1:0] fifo_tran_out; // transaction out of the fifo
|
|
input fifo_empty; // fifo is empty
|
|
//# from the emesh
|
|
input emesh_wait_in; // emesh wait indication
|
|
|
|
//##########
|
|
//# OUTPUTS
|
|
//##########
|
|
//# to the fifo
|
|
output fifo_read; // read next entry
|
|
//# to the emesh
|
|
output [2*LW-1:0] emesh_tran; // transaction data
|
|
output emesh_frame; // emesh frame
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
// #########
|
|
// # REGS
|
|
// #########
|
|
|
|
reg [2:0] launch_pointer;
|
|
|
|
// #########
|
|
// # WIRES
|
|
// #########
|
|
|
|
wire last_tran;
|
|
wire [2:0] launch_pointer_incr;
|
|
wire [6:0] launch_sel;
|
|
|
|
//################################
|
|
//# next transaction read control
|
|
//################################
|
|
|
|
assign fifo_read = last_tran & ~emesh_wait_in;
|
|
|
|
//############################################
|
|
//# transaction launcher state machine
|
|
//############################################
|
|
assign last_tran = (launch_pointer[2:0] == 3'b110);
|
|
|
|
assign launch_pointer_incr[2:0] = last_tran ? 3'b000 : (launch_pointer[2:0] + 3'b001);
|
|
|
|
always @ (posedge cclk or posedge reset)
|
|
if(reset)
|
|
launch_pointer[2:0] <= 3'b000;
|
|
else if(cclk_en)
|
|
if (~(fifo_empty | emesh_wait_in))
|
|
launch_pointer[2:0] <= launch_pointer_incr[2:0];
|
|
|
|
assign launch_sel[0] = (launch_pointer[2:0] == 3'b000);
|
|
assign launch_sel[1] = (launch_pointer[2:0] == 3'b001);
|
|
assign launch_sel[2] = (launch_pointer[2:0] == 3'b010);
|
|
assign launch_sel[3] = (launch_pointer[2:0] == 3'b011);
|
|
assign launch_sel[4] = (launch_pointer[2:0] == 3'b100);
|
|
assign launch_sel[5] = (launch_pointer[2:0] == 3'b101);
|
|
assign launch_sel[6] = (launch_pointer[2:0] == 3'b110);
|
|
|
|
//###########################
|
|
//# frame and data selection
|
|
//###########################
|
|
|
|
assign emesh_frame = ~(fifo_empty | last_tran);
|
|
|
|
e16_mux7 #(2*LW) mux7(// Outputs
|
|
.out (emesh_tran[2*LW-1:0]),
|
|
// Inputs
|
|
.in0 (fifo_tran_out[2*LW-1:0]), .sel0 (launch_sel[0]),
|
|
.in1 (fifo_tran_out[4*LW-1:2*LW]), .sel1 (launch_sel[1]),
|
|
.in2 (fifo_tran_out[6*LW-1:4*LW]), .sel2 (launch_sel[2]),
|
|
.in3 (fifo_tran_out[8*LW-1:6*LW]), .sel3 (launch_sel[3]),
|
|
.in4 (fifo_tran_out[10*LW-1:8*LW]), .sel4 (launch_sel[4]),
|
|
.in5 (fifo_tran_out[12*LW-1:10*LW]), .sel5 (launch_sel[5]),
|
|
.in6 (fifo_tran_out[14*LW-1:12*LW]), .sel6 (launch_sel[6]));
|
|
|
|
endmodule // link_rxi_launcher
|
|
module link_rxi_mesh_launcher (/*AUTOARG*/
|
|
// Outputs
|
|
mesh_fifo_read, emesh_tran_dis, access, write, datamode, ctrlmode,
|
|
data, dstaddr, srcaddr,
|
|
// Inputs
|
|
ext_yid_k, ext_xid_k, who_am_i, cfg_extcomp_dis, fifo_tran_out,
|
|
fifo_empty, mesh_wait_in
|
|
);
|
|
|
|
parameter AW = `CFG_AW ;//address width
|
|
parameter DW = `CFG_DW ;//data width
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
|
|
//#########
|
|
//# INPUTS
|
|
//#########
|
|
|
|
input [3:0] ext_yid_k;//external y-id
|
|
input [3:0] ext_xid_k;//external x-id
|
|
input [3:0] who_am_i;// specifies what link is that (north,east,south,west)
|
|
input cfg_extcomp_dis;// Disable external coordinates comparison
|
|
// Every input transaction is received by the chip
|
|
//# from the fifo
|
|
input [14*LW-1:0] fifo_tran_out; // transaction out of the fifo
|
|
input fifo_empty; // fifo is empty
|
|
//# from the mesh
|
|
input mesh_wait_in; // wait indication from mesh
|
|
|
|
//##########
|
|
//# OUTPUTS
|
|
//##########
|
|
//# to the fifo
|
|
output mesh_fifo_read; // read next entry
|
|
//# to prevent emesh launch
|
|
output emesh_tran_dis;
|
|
//# to the mesh
|
|
output access;
|
|
output write;
|
|
output [1:0] datamode;
|
|
output [3:0] ctrlmode;
|
|
output [DW-1:0] data;
|
|
output [AW-1:0] dstaddr;
|
|
output [AW-1:0] srcaddr;
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
// #########
|
|
// # WIRES
|
|
// #########
|
|
wire [AW-1:0] srcaddr_int;
|
|
wire [AW-1:0] srcaddr_multicast;
|
|
wire access_int;
|
|
wire multicast_match;
|
|
|
|
wire [1:0] srcaddr_int_ycoord;
|
|
wire [1:0] srcaddr_int_xcoord;
|
|
|
|
wire [1:0] north_srcaddr_int_ycoord;
|
|
wire [1:0] north_srcaddr_int_xcoord;
|
|
wire [1:0] east_srcaddr_int_ycoord;
|
|
wire [1:0] east_srcaddr_int_xcoord;
|
|
wire [1:0] south_srcaddr_int_ycoord;
|
|
wire [1:0] south_srcaddr_int_xcoord;
|
|
wire [1:0] west_srcaddr_int_ycoord;
|
|
wire [1:0] west_srcaddr_int_xcoord;
|
|
|
|
wire [3:0] dst_y_k;
|
|
wire [3:0] dst_x_k;
|
|
wire west_east_corner_tran;
|
|
wire north_south_corner_tran;
|
|
wire [3:0] corner_tran;
|
|
wire corner_tran_match;
|
|
wire mesh_tran_match;
|
|
|
|
//# If valid mesh transaction is detected we should prevent the launch
|
|
//# of this transaction on the emesh
|
|
assign emesh_tran_dis = access;
|
|
|
|
//# Valid mesh (multicast or not) transaction
|
|
assign access = ~fifo_empty & access_int &
|
|
(corner_tran_match | multicast_match | mesh_tran_match);
|
|
|
|
//# Read next entry
|
|
assign mesh_fifo_read = access & ~mesh_wait_in;
|
|
|
|
//# Mesh transaction fields extraction
|
|
assign ctrlmode[3:0] = fifo_tran_out[2*LW-1:2*LW-4];
|
|
|
|
assign dstaddr[AW-1:0] = {fifo_tran_out[2*LW-5:0],
|
|
fifo_tran_out[4*LW-1:2*LW],
|
|
fifo_tran_out[6*LW-1:6*LW-4]};
|
|
|
|
assign datamode[1:0] = fifo_tran_out[6*LW-5:6*LW-6];
|
|
assign write = fifo_tran_out[6*LW-7];
|
|
assign access_int = fifo_tran_out[5*LW];
|
|
|
|
assign data[DW-1:0] = {fifo_tran_out[5*LW-1:4*LW],
|
|
fifo_tran_out[8*LW-1:6*LW],
|
|
fifo_tran_out[10*LW-1:9*LW]};
|
|
|
|
assign srcaddr_int[AW-1:0] = {fifo_tran_out[9*LW-1:8*LW],
|
|
fifo_tran_out[12*LW-1:10*LW],
|
|
fifo_tran_out[14*LW-1:13*LW]};
|
|
|
|
//# Multicast transaction (there is no multicast transaction when no external compare)
|
|
assign multicast_match = write & ~cfg_extcomp_dis &
|
|
(ctrlmode[1:0]==2'b11) & ~(datamode[1:0] == 2'b11);
|
|
|
|
//# We rewrite the internal coordinates of every multicast transaction
|
|
//# in the way it will propagate through all the scores in the system
|
|
//# The new internal coordinates will be those of the attached to the
|
|
//# current link score and are constant and different for every link
|
|
//# !!! Since the transaction will propagate in all directions out of the
|
|
//# !!! attached score, it will try to get out of the chip on the same
|
|
//# !!! link, but it won't happen due to the external coordinate comparison
|
|
//# !!! of the link transmitter.
|
|
|
|
assign north_srcaddr_int_ycoord[1:0] = 2'b00;
|
|
assign east_srcaddr_int_ycoord[1:0] = 2'b00;
|
|
assign south_srcaddr_int_ycoord[1:0] = 2'b11;
|
|
assign west_srcaddr_int_ycoord[1:0] = 2'b00;
|
|
|
|
assign north_srcaddr_int_xcoord[1:0] = 2'b00;
|
|
assign east_srcaddr_int_xcoord[1:0] = 2'b11;
|
|
assign south_srcaddr_int_xcoord[1:0] = 2'b00;
|
|
assign west_srcaddr_int_xcoord[1:0] = 2'b00;
|
|
|
|
assign srcaddr_int_ycoord[1:0] = {(2){who_am_i[3]}} & north_srcaddr_int_ycoord[1:0]|
|
|
{(2){who_am_i[2]}} & east_srcaddr_int_ycoord[1:0] |
|
|
{(2){who_am_i[1]}} & south_srcaddr_int_ycoord[1:0]|
|
|
{(2){who_am_i[0]}} & west_srcaddr_int_ycoord[1:0];
|
|
|
|
assign srcaddr_int_xcoord[1:0] = {(2){who_am_i[3]}} & north_srcaddr_int_xcoord[1:0]|
|
|
{(2){who_am_i[2]}} & east_srcaddr_int_xcoord[1:0] |
|
|
{(2){who_am_i[1]}} & south_srcaddr_int_xcoord[1:0]|
|
|
{(2){who_am_i[0]}} & west_srcaddr_int_xcoord[1:0];
|
|
|
|
//# Modified source address
|
|
//assign srcaddr_multicast[AW-1:0] = {srcaddr_int[31:26],1'b0,srcaddr_int_ycoord[1:0],
|
|
// 1'b0,srcaddr_int_xcoord[1:0],
|
|
// srcaddr_int[19:0]};
|
|
|
|
assign srcaddr_multicast[AW-1:0] = {srcaddr_int[31:28],srcaddr_int_ycoord[1:0],
|
|
srcaddr_int[25:22],srcaddr_int_xcoord[1:0],
|
|
srcaddr_int[19:0]};
|
|
|
|
assign srcaddr[AW-1:0] = multicast_match ? srcaddr_multicast[AW-1:0] :
|
|
srcaddr_int[AW-1:0];
|
|
|
|
//# Mesh transaction for external corners detection
|
|
// assign dst_y_k[2:0] = dstaddr[31:29];
|
|
// assign dst_x_k[2:0] = dstaddr[28:26];
|
|
assign dst_y_k[3:0] = dstaddr[31:28];
|
|
assign dst_x_k[3:0] = dstaddr[25:22];
|
|
|
|
assign west_east_corner_tran = ((dst_x_k[3:0] == ext_xid_k[3:0]) &
|
|
~(dst_y_k[3:0] == ext_yid_k[3:0]));
|
|
|
|
assign north_south_corner_tran = (~(dst_x_k[3:0] == ext_xid_k[3:0]) &
|
|
(dst_y_k[3:0] == ext_yid_k[3:0]));
|
|
|
|
assign corner_tran[3:0] = {north_south_corner_tran, west_east_corner_tran,
|
|
north_south_corner_tran, west_east_corner_tran};
|
|
|
|
assign corner_tran_match = ~cfg_extcomp_dis & (|(corner_tran[3:0] & who_am_i[3:0]));
|
|
//# Regular Mesh transaction
|
|
assign mesh_tran_match = cfg_extcomp_dis |
|
|
(~multicast_match & ((dst_x_k[3:0] == ext_xid_k[3:0]) &
|
|
(dst_y_k[3:0] == ext_yid_k[3:0])));
|
|
|
|
endmodule // link_rxi_mesh_launcher
|
|
//#############################################################
|
|
//# This block is a receiver of the read transactions only
|
|
//# Read transactions will enter the chip on rdmesh only
|
|
//#############################################################
|
|
module link_rxi_rd (/*AUTOARG*/
|
|
// Outputs
|
|
rxi_rd_wait, c0_rdmesh_frame_out, c0_rdmesh_tran_out,
|
|
c1_rdmesh_frame_out, c1_rdmesh_tran_out, c2_rdmesh_frame_out,
|
|
c2_rdmesh_tran_out, c3_rdmesh_frame_out, c3_rdmesh_tran_out,
|
|
// Inputs
|
|
reset, ext_yid_k, ext_xid_k, vertical_k, who_am_i, cfg_extcomp_dis,
|
|
rxi_data, rxi_lclk, rxi_frame, c0_clk_in, c1_clk_in, c2_clk_in,
|
|
c3_clk_in, c0_rdmesh_wait_in, c1_rdmesh_wait_in, c2_rdmesh_wait_in,
|
|
c3_rdmesh_wait_in, c0_fifo_full_rlc, c1_fifo_full_rlc,
|
|
c2_fifo_full_rlc, c3_fifo_full_rlc
|
|
);
|
|
|
|
parameter LW = `CFG_LW;//lvds tranceiver pairs per side
|
|
|
|
// #########
|
|
// # Inputs
|
|
// #########
|
|
|
|
input reset; // reset input
|
|
input [3:0] ext_yid_k; // external y-id
|
|
input [3:0] ext_xid_k; // external x-id
|
|
input vertical_k;// specifies if block is vertical or horizontal
|
|
input [3:0] who_am_i; // specifies what link is that (north,east,south,west)
|
|
input cfg_extcomp_dis;// Disable external coordinates comparison
|
|
// Every input transaction is received by the chip
|
|
|
|
input [LW-1:0] rxi_data; // Byte word
|
|
input rxi_lclk; // receive clock (adjusted to the frame/data)
|
|
input rxi_frame; // indicates new transmission
|
|
|
|
// # Sync clocks
|
|
input c0_clk_in; // clock of the core
|
|
input c1_clk_in; // clock of the core
|
|
input c2_clk_in; // clock of the core
|
|
input c3_clk_in; // clock of the core
|
|
|
|
// # Wait indicators
|
|
input c0_rdmesh_wait_in; // wait
|
|
input c1_rdmesh_wait_in; // wait
|
|
input c2_rdmesh_wait_in; // wait
|
|
input c3_rdmesh_wait_in; // wait
|
|
|
|
// ##########
|
|
// # Outputs
|
|
// ##########
|
|
|
|
output rxi_rd_wait; //wait indicator for read transactions
|
|
|
|
// # RDMESH (any read transaction)
|
|
output c0_rdmesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c0_rdmesh_tran_out; // serialized transaction
|
|
output c1_rdmesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c1_rdmesh_tran_out; // serialized transaction
|
|
output c2_rdmesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c2_rdmesh_tran_out; // serialized transaction
|
|
output c3_rdmesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c3_rdmesh_tran_out; // serialized transaction
|
|
|
|
/*AUTOINPUT*/
|
|
// Beginning of automatic inputs (from unused autoinst inputs)
|
|
input c0_fifo_full_rlc; // To link_rxi_buffer of link_rxi_buffer.v
|
|
input c1_fifo_full_rlc; // To link_rxi_buffer of link_rxi_buffer.v
|
|
input c2_fifo_full_rlc; // To link_rxi_buffer of link_rxi_buffer.v
|
|
input c3_fifo_full_rlc; // To link_rxi_buffer of link_rxi_buffer.v
|
|
// End of automatics
|
|
/*AUTOWIRE*/
|
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
|
wire c0_fifo_access_rlc; // From link_rxi_buffer of link_rxi_buffer.v
|
|
wire c1_fifo_access_rlc; // From link_rxi_buffer of link_rxi_buffer.v
|
|
wire c2_fifo_access_rlc; // From link_rxi_buffer of link_rxi_buffer.v
|
|
wire c3_fifo_access_rlc; // From link_rxi_buffer of link_rxi_buffer.v
|
|
wire [14*LW-1:0] rxi_assembled_tran_rlc; // From link_rxi_buffer of link_rxi_buffer.v
|
|
// End of automatics
|
|
|
|
// ################################
|
|
// # Receiver buffer instantiation
|
|
// ################################
|
|
|
|
/*link_rxi_buffer AUTO_TEMPLATE (.rxi_rd (1'b1),
|
|
.rxi_wait (rxi_rd_wait),
|
|
.reset (reset),
|
|
.vertical_k (vertical_k),
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.rxi_data (rxi_data[LW-1:0]),
|
|
.rxi_lclk (rxi_lclk),
|
|
.rxi_frame (rxi_frame),
|
|
.rxi_\(.*\)_access (\1_fifo_access_rlc),
|
|
.\(.*\) (\1_rlc[]),
|
|
.cfg_extcomp_dis (cfg_extcomp_dis),
|
|
);
|
|
*/
|
|
link_rxi_buffer link_rxi_buffer(/*AUTOINST*/
|
|
// Outputs
|
|
.rxi_wait (rxi_rd_wait), // Templated
|
|
.rxi_assembled_tran (rxi_assembled_tran_rlc[14*LW-1:0]), // Templated
|
|
.rxi_c0_access (c0_fifo_access_rlc), // Templated
|
|
.rxi_c1_access (c1_fifo_access_rlc), // Templated
|
|
.rxi_c2_access (c2_fifo_access_rlc), // Templated
|
|
.rxi_c3_access (c3_fifo_access_rlc), // Templated
|
|
// Inputs
|
|
.reset (reset), // Templated
|
|
.vertical_k (vertical_k), // Templated
|
|
.ext_yid_k (ext_yid_k[3:0]), // Templated
|
|
.ext_xid_k (ext_xid_k[3:0]), // Templated
|
|
.rxi_data (rxi_data[LW-1:0]), // Templated
|
|
.rxi_lclk (rxi_lclk), // Templated
|
|
.rxi_frame (rxi_frame), // Templated
|
|
.rxi_rd (1'b1), // Templated
|
|
.cfg_extcomp_dis (cfg_extcomp_dis), // Templated
|
|
.c0_fifo_full (c0_fifo_full_rlc), // Templated
|
|
.c1_fifo_full (c1_fifo_full_rlc), // Templated
|
|
.c2_fifo_full (c2_fifo_full_rlc), // Templated
|
|
.c3_fifo_full (c3_fifo_full_rlc)); // Templated
|
|
|
|
|
|
endmodule // link_rxi_rd
|
|
module link_rxi_router (/*AUTOARG*/
|
|
// Outputs
|
|
fifo_read_cvre, read_out, write_out, dst_addr_out, src_addr_out,
|
|
data_out, datamode_out, ctrlmode_out,
|
|
// Inputs
|
|
fifo_data_out_cvre, fifo_empty_cvre, wait_in
|
|
);
|
|
|
|
parameter AW = 32;
|
|
parameter MDW = 32;
|
|
parameter FW = 112;
|
|
parameter XW = 6;
|
|
parameter YW = 6;
|
|
parameter ZW = 6;
|
|
parameter IAW = 20;//internal address width=20 bits=1MB
|
|
|
|
/********************************************/
|
|
/*FIFO Interface */
|
|
/********************************************/
|
|
input [FW-1:0] fifo_data_out_cvre;
|
|
input fifo_empty_cvre;
|
|
output fifo_read_cvre; //depends on empty and grants
|
|
|
|
/********************************************/
|
|
/*Transaction */
|
|
/********************************************/
|
|
//Mesh wait indicators
|
|
input wait_in;
|
|
output read_out;
|
|
output write_out;
|
|
output [AW-1:0] dst_addr_out;
|
|
output [AW-1:0] src_addr_out;
|
|
output [MDW-1:0] data_out;
|
|
output [1:0] datamode_out;
|
|
output [3:0] ctrlmode_out;
|
|
|
|
|
|
|
|
/********************************************/
|
|
/*Wires */
|
|
/********************************************/
|
|
wire mesh_write_cvre;
|
|
wire mesh_read_cvre;
|
|
wire [1:0] mesh_datamode_cvre;
|
|
wire [3:0] mesh_ctrlmode_cvre;
|
|
wire [7:0] mesh_reserved_cvre;
|
|
wire [MDW-1:0] mesh_data_cvre;
|
|
wire [AW-1:0] mesh_src_addr_cvre;
|
|
wire [AW-1:0] mesh_dst_addr_cvre;
|
|
wire [1:0] compare_addr;
|
|
|
|
wire request_cvre;
|
|
|
|
/********************************************/
|
|
/*Splitting Vector Into Components */
|
|
/********************************************/
|
|
assign mesh_write_cvre = fifo_data_out_cvre[0];
|
|
assign mesh_read_cvre = fifo_data_out_cvre[1];
|
|
assign mesh_datamode_cvre[1:0] = fifo_data_out_cvre[3:2];
|
|
assign mesh_ctrlmode_cvre[3:0] = fifo_data_out_cvre[7:4];
|
|
assign mesh_reserved_cvre[7:0] = fifo_data_out_cvre[15:8];
|
|
assign mesh_data_cvre[MDW-1:0] = fifo_data_out_cvre[47:16];
|
|
assign mesh_dst_addr_cvre[AW-1:0]= fifo_data_out_cvre[79:48];
|
|
assign mesh_src_addr_cvre[AW-1:0]= fifo_data_out_cvre[111:80];
|
|
|
|
|
|
/********************************************/
|
|
/*Address Decoding */
|
|
/********************************************/
|
|
|
|
/********************************************/
|
|
/*Address Decoding */
|
|
/********************************************/
|
|
//Requests
|
|
//How to
|
|
assign request_cvre = ~fifo_empty_cvre;
|
|
|
|
/********************************************/
|
|
/*Only Doing FIFO read when granted */
|
|
/********************************************/
|
|
assign fifo_read_cvre = (request_cvre & ~wait_in);
|
|
|
|
|
|
/********************************************/
|
|
/*DISTRIBUTING TO ALL AGENTS */
|
|
/********************************************/
|
|
//turn on directions with read/write
|
|
|
|
//READ
|
|
assign read_out = request_cvre & mesh_read_cvre;
|
|
|
|
//WRITE
|
|
assign write_out = request_cvre & mesh_write_cvre;
|
|
|
|
//Mesh transaction
|
|
assign dst_addr_out[AW-1:0] = mesh_dst_addr_cvre[AW-1:0];
|
|
assign src_addr_out[AW-1:0] = mesh_src_addr_cvre[AW-1:0];
|
|
assign data_out[MDW-1:0] = mesh_data_cvre[MDW-1:0];
|
|
assign datamode_out[1:0] = mesh_datamode_cvre[1:0];
|
|
assign ctrlmode_out[3:0] = mesh_ctrlmode_cvre[3:0];
|
|
|
|
|
|
endmodule // link_rxi_router
|
|
|
|
//#############################################################
|
|
//# This block is a receiver of the write transactions only
|
|
//# Write transactions will enter the chip on emesh and mesh
|
|
//# only but not on the rdmesh
|
|
//#############################################################
|
|
module link_rxi_wr(/*AUTOARG*/
|
|
// Outputs
|
|
rxi_wr_wait, c0_emesh_frame_out, c0_emesh_tran_out,
|
|
c3_emesh_frame_out, c3_emesh_tran_out, c0_mesh_access_out,
|
|
c0_mesh_write_out, c0_mesh_dstaddr_out, c0_mesh_srcaddr_out,
|
|
c0_mesh_data_out, c0_mesh_datamode_out, c0_mesh_ctrlmode_out,
|
|
c3_mesh_access_out, c3_mesh_write_out, c3_mesh_dstaddr_out,
|
|
c3_mesh_srcaddr_out, c3_mesh_data_out, c3_mesh_datamode_out,
|
|
c3_mesh_ctrlmode_out,
|
|
// Inputs
|
|
reset, ext_yid_k, ext_xid_k, vertical_k, who_am_i, cfg_extcomp_dis,
|
|
rxi_data, rxi_lclk, rxi_frame, c0_clk_in, c3_clk_in,
|
|
c0_emesh_wait_in, c3_emesh_wait_in, c0_mesh_wait_in,
|
|
c3_mesh_wait_in
|
|
);
|
|
|
|
parameter LW = `CFG_LW;//lvds tranceiver pairs per side
|
|
parameter DW = `CFG_DW;//data width
|
|
parameter AW = `CFG_AW;//address width
|
|
|
|
// #########
|
|
// # Inputs
|
|
// #########
|
|
|
|
input reset; // reset input
|
|
input [3:0] ext_yid_k; // external y-id
|
|
input [3:0] ext_xid_k; // external x-id
|
|
input vertical_k;// specifies if block is vertical or horizontal
|
|
input [3:0] who_am_i; // specifies what link is that (north,east,south,west)
|
|
input cfg_extcomp_dis;// Disable external coordinates comparison
|
|
// Every input transaction is received by the chip
|
|
input [LW-1:0] rxi_data; // Byte word
|
|
input rxi_lclk; // receive clock (adjusted to the frame/data)
|
|
input rxi_frame; // indicates new transmission
|
|
|
|
// # Sync clocks
|
|
input c0_clk_in; // clock of the core
|
|
input c3_clk_in; // clock of the core
|
|
|
|
// # Wait indicators
|
|
input c0_emesh_wait_in; // wait
|
|
input c3_emesh_wait_in; // wait
|
|
input c0_mesh_wait_in; // wait
|
|
input c3_mesh_wait_in; // wait
|
|
|
|
// ##########
|
|
// # Outputs
|
|
// ##########
|
|
|
|
output rxi_wr_wait; //wait indicator for write transactions
|
|
|
|
//# EMESH (write transactions with the off chip destination)
|
|
output c0_emesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c0_emesh_tran_out; // serialized transaction
|
|
output c3_emesh_frame_out; // transaction frame
|
|
output [2*LW-1:0] c3_emesh_tran_out; // serialized transaction
|
|
// # MESH (write transactions internal and external corners)
|
|
// # core0
|
|
output c0_mesh_access_out; // access control to the mesh
|
|
output c0_mesh_write_out; // write control to the mesh
|
|
output [AW-1:0] c0_mesh_dstaddr_out; // destination address to the mesh
|
|
output [AW-1:0] c0_mesh_srcaddr_out; // source address to the mesh
|
|
output [DW-1:0] c0_mesh_data_out; // data to the mesh
|
|
output [1:0] c0_mesh_datamode_out;// data mode to the mesh
|
|
output [3:0] c0_mesh_ctrlmode_out;// ctrl mode to the mesh
|
|
// # core3
|
|
output c3_mesh_access_out; // access control to the mesh
|
|
output c3_mesh_write_out; // write control to the mesh
|
|
output [AW-1:0] c3_mesh_dstaddr_out; // destination address to the mesh
|
|
output [AW-1:0] c3_mesh_srcaddr_out; // source address to the mesh
|
|
output [DW-1:0] c3_mesh_data_out; // data to the mesh
|
|
output [1:0] c3_mesh_datamode_out;// data mode to the mesh
|
|
output [3:0] c3_mesh_ctrlmode_out;// ctrl mode to the mesh
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
|
wire c0_fifo_access; // From link_rxi_buffer of link_rxi_buffer.v
|
|
wire c0_fifo_full_rlc; // From c0_link_rxi_double_channel of link_rxi_double_channel.v
|
|
wire c1_fifo_access; // From link_rxi_buffer of link_rxi_buffer.v
|
|
wire c2_fifo_access; // From link_rxi_buffer of link_rxi_buffer.v
|
|
wire c3_fifo_access; // From link_rxi_buffer of link_rxi_buffer.v
|
|
wire c3_fifo_full_rlc; // From c3_link_rxi_double_channel of link_rxi_double_channel.v
|
|
wire [14*LW-1:0] rxi_assembled_tran_rlc; // From link_rxi_buffer of link_rxi_buffer.v
|
|
// End of automatics
|
|
|
|
//##########
|
|
//# WIRES
|
|
//##########
|
|
|
|
wire c0_fifo_access_rlc;
|
|
wire c3_fifo_access_rlc;
|
|
|
|
|
|
// ################################
|
|
// # Receiver buffer instantiation
|
|
// ################################
|
|
|
|
/*link_rxi_buffer AUTO_TEMPLATE (.rxi_rd (1'b0),
|
|
.rxi_wait (rxi_wr_wait),
|
|
.reset (reset),
|
|
.vertical_k (vertical_k),
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.rxi_data (rxi_data[LW-1:0]),
|
|
.rxi_lclk (rxi_lclk),
|
|
.rxi_frame (rxi_frame),
|
|
.rxi_\(.*\)_access (\1_fifo_access),
|
|
.\(.*\) (\1_rlc[]),
|
|
.cfg_extcomp_dis (cfg_extcomp_dis),
|
|
.c1_fifo_full (1'b0),
|
|
.c2_fifo_full (1'b0),
|
|
);
|
|
*/
|
|
link_rxi_buffer link_rxi_buffer(/*AUTOINST*/
|
|
// Outputs
|
|
.rxi_wait (rxi_wr_wait), // Templated
|
|
.rxi_assembled_tran (rxi_assembled_tran_rlc[14*LW-1:0]), // Templated
|
|
.rxi_c0_access (c0_fifo_access), // Templated
|
|
.rxi_c1_access (c1_fifo_access), // Templated
|
|
.rxi_c2_access (c2_fifo_access), // Templated
|
|
.rxi_c3_access (c3_fifo_access), // Templated
|
|
// Inputs
|
|
.reset (reset), // Templated
|
|
.vertical_k (vertical_k), // Templated
|
|
.ext_yid_k (ext_yid_k[3:0]), // Templated
|
|
.ext_xid_k (ext_xid_k[3:0]), // Templated
|
|
.rxi_data (rxi_data[LW-1:0]), // Templated
|
|
.rxi_lclk (rxi_lclk), // Templated
|
|
.rxi_frame (rxi_frame), // Templated
|
|
.rxi_rd (1'b0), // Templated
|
|
.cfg_extcomp_dis (cfg_extcomp_dis), // Templated
|
|
.c0_fifo_full (c0_fifo_full_rlc), // Templated
|
|
.c1_fifo_full (1'b0), // Templated
|
|
.c2_fifo_full (1'b0), // Templated
|
|
.c3_fifo_full (c3_fifo_full_rlc)); // Templated
|
|
|
|
// ################################################
|
|
// # Receiver channels instantiation
|
|
// ################################################
|
|
|
|
//# All the received transactions will be issued on channel0 or channel3 only
|
|
assign c0_fifo_access_rlc = c0_fifo_access | c1_fifo_access;
|
|
assign c3_fifo_access_rlc = c2_fifo_access | c3_fifo_access;
|
|
|
|
/*link_rxi_double_channel AUTO_TEMPLATE (
|
|
.fifo_full_rlc (@"(substring vl-cell-name 0 2)"_fifo_full_rlc),
|
|
.\(.*\)_out (@"(substring vl-cell-name 0 2)"_\1_out[]),
|
|
.emesh_wait_in (@"(substring vl-cell-name 0 2)"_emesh_wait_in),
|
|
.mesh_\(.*\) (@"(substring vl-cell-name 0 2)"_mesh_\1[]),
|
|
.cclk (@"(substring vl-cell-name 0 2)"_clk_in),
|
|
.cclk_en (1'b1),
|
|
.fifo_access_rlc (@"(substring vl-cell-name 0 2)"_fifo_access_rlc),
|
|
.mesh_fifo_access_rlc (mesh_fifo_access_rlc),
|
|
);
|
|
*/
|
|
|
|
//# channel 0 (emesh + mesh + mesh for multicast)
|
|
link_rxi_double_channel c0_link_rxi_double_channel(/*AUTOINST*/
|
|
// Outputs
|
|
.fifo_full_rlc (c0_fifo_full_rlc), // Templated
|
|
.emesh_tran_out (c0_emesh_tran_out[2*LW-1:0]), // Templated
|
|
.emesh_frame_out (c0_emesh_frame_out), // Templated
|
|
.mesh_access_out (c0_mesh_access_out), // Templated
|
|
.mesh_write_out (c0_mesh_write_out), // Templated
|
|
.mesh_dstaddr_out (c0_mesh_dstaddr_out[AW-1:0]), // Templated
|
|
.mesh_srcaddr_out (c0_mesh_srcaddr_out[AW-1:0]), // Templated
|
|
.mesh_data_out (c0_mesh_data_out[DW-1:0]), // Templated
|
|
.mesh_datamode_out(c0_mesh_datamode_out[1:0]), // Templated
|
|
.mesh_ctrlmode_out(c0_mesh_ctrlmode_out[3:0]), // Templated
|
|
// Inputs
|
|
.reset (reset),
|
|
.cclk (c0_clk_in), // Templated
|
|
.cclk_en (1'b1), // Templated
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.rxi_lclk (rxi_lclk),
|
|
.who_am_i (who_am_i[3:0]),
|
|
.cfg_extcomp_dis (cfg_extcomp_dis),
|
|
.rxi_assembled_tran_rlc(rxi_assembled_tran_rlc[14*LW-1:0]),
|
|
.fifo_access_rlc (c0_fifo_access_rlc), // Templated
|
|
.emesh_wait_in (c0_emesh_wait_in), // Templated
|
|
.mesh_wait_in (c0_mesh_wait_in)); // Templated
|
|
|
|
//# channel 3 (emesh + mesh)
|
|
link_rxi_double_channel c3_link_rxi_double_channel(/*AUTOINST*/
|
|
// Outputs
|
|
.fifo_full_rlc (c3_fifo_full_rlc), // Templated
|
|
.emesh_tran_out (c3_emesh_tran_out[2*LW-1:0]), // Templated
|
|
.emesh_frame_out (c3_emesh_frame_out), // Templated
|
|
.mesh_access_out (c3_mesh_access_out), // Templated
|
|
.mesh_write_out (c3_mesh_write_out), // Templated
|
|
.mesh_dstaddr_out (c3_mesh_dstaddr_out[AW-1:0]), // Templated
|
|
.mesh_srcaddr_out (c3_mesh_srcaddr_out[AW-1:0]), // Templated
|
|
.mesh_data_out (c3_mesh_data_out[DW-1:0]), // Templated
|
|
.mesh_datamode_out(c3_mesh_datamode_out[1:0]), // Templated
|
|
.mesh_ctrlmode_out(c3_mesh_ctrlmode_out[3:0]), // Templated
|
|
// Inputs
|
|
.reset (reset),
|
|
.cclk (c3_clk_in), // Templated
|
|
.cclk_en (1'b1), // Templated
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.rxi_lclk (rxi_lclk),
|
|
.who_am_i (who_am_i[3:0]),
|
|
.cfg_extcomp_dis (cfg_extcomp_dis),
|
|
.rxi_assembled_tran_rlc(rxi_assembled_tran_rlc[14*LW-1:0]),
|
|
.fifo_access_rlc (c3_fifo_access_rlc), // Templated
|
|
.emesh_wait_in (c3_emesh_wait_in), // Templated
|
|
.mesh_wait_in (c3_mesh_wait_in)); // Templated
|
|
|
|
|
|
endmodule // link_rxi_wr
|
|
module link_transmitter (/*AUTOARG*/
|
|
// Outputs
|
|
txo_data, txo_lclk90, txo_frame, c0_emesh_wait_out,
|
|
c1_emesh_wait_out, c2_emesh_wait_out, c3_emesh_wait_out,
|
|
c0_rdmesh_wait_out, c1_rdmesh_wait_out, c2_rdmesh_wait_out,
|
|
c3_rdmesh_wait_out, c0_mesh_wait_out, c3_mesh_wait_out,
|
|
// Inputs
|
|
reset, ext_yid_k, ext_xid_k, who_am_i, txo_cfg_reg, txo_wr_wait,
|
|
txo_rd_wait, c0_clk_in, c1_clk_in, c2_clk_in, c3_clk_in,
|
|
c0_mesh_access_in, c0_mesh_write_in, c0_mesh_dstaddr_in,
|
|
c0_mesh_srcaddr_in, c0_mesh_data_in, c0_mesh_datamode_in,
|
|
c0_mesh_ctrlmode_in, c3_mesh_access_in, c3_mesh_write_in,
|
|
c3_mesh_dstaddr_in, c3_mesh_srcaddr_in, c3_mesh_data_in,
|
|
c3_mesh_datamode_in, c3_mesh_ctrlmode_in, c0_emesh_frame_in,
|
|
c0_emesh_tran_in, c1_emesh_frame_in, c1_emesh_tran_in,
|
|
c2_emesh_frame_in, c2_emesh_tran_in, c3_emesh_frame_in,
|
|
c3_emesh_tran_in
|
|
);
|
|
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
parameter AW = `CFG_AW ;//address width
|
|
parameter DW = `CFG_DW ;//data width
|
|
|
|
// #########
|
|
// # Inputs
|
|
// #########
|
|
|
|
input reset;
|
|
input [3:0] ext_yid_k; //external y-id
|
|
input [3:0] ext_xid_k; //external x-id
|
|
input [3:0] who_am_i; // specifies what link is that (north,east,south,west)
|
|
|
|
// # Configuration registers
|
|
input [5:0] txo_cfg_reg; //Clock divider configuration on bits 3-0,
|
|
//Bursting disable control on bit 4
|
|
//Multicast disable control on bit 5
|
|
// # from io
|
|
input txo_wr_wait; //wait indicator for write transactions
|
|
input txo_rd_wait; //wait indicator for read transactions
|
|
|
|
// # Clocks
|
|
input c0_clk_in; // clock of the core
|
|
input c1_clk_in; // clock of the core
|
|
input c2_clk_in; // clock of the core
|
|
input c3_clk_in; // clock of the core
|
|
|
|
// # MESH
|
|
// # core0 (external corners and multicast)
|
|
input c0_mesh_access_in; // access control from the mesh
|
|
input c0_mesh_write_in; // write control from the mesh
|
|
input [AW-1:0] c0_mesh_dstaddr_in; // destination address from the mesh
|
|
input [AW-1:0] c0_mesh_srcaddr_in; // source address from the mesh
|
|
input [DW-1:0] c0_mesh_data_in; // data from the mesh
|
|
input [1:0] c0_mesh_datamode_in;// data mode from the mesh
|
|
input [3:0] c0_mesh_ctrlmode_in;// ctrl mode from the mesh
|
|
// # core3 (external corners only)
|
|
input c3_mesh_access_in; // access control from the mesh
|
|
input c3_mesh_write_in; // write control from the mesh
|
|
input [AW-1:0] c3_mesh_dstaddr_in; // destination address from the mesh
|
|
input [AW-1:0] c3_mesh_srcaddr_in; // source address from the mesh
|
|
input [DW-1:0] c3_mesh_data_in; // data from the mesh
|
|
input [1:0] c3_mesh_datamode_in;// data mode from the mesh
|
|
input [3:0] c3_mesh_ctrlmode_in;// ctrl mode from the mesh
|
|
|
|
// ##############
|
|
// # Outputs
|
|
// ##############
|
|
|
|
output [LW-1:0] txo_data; //Byte word
|
|
output txo_lclk90; //transmit clock (adjusted to the frame/data)
|
|
output txo_frame; //indicates new transmission
|
|
|
|
output c0_emesh_wait_out; // wait to the emesh
|
|
output c1_emesh_wait_out; // wait to the emesh
|
|
output c2_emesh_wait_out; // wait to the emesh
|
|
output c3_emesh_wait_out; // wait to the emesh
|
|
|
|
output c0_rdmesh_wait_out; // wait to the rdmesh
|
|
output c1_rdmesh_wait_out; // wait to the rdmesh
|
|
output c2_rdmesh_wait_out; // wait to the rdmesh
|
|
output c3_rdmesh_wait_out; // wait to the rdmesh
|
|
|
|
output c0_mesh_wait_out; // wait to the mesh
|
|
output c3_mesh_wait_out; // wait to the mesh
|
|
|
|
// ##########
|
|
// # WIRES
|
|
// ##########
|
|
|
|
wire txo_lclk; //transmit clock to be used internally
|
|
wire txo_lclk90;//transmit clock (adjusted to the frame/data)
|
|
|
|
/*AUTOINPUT*/
|
|
// Beginning of automatic inputs (from unused autoinst inputs)
|
|
input c0_emesh_frame_in; // To link_txo_wr of link_txo_wr.v
|
|
input [2*LW-1:0] c0_emesh_tran_in; // To link_txo_wr of link_txo_wr.v
|
|
input c1_emesh_frame_in; // To link_txo_wr of link_txo_wr.v
|
|
input [2*LW-1:0] c1_emesh_tran_in; // To link_txo_wr of link_txo_wr.v
|
|
input c2_emesh_frame_in; // To link_txo_wr of link_txo_wr.v
|
|
input [2*LW-1:0] c2_emesh_tran_in; // To link_txo_wr of link_txo_wr.v
|
|
input c3_emesh_frame_in; // To link_txo_wr of link_txo_wr.v
|
|
input [2*LW-1:0] c3_emesh_tran_in; // To link_txo_wr of link_txo_wr.v
|
|
// End of automatics
|
|
/*AUTOWIRE*/
|
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
|
wire [LW-1:0] txo_wr_data_even; // From link_txo_wr of link_txo_wr.v
|
|
wire [LW-1:0] txo_wr_data_odd; // From link_txo_wr of link_txo_wr.v
|
|
wire txo_wr_frame; // From link_txo_wr of link_txo_wr.v
|
|
wire txo_wr_launch_req_tlc; // From link_txo_wr of link_txo_wr.v
|
|
wire txo_wr_rotate_dis; // From link_txo_wr of link_txo_wr.v
|
|
// End of automatics
|
|
|
|
|
|
// ##############################
|
|
// # Clock divider instantiation
|
|
// ##############################
|
|
|
|
//# Since the logic of the fifo of the transmitter's channel
|
|
//# assumes txo_lck and cclk to be asynchronous clocks, we don't
|
|
//# mind to have txo_lclk be generated out of any of the clk_in
|
|
//# clocks even though they are inverted relative to each other.
|
|
//# c1_clk_in is selected because of the physical implementation
|
|
//# considerations.
|
|
e16_clock_divider clock_divider (.clk_out (txo_lclk),
|
|
.clk_out90 (txo_lclk90),
|
|
.clk_in (c1_clk_in),
|
|
.reset (reset),
|
|
.div_cfg (4'b0)
|
|
);
|
|
|
|
//########################
|
|
//# Transmitter interface
|
|
//########################
|
|
|
|
link_txo_interface link_txo_interface(
|
|
// Outputs
|
|
.txo_data (txo_data[LW-1:0]),
|
|
.txo_frame (txo_frame),
|
|
.txo_wr_wait_int (txo_wr_wait_int),
|
|
.txo_rd_wait_int (txo_rd_wait_int),
|
|
// Inputs
|
|
.txo_lclk (txo_lclk),
|
|
.reset (reset),
|
|
.txo_wr_data_even (txo_wr_data_even[LW-1:0]),
|
|
.txo_wr_data_odd (txo_wr_data_odd[LW-1:0]),
|
|
.txo_wr_frame (txo_wr_frame),
|
|
.txo_wr_launch_req_tlc (txo_wr_launch_req_tlc),
|
|
.txo_wr_rotate_dis (txo_wr_rotate_dis),
|
|
.txo_rd_data_even (8'd0),
|
|
.txo_rd_data_odd (8'd0),
|
|
.txo_rd_frame (1'd0),
|
|
.txo_rd_launch_req_tlc (1'd0),
|
|
.txo_rd_rotate_dis (1'd0)
|
|
);
|
|
|
|
//#################################
|
|
//# Write Transactions Transmitter
|
|
//#################################
|
|
|
|
link_txo_wr link_txo_wr(.cfg_burst_dis (txo_cfg_reg[4]),
|
|
.cfg_multicast_dis (txo_cfg_reg[5]),
|
|
.txo_wr_wait_int (txo_wr_wait_int),
|
|
/*AUTOINST*/
|
|
// Outputs
|
|
.txo_wr_data_even (txo_wr_data_even[LW-1:0]),
|
|
.txo_wr_data_odd (txo_wr_data_odd[LW-1:0]),
|
|
.txo_wr_frame (txo_wr_frame),
|
|
.txo_wr_launch_req_tlc(txo_wr_launch_req_tlc),
|
|
.txo_wr_rotate_dis (txo_wr_rotate_dis),
|
|
.c0_emesh_wait_out (c0_emesh_wait_out),
|
|
.c1_emesh_wait_out (c1_emesh_wait_out),
|
|
.c2_emesh_wait_out (c2_emesh_wait_out),
|
|
.c3_emesh_wait_out (c3_emesh_wait_out),
|
|
.c0_mesh_wait_out (c0_mesh_wait_out),
|
|
.c3_mesh_wait_out (c3_mesh_wait_out),
|
|
// Inputs
|
|
.txo_lclk (txo_lclk),
|
|
.reset (reset),
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.who_am_i (who_am_i[3:0]),
|
|
.txo_wr_wait (txo_wr_wait),
|
|
.c0_clk_in (c0_clk_in),
|
|
.c1_clk_in (c1_clk_in),
|
|
.c2_clk_in (c2_clk_in),
|
|
.c3_clk_in (c3_clk_in),
|
|
.c0_emesh_tran_in (c0_emesh_tran_in[2*LW-1:0]),
|
|
.c0_emesh_frame_in (c0_emesh_frame_in),
|
|
.c1_emesh_tran_in (c1_emesh_tran_in[2*LW-1:0]),
|
|
.c1_emesh_frame_in (c1_emesh_frame_in),
|
|
.c2_emesh_tran_in (c2_emesh_tran_in[2*LW-1:0]),
|
|
.c2_emesh_frame_in (c2_emesh_frame_in),
|
|
.c3_emesh_tran_in (c3_emesh_tran_in[2*LW-1:0]),
|
|
.c3_emesh_frame_in (c3_emesh_frame_in),
|
|
.c0_mesh_access_in (c0_mesh_access_in),
|
|
.c0_mesh_write_in (c0_mesh_write_in),
|
|
.c0_mesh_dstaddr_in (c0_mesh_dstaddr_in[AW-1:0]),
|
|
.c0_mesh_srcaddr_in (c0_mesh_srcaddr_in[AW-1:0]),
|
|
.c0_mesh_data_in (c0_mesh_data_in[DW-1:0]),
|
|
.c0_mesh_datamode_in (c0_mesh_datamode_in[1:0]),
|
|
.c0_mesh_ctrlmode_in (c0_mesh_ctrlmode_in[3:0]),
|
|
.c3_mesh_access_in (c3_mesh_access_in),
|
|
.c3_mesh_write_in (c3_mesh_write_in),
|
|
.c3_mesh_dstaddr_in (c3_mesh_dstaddr_in[AW-1:0]),
|
|
.c3_mesh_srcaddr_in (c3_mesh_srcaddr_in[AW-1:0]),
|
|
.c3_mesh_data_in (c3_mesh_data_in[DW-1:0]),
|
|
.c3_mesh_datamode_in (c3_mesh_datamode_in[1:0]),
|
|
.c3_mesh_ctrlmode_in (c3_mesh_ctrlmode_in[3:0]));
|
|
|
|
|
|
endmodule // link_transmitter
|
|
module link_txo_arbiter(/*AUTOARG*/
|
|
// Outputs
|
|
txo_launch_req_tlc, txo_rotate_dis_tlc, c0_txo_launch_ack_tlc,
|
|
c1_txo_launch_ack_tlc, c2_txo_launch_ack_tlc,
|
|
c3_txo_launch_ack_tlc,
|
|
// Inputs
|
|
txo_lclk, reset, txo_wait, txo_wait_int, c0_txo_launch_req_tlc,
|
|
c0_txo_rotate_dis, c1_txo_launch_req_tlc, c1_txo_rotate_dis,
|
|
c2_txo_launch_req_tlc, c2_txo_rotate_dis, c3_txo_launch_req_tlc,
|
|
c3_txo_rotate_dis
|
|
);
|
|
|
|
|
|
// ##########
|
|
// # Inputs
|
|
// ##########
|
|
|
|
input txo_lclk;
|
|
input reset;
|
|
input txo_wait; // Wait from the receiver (we have to finish current transmission)
|
|
input txo_wait_int; // Wait from the txo_interface (have to stall immediately)
|
|
|
|
//Channel 0
|
|
input c0_txo_launch_req_tlc; // Launch request
|
|
input c0_txo_rotate_dis; // Arbiter's rotate disable
|
|
//Channel 1
|
|
input c1_txo_launch_req_tlc; // Launch request
|
|
input c1_txo_rotate_dis; // Arbiter's rotate disable
|
|
//Channel 2
|
|
input c2_txo_launch_req_tlc; // Launch request
|
|
input c2_txo_rotate_dis; // Arbiter's rotate disable
|
|
//Channel 3
|
|
input c3_txo_launch_req_tlc; // Launch request
|
|
input c3_txo_rotate_dis; // Arbiter's rotate disable
|
|
|
|
// ##########
|
|
// # Outputs
|
|
// ##########
|
|
// to the txo_interface
|
|
output txo_launch_req_tlc;
|
|
output txo_rotate_dis_tlc;
|
|
// to the channels
|
|
output c0_txo_launch_ack_tlc;
|
|
output c1_txo_launch_ack_tlc;
|
|
output c2_txo_launch_ack_tlc;
|
|
output c3_txo_launch_ack_tlc;
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
// #######
|
|
// # REGS
|
|
// #######
|
|
|
|
reg [3:0] grants_reg;
|
|
|
|
// ############
|
|
// # WIRES
|
|
// ############
|
|
|
|
wire [3:0] txo_rotate_dis;
|
|
wire en_arbitration;
|
|
wire en_rotate;
|
|
|
|
wire [3:0] grants; //one-hot grants signals
|
|
wire [3:0] requests_unmasked; //unmasked (original) requests
|
|
wire [3:0] requests; //requests
|
|
wire txo_wait_tlc;
|
|
|
|
//############################
|
|
//# txo_wait synchronization
|
|
//############################
|
|
e16_synchronizer #(.DW(1)) synchronizer(.out (txo_wait_tlc),
|
|
.in (txo_wait),
|
|
.clk (txo_lclk),
|
|
.reset (reset));
|
|
|
|
//#############################################################
|
|
//# creating requests information for the additional
|
|
//# arbitration which is performed in the txo_interface
|
|
//#############################################################
|
|
assign txo_launch_req_tlc = c0_txo_launch_req_tlc | c1_txo_launch_req_tlc |
|
|
c2_txo_launch_req_tlc | c3_txo_launch_req_tlc;
|
|
|
|
assign txo_rotate_dis_tlc = c0_txo_rotate_dis | c1_txo_rotate_dis |
|
|
c2_txo_rotate_dis | c3_txo_rotate_dis;
|
|
|
|
//###########################################
|
|
//# Rotation mechanism and requests creation
|
|
//###########################################
|
|
always @ (posedge txo_lclk or posedge reset)
|
|
if(reset)
|
|
grants_reg[3:0] <= 4'b0000;
|
|
else
|
|
grants_reg[3:0] <= grants[3:0];
|
|
|
|
assign txo_rotate_dis[3:0] = {c3_txo_rotate_dis,
|
|
c2_txo_rotate_dis,
|
|
c1_txo_rotate_dis,
|
|
c0_txo_rotate_dis};
|
|
|
|
assign en_rotate = ~(|(grants_reg[3:0] & txo_rotate_dis[3:0]));
|
|
|
|
assign en_arbitration = ~txo_wait_tlc | (|(txo_rotate_dis[3:0]));
|
|
|
|
assign requests_unmasked[3:0] = {c3_txo_launch_req_tlc,
|
|
c2_txo_launch_req_tlc,
|
|
c1_txo_launch_req_tlc,
|
|
c0_txo_launch_req_tlc};
|
|
|
|
assign requests[3:0] = {(4){en_arbitration}} &
|
|
requests_unmasked[3:0] & (grants_reg[3:0] | {(4){en_rotate}});
|
|
|
|
//############
|
|
//# Grants
|
|
//############
|
|
assign c3_txo_launch_ack_tlc = grants[3] & ~txo_wait_int;
|
|
assign c2_txo_launch_ack_tlc = grants[2] & ~txo_wait_int;
|
|
assign c1_txo_launch_ack_tlc = grants[1] & ~txo_wait_int;
|
|
assign c0_txo_launch_ack_tlc = grants[0] & ~txo_wait_int;
|
|
|
|
//######################################
|
|
//# Round-Robin Arbiter Instantiation
|
|
//######################################
|
|
/*e16_arbiter_roundrobin AUTO_TEMPLATE (.clk (txo_lclk),
|
|
.clk_en (1'b1),
|
|
.grants (grants[3:0]),
|
|
.requests (requests[3:0]),
|
|
);
|
|
*/
|
|
e16_arbiter_roundrobin #(.ARW(4)) arbiter_roundrobin(/*AUTOINST*/
|
|
// Outputs
|
|
.grants (grants[3:0]), // Templated
|
|
// Inputs
|
|
.clk (txo_lclk), // Templated
|
|
.clk_en (1'b1), // Templated
|
|
.reset (reset),
|
|
.en_rotate (en_rotate),
|
|
.requests (requests[3:0])); // Templated
|
|
|
|
endmodule // link_txo_arbiter
|
|
module link_txo_buffer(/*AUTOARG*/
|
|
// Outputs
|
|
txo_data_even, txo_data_odd, txo_frame,
|
|
// Inputs
|
|
c0_tran_frame_tlc, c0_tran_byte_even_tlc, c0_tran_byte_odd_tlc,
|
|
c1_tran_frame_tlc, c1_tran_byte_even_tlc, c1_tran_byte_odd_tlc,
|
|
c2_tran_frame_tlc, c2_tran_byte_even_tlc, c2_tran_byte_odd_tlc,
|
|
c3_tran_frame_tlc, c3_tran_byte_even_tlc, c3_tran_byte_odd_tlc
|
|
);
|
|
|
|
parameter LW = `CFG_LW;
|
|
|
|
// #########
|
|
// # Inputs
|
|
// #########
|
|
|
|
//# from channel 0
|
|
input c0_tran_frame_tlc; // Frame of the transaction
|
|
input [LW-1:0] c0_tran_byte_even_tlc; // Even byte of the transaction
|
|
input [LW-1:0] c0_tran_byte_odd_tlc; // Odd byte of the transaction
|
|
//# from channel 1
|
|
input c1_tran_frame_tlc; // Frame of the transaction
|
|
input [LW-1:0] c1_tran_byte_even_tlc; // Even byte of the transaction
|
|
input [LW-1:0] c1_tran_byte_odd_tlc; // Odd byte of the transaction
|
|
//# from channel 2
|
|
input c2_tran_frame_tlc; // Frame of the transaction
|
|
input [LW-1:0] c2_tran_byte_even_tlc; // Even byte of the transaction
|
|
input [LW-1:0] c2_tran_byte_odd_tlc; // Odd byte of the transaction
|
|
//# from channel 3
|
|
input c3_tran_frame_tlc; // Frame of the transaction
|
|
input [LW-1:0] c3_tran_byte_even_tlc; // Even byte of the transaction
|
|
input [LW-1:0] c3_tran_byte_odd_tlc; // Odd byte of the transaction
|
|
|
|
// ##########
|
|
// # Outputs
|
|
// ##########
|
|
|
|
output [LW-1:0] txo_data_even; //Even byte word
|
|
output [LW-1:0] txo_data_odd; //Odd byte word
|
|
output txo_frame; //indicates new transmission
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
// ##########
|
|
// # Regs
|
|
// ##########
|
|
|
|
// ##########
|
|
// # Wires
|
|
// ##########
|
|
|
|
wire txo_frame; // selected frame of the transmission
|
|
wire [LW-1:0] txo_data_even; // selected even bytes of the transmission
|
|
wire [LW-1:0] txo_data_odd; // selected odd bytes of the transmission
|
|
|
|
//###########################################
|
|
//# Transaction mux
|
|
//# The "and" part of the "and-or" mux is
|
|
//# implemented in the link channels blocks
|
|
//# therefore here we are good with "or" only
|
|
//###########################################
|
|
|
|
assign txo_frame = c0_tran_frame_tlc;
|
|
|
|
assign txo_data_even[LW-1:0] = c0_tran_byte_even_tlc[LW-1:0];
|
|
|
|
assign txo_data_odd[LW-1:0] = c0_tran_byte_odd_tlc[LW-1:0];
|
|
|
|
|
|
endmodule // link_txo_buffer
|
|
|
|
|
|
|
|
|
|
//#########################################################
|
|
//# This block is a single channel of the link transmitter
|
|
//# mechanism.
|
|
//#
|
|
//# The input transaction of this block is of the fixed size,
|
|
//# while the output transaction has an option
|
|
//# of the bursting where data of the new transaction
|
|
//# is sent without the address. In such a case the
|
|
//# address of the transaction will be determined in
|
|
//# the receiver according to the address of the
|
|
//# previous transaction.
|
|
//#
|
|
//# TXO-RXI TRANSMISSION PROTOCOL
|
|
//# ###############################
|
|
//# ---- ---- ---- ---- ---- --
|
|
//# LCLK _| |____| |____| |____| |____| |____|
|
|
//#
|
|
//# -------------------------------------
|
|
//# FRAME ______/
|
|
//# ----- ----- ----- ----- -----
|
|
//# DATA XXXXXXX 0 X 1 X 2 X 3 X 4 X .....
|
|
//# ----- ----- ----- ----- -----
|
|
//#
|
|
//# The byte sampled on the first rising edge of the LCLK following
|
|
//# the "low-to-high" change of the FRAME signal (byte0) will determine
|
|
//# the type of the transmitted data according to the following
|
|
//# encoding scheme:
|
|
//#
|
|
//# byte0 | transaction type
|
|
//# ----------------- | ----------------
|
|
//# 8'b??_??_?0_<cid> | New transaction with incremental bursting address
|
|
//# 8'b??_??_?1_<cid> | New transaction with the same bursting address
|
|
//#
|
|
//# cid[1:0] - channel id (for debugging usage only for now)
|
|
//#
|
|
//# New transaction structure:
|
|
//# -------------------------
|
|
//# byte1 -> ctrlmode[3:0],dstaddr[31:28]
|
|
//# byte2 -> dstaddr[27:20]
|
|
//# byte3 -> dstaddr[19:12]
|
|
//# byte4 -> dstaddr[11:4]
|
|
//# byte5 -> dstaddr[3:0],datamode[1:0],write,access
|
|
//# byte6 -> data[31:24] (or srcaddr[31:24] if read transaction)
|
|
//# byte7 -> data[23:16] (or srcaddr[23:16] if read transaction)
|
|
//# byte8 -> data[15:8] (or srcaddr[15:8] if read transaction)
|
|
//# *byte9 -> data[7:0] (or srcaddr[7:0] if read transaction)
|
|
//# byte10 -> data[63:56]
|
|
//# byte11 -> data[55:48]
|
|
//# byte12 -> data[47:40]
|
|
//# byte13 -> data[39:32]
|
|
//# **byte14 -> data[31:24]
|
|
//# ...
|
|
//# ...
|
|
//# ...
|
|
//#
|
|
//# * byte9 is the last byte of 32 bit write or read transaction
|
|
//#
|
|
//# ** if 64 bit write transaction, data of byte14 is the first data byte of
|
|
//# bursting transaction
|
|
//#
|
|
//# -- The data is transmitted MSB first but in 32bits resolution. If we want
|
|
//# to transmit 64 bits it will be [31:0] (msb first) and then [63:32] (msb first)
|
|
//#
|
|
//# !!!
|
|
//# !!! According to the above scheme, any new transaction (burst or not)
|
|
//# !!! will take at least four cycles to be transmitted.
|
|
//# !!! There are some internal mechanisms in the transmitter-receiver logic
|
|
//# !!! which are implemented considering this assumption true.
|
|
//# !!! Any change to this assumption (transaction takes at least four cycles)
|
|
//# !!! should be carefully reviewed with its implications on the internal
|
|
//# !!! implementation
|
|
//# !!!
|
|
//#
|
|
//#####################################################################
|
|
|
|
module link_txo_channel (/*AUTOARG*/
|
|
// Outputs
|
|
emesh_wait_out, txo_launch_req_tlc, txo_rotate_dis, tran_frame_tlc,
|
|
tran_byte_even_tlc, tran_byte_odd_tlc,
|
|
// Inputs
|
|
cclk, cclk_en, txo_lclk, reset, txo_rd, txo_cid, cfg_burst_dis,
|
|
emesh_tran_in, emesh_frame_in, txo_launch_ack_tlc
|
|
);
|
|
|
|
parameter AW = `CFG_AW ;//address width
|
|
parameter DW = `CFG_DW ;//data width
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
parameter FW = `CFG_NW*`CFG_LW;
|
|
parameter FAD = 5; // Number of bits to access all the entries (2^FAD + 1) > AE*PE
|
|
|
|
//##########
|
|
//# INPUTS
|
|
//##########
|
|
|
|
input cclk; // clock of the score the emesh comes from
|
|
input cclk_en; // clock enable
|
|
input txo_lclk; // clock of the link transmitter
|
|
input reset;
|
|
|
|
input txo_rd; // this is read transactions channel
|
|
input [1:0] txo_cid; // transmitter channel ID
|
|
input cfg_burst_dis; // control register bursting disable
|
|
|
|
//# from the EMESH
|
|
input [2*LW-1:0] emesh_tran_in; // serialized transaction
|
|
input emesh_frame_in; // transaction frame
|
|
|
|
//# from the arbiter
|
|
input txo_launch_ack_tlc;
|
|
|
|
//###########
|
|
//# OUTPUTS
|
|
//###########
|
|
//# to emesh
|
|
output emesh_wait_out; // wait to the emesh
|
|
|
|
//# to the arbiter
|
|
output txo_launch_req_tlc; // Launch request
|
|
output txo_rotate_dis; // Arbiter's rotate disable
|
|
|
|
//# to the output mux/buffer
|
|
output tran_frame_tlc; // Frame of the transaction
|
|
output [LW-1:0] tran_byte_even_tlc; // Even byte of the transaction
|
|
output [LW-1:0] tran_byte_odd_tlc; // Odd byte of the transaction
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
|
|
|
|
|
|
endmodule // link_txo_channel
|
|
|
|
//#############################################################################
|
|
//# This block is a custom fifo for the link single channel
|
|
//# transmitter.
|
|
//# The fifo has a following structure:
|
|
//# - 4 "architectural" entries to contain 4 full-size transactions.
|
|
//# Every architectural entry has 7 "sub-entries" of 16bit each
|
|
//# 112 bits in total (104 bits of actual transaction + 8 bits of zerros)
|
|
//# - 28 "physical" entries in total (4*7)
|
|
//#
|
|
//# The fifo is written in the "regular" manner - i.e. whenever there is an
|
|
//# empty "physical" entry to write in.
|
|
//# The fifo is read "freely" from within every "architectural" entry
|
|
//# (7 "physical" entries in a raw) once the "architectural" entry is written
|
|
//# in full.
|
|
//#
|
|
//# For this purpose, the "fifo write" domain indicates to the "fifo-read"
|
|
//# domain every "architectural" entry being written,
|
|
//# While the "fifo read" domain indicates to the "fifo-write" domain
|
|
//# every "physical" entry being read.
|
|
//#############################################################################
|
|
|
|
module link_txo_fifo (/*AUTOARG*/
|
|
// Outputs
|
|
wr_fifo_full, fifo_out_tlc, tran_written_tlc, next_ctrlmode_tlc,
|
|
next_dstaddr_tlc, next_datamode_tlc, next_write_tlc,
|
|
next_access_tlc,
|
|
// Inputs
|
|
reset, cclk, cclk_en, txo_lclk, tran_in, frame_in, rd_read_tlc,
|
|
check_next_dstaddr_tlc
|
|
);
|
|
|
|
parameter AW = `CFG_AW ;//address width
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
parameter AE = 4; // Number of "architectural" entries
|
|
parameter PE = 7; // Number of "physical" entries in the "architectural" one
|
|
parameter FAD = 5; // Number of bits to access all the entries (2^FAD + 1) > AE*PE
|
|
localparam MD = 1<<FAD;
|
|
|
|
// #########
|
|
// # Inputs
|
|
// #########
|
|
|
|
input reset;
|
|
|
|
input cclk; // core clock
|
|
input cclk_en; // core clock enable
|
|
input txo_lclk; // link transmitter clock
|
|
|
|
//# from the emesh/mesh selection logic
|
|
input [2*LW-1:0] tran_in; // serialized transaction
|
|
input frame_in; // transaction frame
|
|
|
|
//# from the control
|
|
input [FAD:0] rd_read_tlc; // Read containing potential jump for bursting
|
|
input check_next_dstaddr_tlc; // Next transaction dstaddr can be checked
|
|
|
|
// ##########
|
|
// # Outputs
|
|
// ##########
|
|
|
|
//# to the emesh/mesh selection logic
|
|
output wr_fifo_full;
|
|
|
|
//# to the control
|
|
output [2*LW-1:0] fifo_out_tlc;
|
|
output tran_written_tlc;
|
|
output [3:0] next_ctrlmode_tlc;
|
|
output [AW-1:0] next_dstaddr_tlc;
|
|
output [1:0] next_datamode_tlc;
|
|
output next_write_tlc;
|
|
output next_access_tlc;
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
// ##########
|
|
// # REGS
|
|
// #########
|
|
reg [LW-1:0] even_byte;
|
|
reg [2*LW-1:0] fifo_mem[MD-1:0];
|
|
|
|
reg [FAD:0] rd_gray_pointer_tlc;
|
|
reg [FAD:0] rd_binary_pointer_tlc;
|
|
reg [FAD:0] rd_addr_traninfo0_tlc;
|
|
|
|
reg frame_del;
|
|
reg [FAD:0] wr_binary_pointer;
|
|
reg wr_fifo_full;
|
|
|
|
// #########
|
|
// # WIRES
|
|
// #########
|
|
wire [FAD-1:0] rd_addr_tlc;
|
|
wire [FAD:0] rd_binary_next_tlc;
|
|
wire [FAD:0] rd_gray_next_tlc;
|
|
wire [FAD:0] rd_addr_traninfo0_next_tlc;
|
|
wire [FAD-1:0] rd_addr_traninfo1_tlc;
|
|
wire [FAD-1:0] rd_addr_traninfo2_tlc;
|
|
wire [2*LW-1:0] traninfo0_tlc;
|
|
wire [2*LW-1:0] traninfo1_tlc;
|
|
wire [2*LW-1:0] traninfo2_tlc;
|
|
|
|
wire [FAD-1:0] wr_addr;
|
|
wire wr_write;
|
|
wire tran_written;
|
|
wire [FAD:0] rd_gray_pointer;
|
|
wire wr_fifo_full_next;
|
|
wire [FAD:0] wr_gray_next;
|
|
wire [FAD:0] wr_binary_next;
|
|
|
|
//###########################
|
|
//# Write control generation
|
|
//###########################
|
|
always @ (posedge cclk or posedge reset)
|
|
if(reset)
|
|
frame_del <= 1'b0;
|
|
else if(cclk_en)
|
|
if(!wr_fifo_full)
|
|
frame_del <= frame_in;
|
|
|
|
assign wr_write = (frame_in | frame_del) & ~wr_fifo_full;
|
|
|
|
//###################################
|
|
//# Full transaction write completed
|
|
//###################################
|
|
assign tran_written = ~frame_in & frame_del & ~wr_fifo_full;
|
|
|
|
//#################################
|
|
//# FIFO data
|
|
//#################################
|
|
|
|
//# Write
|
|
//# two bytes of the tran short word should enter different fifo entries
|
|
//# in order to get 32 bit of data, dstaddr and srcaddr each "sitting" in two
|
|
//# entries only.
|
|
//# In this case byte0 of the first entry of the transaction
|
|
//# ({byte0,ctrlmode[3:0],dstaddr[31:28]}) will be a "zevel" but we don't care
|
|
//# since this byte is replaced later anyway.
|
|
|
|
always @ (posedge cclk)
|
|
if (cclk_en)
|
|
if(!wr_fifo_full)
|
|
even_byte[LW-1:0] <= tran_in[LW-1:0];
|
|
|
|
always @ (posedge cclk)
|
|
if (cclk_en)
|
|
if (wr_write)
|
|
fifo_mem[wr_addr[FAD-1:0]] <= {even_byte[LW-1:0],tran_in[2*LW-1:LW]};
|
|
|
|
//# Read (for dispatch)
|
|
assign fifo_out_tlc[2*LW-1:0] = fifo_mem[rd_addr_tlc[FAD-1:0]];
|
|
|
|
//# Read (first short word of the next transaction to dispatch)
|
|
assign traninfo0_tlc[2*LW-1:0] = fifo_mem[rd_addr_traninfo0_tlc[FAD-1:0]];
|
|
|
|
//# Read (second short word of the next transaction to dispatch)
|
|
assign traninfo1_tlc[2*LW-1:0] = fifo_mem[rd_addr_traninfo1_tlc[FAD-1:0]];
|
|
|
|
//# Read (third short word of the next transaction to dispatch)
|
|
assign traninfo2_tlc[2*LW-1:0] = fifo_mem[rd_addr_traninfo2_tlc[FAD-1:0]];
|
|
|
|
assign next_ctrlmode_tlc[3:0] = traninfo0_tlc[LW-1:LW-4];
|
|
|
|
assign next_dstaddr_tlc[AW-1:0] = {traninfo0_tlc[3:0],
|
|
traninfo1_tlc[2*LW-1:0],
|
|
traninfo2_tlc[2*LW-1:4]};
|
|
|
|
assign next_datamode_tlc[1:0] = traninfo2_tlc[3:2];
|
|
|
|
assign next_write_tlc = traninfo2_tlc[1];
|
|
assign next_access_tlc = traninfo2_tlc[0];
|
|
|
|
//#####################################
|
|
//# FIFO Write State Machine
|
|
//#####################################
|
|
|
|
//# While for the actual address calculation we use [FAD-1:0] bits only,
|
|
//# the bit FAD of the counter is needed in order to distinguish
|
|
//# between the fifo entry currently being written and the one
|
|
//# written in the previous "round" (FAD is a carry-out bit and is
|
|
//# switched every "round")
|
|
always @(posedge cclk or posedge reset)
|
|
if(reset)
|
|
wr_binary_pointer[FAD:0] <= {(FAD+1){1'b0}};
|
|
else if(cclk_en)
|
|
if(wr_write)
|
|
wr_binary_pointer[FAD:0] <= wr_binary_next[FAD:0];
|
|
|
|
assign wr_addr[FAD-1:0] = wr_binary_pointer[FAD-1:0];
|
|
assign wr_binary_next[FAD:0] = wr_binary_pointer[FAD:0] + {{(FAD){1'b0}},wr_write};
|
|
|
|
//# Gray Pointer Conversion (for more reliable synchronization)!
|
|
assign wr_gray_next[FAD:0] = {1'b0,wr_binary_next[FAD:1]} ^ wr_binary_next[FAD:0];
|
|
|
|
//# FIFO full indication
|
|
assign wr_fifo_full_next = (wr_gray_next[FAD-2:0] == rd_gray_pointer[FAD-2:0]) &
|
|
(wr_gray_next[FAD] ^ rd_gray_pointer[FAD]) &
|
|
(wr_gray_next[FAD-1] ^ rd_gray_pointer[FAD-1]);
|
|
|
|
always @ (posedge cclk or posedge reset)
|
|
if(reset)
|
|
wr_fifo_full <= 1'b0;
|
|
else if(cclk_en)
|
|
wr_fifo_full <=wr_fifo_full_next;
|
|
|
|
//#############################
|
|
//# FIFO Read State Machine
|
|
//#############################
|
|
|
|
always @(posedge txo_lclk or posedge reset)
|
|
if(reset)
|
|
begin
|
|
rd_binary_pointer_tlc[FAD:0] <= {(FAD+1){1'b0}};
|
|
rd_gray_pointer_tlc[FAD:0] <= {(FAD+1){1'b0}};
|
|
end
|
|
else if(|(rd_read_tlc[FAD:0]))
|
|
begin rd_binary_pointer_tlc[FAD:0] <= rd_binary_next_tlc[FAD:0];
|
|
rd_gray_pointer_tlc[FAD:0] <= rd_gray_next_tlc[FAD:0];
|
|
end
|
|
|
|
assign rd_addr_tlc[FAD-1:0] = rd_binary_pointer_tlc[FAD-1:0];
|
|
assign rd_binary_next_tlc[FAD:0] = rd_binary_pointer_tlc[FAD:0] + rd_read_tlc[FAD:0];
|
|
|
|
//# Gray Pointer Conversion (for more reliable synchronization)!
|
|
assign rd_gray_next_tlc[FAD:0] = {1'b0,rd_binary_next_tlc[FAD:1]} ^
|
|
rd_binary_next_tlc[FAD:0];
|
|
|
|
//#
|
|
//# address and controls of the next transaction to be dispatch
|
|
//# * the size is actually FAD-1:0 but since FAD=3 causes syntax
|
|
//# error for (FAD-3){1'b0} expression, we use a biger range
|
|
//# FAD:0 and (FAD-2){1'b0}
|
|
//assign rd_addr_traninfo0_next_tlc[FAD-1:0] = rd_addr_traninfo0_tlc[FAD-1:0] +
|
|
// {{(FAD-3){1'b0}},3'b111};
|
|
assign rd_addr_traninfo0_next_tlc[FAD:0] = rd_addr_traninfo0_tlc[FAD:0] +
|
|
{{(FAD-2){1'b0}},3'b111};
|
|
|
|
always @(posedge txo_lclk or posedge reset)
|
|
if(reset)
|
|
rd_addr_traninfo0_tlc[FAD:0] <= {(FAD){1'b0}};
|
|
else if(check_next_dstaddr_tlc)
|
|
rd_addr_traninfo0_tlc[FAD-1:0] <= rd_addr_traninfo0_next_tlc[FAD-1:0];
|
|
|
|
assign rd_addr_traninfo1_tlc[FAD-1:0] = rd_addr_traninfo0_tlc[FAD-1:0] +
|
|
{{(FAD-2){1'b0}},2'b01};
|
|
|
|
assign rd_addr_traninfo2_tlc[FAD-1:0] = rd_addr_traninfo0_tlc[FAD-1:0] +
|
|
{{(FAD-2){1'b0}},2'b10};
|
|
|
|
//####################################################
|
|
//# Synchronization between rd/wr domains
|
|
//####################################################
|
|
|
|
e16_pulse2pulse pulse_wr2rd (.out (tran_written_tlc),
|
|
.outclk (txo_lclk),
|
|
.in (tran_written),
|
|
.inclk (cclk),
|
|
.reset (reset));
|
|
|
|
e16_synchronizer #(.DW(FAD+1)) sync_rd2wr (.out (rd_gray_pointer[FAD:0]),
|
|
.in (rd_gray_pointer_tlc[FAD:0]),
|
|
.clk (cclk),
|
|
.reset (reset));
|
|
|
|
|
|
endmodule // link_txo_fifo
|
|
|
|
module link_txo_interface (/*AUTOARG*/
|
|
// Outputs
|
|
txo_data, txo_frame, txo_wr_wait_int, txo_rd_wait_int,
|
|
// Inputs
|
|
txo_lclk, reset, txo_wr_data_even, txo_wr_data_odd, txo_wr_frame,
|
|
txo_wr_launch_req_tlc, txo_wr_rotate_dis, txo_rd_data_even,
|
|
txo_rd_data_odd, txo_rd_frame, txo_rd_launch_req_tlc,
|
|
txo_rd_rotate_dis
|
|
);
|
|
|
|
parameter LW = `CFG_LW;
|
|
|
|
//#########
|
|
//# Inputs
|
|
//#########
|
|
|
|
input txo_lclk;
|
|
input reset;
|
|
|
|
//# write transactions
|
|
input [LW-1:0] txo_wr_data_even; //Even byte word
|
|
input [LW-1:0] txo_wr_data_odd; //Odd byte word
|
|
input txo_wr_frame; //indicates new transmission
|
|
input txo_wr_launch_req_tlc;
|
|
input txo_wr_rotate_dis;
|
|
//# read transactions
|
|
input [LW-1:0] txo_rd_data_even; //Even byte word
|
|
input [LW-1:0] txo_rd_data_odd; //Odd byte word
|
|
input txo_rd_frame; //indicates new transmission
|
|
input txo_rd_launch_req_tlc;
|
|
input txo_rd_rotate_dis;
|
|
|
|
//############
|
|
//# Outputs
|
|
//############
|
|
|
|
output [LW-1:0] txo_data; //Byte word
|
|
output txo_frame; //indicates new transmission
|
|
|
|
output txo_wr_wait_int; // Wait to txo_wr (have to stall immediately)
|
|
output txo_rd_wait_int; // Wait to txo_rd (have to stall immediately)
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
//##########
|
|
//# REGS
|
|
//##########
|
|
reg [LW-1:0] data_even_lsl;// Even bytes of the transmission
|
|
reg [LW-1:0] data_even_lsh;// Even bytes of the transmission
|
|
reg [LW-1:0] data_odd_lsl; // Odd bytes of the transmission
|
|
reg txo_frame; //indicates transmission of new package
|
|
|
|
//###########
|
|
//# WIRES
|
|
//###########
|
|
wire txo_frame_in; // selected frame of the transmission
|
|
wire [LW-1:0] data_even_in; // selected even bytes of the transmission
|
|
wire [LW-1:0] data_odd_in; // selected odd bytes of the transmission
|
|
wire [LW-1:0] txo_data; // ddr data
|
|
|
|
//###########################
|
|
//# Priority arbitration
|
|
//###########################
|
|
|
|
assign txo_wr_wait_int = txo_rd_rotate_dis;
|
|
assign txo_rd_wait_int = txo_wr_launch_req_tlc & ~txo_rd_rotate_dis;
|
|
|
|
//###########################################
|
|
//# Transaction mux
|
|
//# The "and" part of the "and-or" mux is
|
|
//# implemented in the link channels blocks
|
|
//# therefore here we are good with "or" only
|
|
//###########################################
|
|
|
|
assign txo_frame_in = txo_wr_frame | txo_rd_frame;
|
|
|
|
assign data_even_in[LW-1:0] = txo_wr_data_even[LW-1:0] |
|
|
txo_rd_data_even[LW-1:0];
|
|
|
|
assign data_odd_in[LW-1:0] = txo_wr_data_odd[LW-1:0] |
|
|
txo_rd_data_odd[LW-1:0];
|
|
|
|
// ################################
|
|
// # Transaction output
|
|
// ################################
|
|
|
|
always @ (posedge txo_lclk or posedge reset)
|
|
if (reset)
|
|
begin
|
|
txo_frame <= 1'b0;
|
|
data_even_lsl[LW-1:0] <= {(LW){1'b0}};
|
|
data_odd_lsl[LW-1:0] <= {(LW){1'b0}};
|
|
end
|
|
else
|
|
begin
|
|
txo_frame <= txo_frame_in;
|
|
data_even_lsl[LW-1:0] <= data_even_in[LW-1:0];
|
|
data_odd_lsl[LW-1:0] <= data_odd_in[LW-1:0];
|
|
end
|
|
|
|
// # Creating data that is stable high
|
|
always @ (negedge txo_lclk or posedge reset)
|
|
if (reset)
|
|
data_even_lsh[LW-1:0] <= {(LW){1'b0}};
|
|
else
|
|
data_even_lsh[LW-1:0] <= data_even_lsl[LW-1:0];
|
|
|
|
// #################################
|
|
// # Dual data rate implementation
|
|
// #################################
|
|
|
|
assign txo_data[LW-1:0] = txo_lclk ? data_even_lsh[LW-1:0]://stable high data
|
|
data_odd_lsl[LW-1:0]; //stable low data
|
|
|
|
|
|
endmodule // link_txo_interface
|
|
module link_txo_launcher (/*AUTOARG*/
|
|
// Outputs
|
|
rd_read, check_next_dstaddr, txo_launch_req, txo_rotate_dis,
|
|
tran_frame, tran_byte_even, tran_byte_odd,
|
|
// Inputs
|
|
reset, txo_lclk, txo_rd, txo_cid, cfg_burst_dis, fifo_out,
|
|
tran_written, next_ctrlmode, next_dstaddr, next_datamode,
|
|
next_write, next_access, txo_launch_ack
|
|
);
|
|
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
parameter AW = `CFG_AW ;//address width
|
|
parameter AE = 4; // Number of "architectural" entries
|
|
parameter PE = 7; // Number of "physical" entries in the "architectural" one
|
|
parameter FAD = 5; // Number of bits to access all the entries (2^FAD + 1) > AE*PE
|
|
|
|
//##########
|
|
//# INPUTS
|
|
//##########
|
|
input reset;
|
|
input txo_lclk; // link transmitter clock
|
|
|
|
input txo_rd; // this is read transactions channel
|
|
input [1:0] txo_cid; // transmitter channel ID
|
|
//# from configuration register
|
|
input cfg_burst_dis; // control register bursting disable
|
|
|
|
//# from the fifo
|
|
input [2*LW-1:0] fifo_out;
|
|
input tran_written;
|
|
input [3:0] next_ctrlmode;
|
|
input [AW-1:0] next_dstaddr;
|
|
input [1:0] next_datamode;
|
|
input next_write;
|
|
input next_access;
|
|
|
|
//# from the arbiter
|
|
input txo_launch_ack;
|
|
|
|
//############
|
|
//# OUTPUTS
|
|
//############
|
|
|
|
//# to the fifo
|
|
output [FAD:0] rd_read; // Read containing potential jump for bursting
|
|
output check_next_dstaddr; // Next transaction dstaddr can be checked
|
|
|
|
//# to the arbiter
|
|
output txo_launch_req; // Launch request
|
|
output txo_rotate_dis; // Arbiter's rotate disable
|
|
|
|
//# to the output mux/buffer
|
|
output tran_frame; // Frame of the transaction
|
|
output [LW-1:0] tran_byte_even; // Even byte of the transaction
|
|
output [LW-1:0] tran_byte_odd; // Odd byte of the transaction
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
//#############
|
|
//# REGS
|
|
//#############
|
|
reg [AE+1:0] fifo_trans;
|
|
reg [3:0] ref_ctrlmode;
|
|
reg [AW-1:0] ref_dstaddr;
|
|
reg [1:0] ref_datamode;
|
|
reg ref_write;
|
|
reg ref_access;
|
|
reg byte0_inc0;
|
|
reg txo_launch_init_req;
|
|
reg txo_launch_ack_del1;
|
|
reg txo_launch_ack_del2;
|
|
reg tran_frame;
|
|
reg [LW-1:0] byte_odd_del;
|
|
reg [LW-1:0] tran_byte_even;
|
|
reg [LW-1:0] tran_byte_odd;
|
|
reg [2:0] txo_launch_cnt;
|
|
reg burst_req;
|
|
reg [1:0] burst_backup_cnt;
|
|
|
|
//#############
|
|
//# WIRES
|
|
//#############
|
|
wire start_new_read;
|
|
wire [AW-1:0] ref_dstaddr_inc8; //Refernce address incremented by 8
|
|
wire next_inc8_match; // Next address match (incremented by 8)
|
|
wire next_inc0_match; // Next address match (un-incremented)
|
|
wire [7:0] ref_ctrl; // Control type of reference transaction
|
|
wire [7:0] next_ctrl;// Control type of next transaction
|
|
wire type_match; // Reference and next transactions are of the same type
|
|
wire [7:0] tran_byte0; // Byte0 of the transaction
|
|
wire burst_tran; // Burst transaction
|
|
wire [2:0] txo_launch_cnt_inc; // Incremented value of the counter
|
|
wire [2:0] txo_launch_cnt_next;// Next value of the counter
|
|
wire txo_launch_cnt_max; // The counter reached its maximum value
|
|
wire tran_read; // Transaction is read (last cycle of the transmission)
|
|
wire jump_4entries; // Jump forward four entries
|
|
wire jump_3entries; // Jump forward three entries
|
|
wire jump_3entries_write; // jump over srcaddr part of the tran on write
|
|
wire jump_3entries_read; // jump over data part of the transaction on read
|
|
wire jump_1entry; // single entry "jump"
|
|
wire [2:0] jump_value; // value of the jump for read pointer
|
|
wire txo_op_ack; // "operation" acknowledge
|
|
wire txo_op_ack_first; // first "operation" acknowledge cycle
|
|
wire [LW-1:0] byte_even_mux;
|
|
wire [LW-1:0] byte_odd_mux;
|
|
wire [LW-1:0] byte_even;
|
|
wire [LW-1:0] byte_odd;
|
|
wire make_gap; // make gap in the transaction frame
|
|
wire single_write; // single write transaction
|
|
wire double_write; // double write transaction
|
|
wire burst_req_denied; // request of burst transaction is not acknowledged
|
|
wire burst_backup_inc; // burst transaction backup counter increment
|
|
wire [1:0] burst_backup_inc_cnt; // Incremented burst backup counter
|
|
wire [1:0] burst_backup_next_cnt; // Next burst backup counter value
|
|
wire freeze_fifo; // FIFO and main counter advance should stoped
|
|
wire sel_ref_byte0; // select byte0 from the reference information of the transaction
|
|
wire sel_ref_byte1; // select byte1 from the reference information of the transaction
|
|
wire sel_ref_byte2; // select byte2 from the reference information of the transaction
|
|
wire sel_ref_byte3; // select byte3 from the reference information of the transaction
|
|
wire sel_ref_byte4; // select byte4 from the reference information of the transaction
|
|
wire sel_ref_byte5; // select byte5 from the reference information of the transaction
|
|
|
|
//####################################################
|
|
//# Interface to the arbiter
|
|
//#
|
|
//#####################################################
|
|
|
|
//# When the acknowledge is received on the last cycle of the transaction
|
|
//# and if the next transaction is not a burst transaction then we should
|
|
//# create an "artificial gap" in the frame signal.
|
|
//# If burst request was denied we should de-assert frame signal
|
|
|
|
assign make_gap = tran_read & ~burst_tran;
|
|
|
|
always @ (posedge txo_lclk or posedge reset)
|
|
if(reset)
|
|
begin
|
|
txo_launch_ack_del1 <= 1'b0;
|
|
txo_launch_ack_del2 <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
txo_launch_ack_del1 <= txo_launch_ack & ~make_gap;
|
|
txo_launch_ack_del2 <= txo_launch_ack_del1 & ~burst_req_denied;
|
|
end
|
|
|
|
assign txo_op_ack = txo_launch_ack & txo_launch_ack_del1;
|
|
assign txo_op_ack_first = txo_launch_ack_del1 & ~txo_launch_ack_del2;
|
|
|
|
//# Request and rotate disable
|
|
//# On the first cycle of the acknowledge the launch count is not incremented
|
|
//# yet, therefore we have to force request and rotate disable "artificially"
|
|
always @ (posedge txo_lclk or posedge reset)
|
|
if (reset)
|
|
txo_launch_init_req <= 1'b0;
|
|
else if(start_new_read)
|
|
txo_launch_init_req <= 1'b1;
|
|
else if(txo_launch_ack)
|
|
txo_launch_init_req <= 1'b0;
|
|
|
|
assign txo_launch_req = txo_launch_init_req |
|
|
txo_op_ack_first | (|(txo_launch_cnt[2:0]));
|
|
|
|
assign txo_rotate_dis = ~txo_launch_init_req &
|
|
(txo_op_ack_first | (|(txo_launch_cnt[2:0])));
|
|
|
|
//#######################################
|
|
//# Architectural entries state tracking
|
|
//# (written/read transactions tracking)
|
|
//#######################################
|
|
|
|
always @ (posedge txo_lclk or posedge reset)
|
|
if(reset)
|
|
fifo_trans[AE+1:0] <= {{(AE+1){1'b0}},1'b1};
|
|
else if(tran_written & ~tran_read)
|
|
fifo_trans[AE+1:0] <= {fifo_trans[AE:0],1'b0};
|
|
else if(tran_read & ~tran_written)
|
|
fifo_trans[AE+1:0] <= {1'b0,fifo_trans[AE+1:1]};
|
|
|
|
//# we start new read if:
|
|
//# 1. there is an indication of the first written transaction
|
|
//# 2. transaction is read and the new one is written at the same cycle
|
|
//# 3. transaction is read but there are more already written indicated by fifo_trans
|
|
assign start_new_read = (fifo_trans[0] & tran_written) |
|
|
(tran_read & tran_written) |
|
|
((|(fifo_trans[AE+1:2])) & tran_read );
|
|
|
|
assign check_next_dstaddr = start_new_read;
|
|
|
|
//#####################
|
|
//# Bursting logic
|
|
//#####################
|
|
|
|
//# keeping track of the address increment mode of burst transaction
|
|
always @ (posedge txo_lclk or posedge reset)
|
|
if(reset)
|
|
byte0_inc0 <= 1'b0;
|
|
else if(start_new_read)
|
|
byte0_inc0 <= next_inc0_match;
|
|
|
|
//# reference destination address and controls
|
|
always @(posedge txo_lclk)
|
|
if(start_new_read)
|
|
begin
|
|
ref_ctrlmode[3:0] <= next_ctrlmode[3:0];
|
|
ref_dstaddr[AW-1:0] <= next_dstaddr[AW-1:0];
|
|
ref_datamode[1:0] <= next_datamode[1:0];
|
|
ref_write <= next_write;
|
|
ref_access <= next_access;
|
|
end
|
|
|
|
//# transaction type (double write should be known in advance for burst determination)
|
|
// assign single_write = ref_access & ref_write & ~(&(ref_datamode[1:0]));
|
|
assign single_write = 1'b0; // No special treatment for single write
|
|
assign double_write = next_access & next_write & (&(next_datamode[1:0]));
|
|
|
|
//# compare address
|
|
assign ref_dstaddr_inc8[AW-1:0] = ref_dstaddr[AW-1:0]+{{(AW-4){1'b0}},4'b1000};
|
|
|
|
assign next_inc8_match = (ref_dstaddr_inc8[AW-1:0] == next_dstaddr[AW-1:0]);
|
|
assign next_inc0_match = (ref_dstaddr[AW-1:0] == next_dstaddr[AW-1:0]);
|
|
|
|
assign ref_ctrl[7:0] = {ref_ctrlmode[3:0], ref_datamode[1:0], ref_write, ref_access};
|
|
assign next_ctrl[7:0] = {next_ctrlmode[3:0],next_datamode[1:0],next_write,next_access};
|
|
|
|
assign type_match = (ref_ctrl[7:0] == next_ctrl[7:0]);
|
|
|
|
//# burst mode determination
|
|
assign burst_tran = ~cfg_burst_dis & // bursting is enabled by user
|
|
start_new_read & // valid cycle
|
|
tran_read & // only continuous burst is supported
|
|
type_match & // type match
|
|
double_write & // double write transaction
|
|
((next_inc8_match & ~byte0_inc0) | // address match
|
|
(next_inc0_match & byte0_inc0));
|
|
|
|
always @ (posedge txo_lclk or posedge reset)
|
|
if (reset)
|
|
burst_req <= 1'b0;
|
|
else
|
|
burst_req <= burst_tran;
|
|
|
|
//####################################################################################
|
|
//# Composing byte0 of the transaction
|
|
//#
|
|
//# Byte0 has the following encoding scheme:
|
|
//#
|
|
//# 8'b1?_??_??_<cid> | New READ transaction
|
|
//# 8'b0?_??_?0_<cid> | New WRITE transaction with incremental bursting address
|
|
//# 8'b0?_??_?1_<cid> | New WRITE transaction with the same bursting address
|
|
//#
|
|
//# cid[1:0] - channel id (for debugging usage only in the current version of design)
|
|
//####################################################################################
|
|
|
|
assign tran_byte0[7:0] = {txo_rd,4'b0000, byte0_inc0, txo_cid[1:0]};
|
|
|
|
//###################################################################
|
|
//# Order of the transaction fields in the fifo
|
|
//# -------------------------------------------
|
|
//# Entry "n+6" srcaddr[15:0]
|
|
//# Entry "n+5" srcaddr[31:16],
|
|
//# Entry "n+4" data[15:0],
|
|
//# Entry "n+3" data[31:16],
|
|
//# Entry "n+2" dstaddr[11:0],datamode[1:0],write,access,
|
|
//# Entry "n+1" dstaddr[27:12],
|
|
//# Entry "n" "zevel",ctrlmode[3:0],dstaddr[31:28],
|
|
//# --------------------------------------------
|
|
//####################################################################
|
|
|
|
//# 4 entries jump on burst transaction (counter comparison is redundant but used
|
|
//# here to underline the mutex between different jumps)
|
|
assign jump_4entries = burst_tran & (txo_launch_cnt[2:0] == 3'b110);
|
|
//# 3 entries jump on single write or read
|
|
assign jump_3entries = jump_3entries_write |
|
|
jump_3entries_read;
|
|
//# single write will jump 3 entries to the end of the transaction
|
|
assign jump_3entries_write = single_write & (txo_launch_cnt[2:0] == 3'b100);
|
|
//# read transaction will jump 3 entries over the data part of that transaction
|
|
//assign jump_3entries_read = ~ref_write & (txo_launch_cnt[2:0] == 3'b010);
|
|
//# read jump over data feature is disabled because of the test-and-set instr.
|
|
assign jump_3entries_read = 1'b0;
|
|
//# single jump when acknowledged and no other jumps and no freeze control
|
|
assign jump_1entry = ~(jump_4entries | jump_3entries | freeze_fifo) & txo_op_ack;
|
|
|
|
//###########################################################
|
|
//# Counter/FIFO Read Pointer increment prevention mechanism
|
|
//# when bursting is not acknowledged.
|
|
//# When burst_backup_cnt[1:0] is not zero, the counter and
|
|
//# FIFO read pointers won't advance and the data out
|
|
//# will be selected from the reference controls and address
|
|
//###########################################################
|
|
|
|
assign burst_req_denied = burst_req & ~txo_op_ack;
|
|
assign burst_backup_inc = freeze_fifo & txo_op_ack;
|
|
|
|
assign burst_backup_inc_cnt[1:0] = burst_backup_cnt[1:0] + 2'b01;
|
|
|
|
assign burst_backup_next_cnt[1:0] = burst_req_denied ? 2'b01 :
|
|
burst_backup_inc ? burst_backup_inc_cnt[1:0] :
|
|
burst_backup_cnt[1:0];
|
|
|
|
always @ (posedge txo_lclk or posedge reset)
|
|
if(reset)
|
|
burst_backup_cnt[1:0] <= 2'b00;
|
|
else
|
|
burst_backup_cnt[1:0] <= burst_backup_next_cnt[1:0];
|
|
|
|
assign freeze_fifo = |(burst_backup_cnt[1:0]);
|
|
|
|
//###################################################################
|
|
//# Launch Counter vs. FIFO Read Pointer:
|
|
//# FIFO Read Pointer is incremented in the range 0-6
|
|
//# relative to any particular entry pointed out in a particular
|
|
//# cycle.
|
|
//# Launch Counter on the other hand is incremented in the same
|
|
//# range of 0-6 but relative to a specific counter state.
|
|
//# For example, FIFO Read Pointer can have a jump of 4 from any
|
|
//# entry, while Launch Counter will have a jump of 4 only if
|
|
//# the current state of the counter is 3'b110 (+ some conditions)
|
|
//#
|
|
//# This difference in behavior is caused by the fact that
|
|
//# for every transaction in the counter we have to go through all
|
|
//# the eight existing states of the counter, while it will take
|
|
//# only six entriest of the FIFO.
|
|
//###################################################################
|
|
|
|
//# FIFO Read Pointer Jump Value
|
|
assign jump_value[2:0] = ({(3){jump_4entries}} & 3'b100) |
|
|
({(3){jump_3entries}} & 3'b011) |
|
|
({(3){jump_1entry}} & 3'b001);
|
|
|
|
assign rd_read[FAD:0] = {{(FAD-2){1'b0}},jump_value[2:0]};
|
|
|
|
//# Counter Next Cycle Value
|
|
assign txo_launch_cnt_max = (txo_launch_cnt[2:0] == 3'b110);
|
|
|
|
assign txo_launch_cnt_inc[2:0] = txo_launch_cnt[2:0] + {2'b00,jump_1entry};
|
|
|
|
assign txo_launch_cnt_next[2:0] = jump_4entries ? 3'b011 :
|
|
(jump_3entries_write | txo_launch_cnt_max) ? 3'b000 :
|
|
jump_3entries_read ? 3'b101 : txo_launch_cnt_inc[2:0];
|
|
|
|
//# Launch counter
|
|
always @ (posedge txo_lclk or posedge reset)
|
|
if (reset)
|
|
txo_launch_cnt[2:0] <= 3'b000;
|
|
else if(txo_op_ack)
|
|
txo_launch_cnt[2:0] <= txo_launch_cnt_next[2:0];
|
|
|
|
//#############################################
|
|
//# Completion of the transaction transmission
|
|
//#############################################
|
|
|
|
assign tran_read = (~single_write & (txo_launch_cnt[2:0] == 3'b110)) |
|
|
( single_write & (txo_launch_cnt[2:0] == 3'b100));
|
|
|
|
//##################################################
|
|
//# Even/Odd bytes construction + tran out sampling
|
|
//##################################################
|
|
|
|
assign sel_ref_byte0 = txo_op_ack_first;
|
|
assign sel_ref_byte2 = (burst_backup_cnt[1:0] == 2'b10);
|
|
assign sel_ref_byte4 = (burst_backup_cnt[1:0] == 2'b11);
|
|
|
|
assign sel_ref_byte1 = (burst_backup_cnt[1:0] == 2'b01);
|
|
assign sel_ref_byte3 = (burst_backup_cnt[1:0] == 2'b10);
|
|
assign sel_ref_byte5 = (burst_backup_cnt[1:0] == 2'b11);
|
|
|
|
assign byte_even_mux[LW-1:0] = sel_ref_byte0 ? tran_byte0[7:0] :
|
|
sel_ref_byte2 ? ref_dstaddr[27:20] :
|
|
sel_ref_byte4 ? ref_dstaddr[11:4] :
|
|
fifo_out[2*LW-1:LW];
|
|
|
|
assign byte_odd_mux[LW-1:0] = sel_ref_byte1 ? {ref_ctrlmode[3:0],ref_dstaddr[31:28]} :
|
|
sel_ref_byte3 ? ref_dstaddr[19:12] :
|
|
sel_ref_byte5 ? {ref_dstaddr[3:0],ref_datamode[1:0],ref_write,ref_access} :
|
|
fifo_out[LW-1:0];
|
|
|
|
assign byte_even[LW-1:0] = {(LW){txo_op_ack}} & byte_even_mux[LW-1:0];
|
|
assign byte_odd[LW-1:0] = {(LW){txo_op_ack}} & byte_odd_mux[LW-1:0];
|
|
|
|
always @ (posedge txo_lclk or posedge reset)
|
|
if(reset)
|
|
tran_frame <= 1'b0;
|
|
else
|
|
tran_frame <= txo_launch_ack_del2;
|
|
|
|
always @ (posedge txo_lclk)
|
|
begin
|
|
byte_odd_del[LW-1:0] <= byte_odd[LW-1:0];
|
|
tran_byte_odd[LW-1:0] <= byte_odd_del[LW-1:0];
|
|
tran_byte_even[LW-1:0] <= byte_even[LW-1:0];
|
|
end
|
|
|
|
//###################
|
|
//# ERROR CHECKERS
|
|
//###################
|
|
// synthesis translate_off
|
|
always @*
|
|
if(~(|(fifo_trans[AE+1:0])) & $time>0)
|
|
$display("ERROR>>link launcher mechanism is broken in cell %m");
|
|
|
|
always @*
|
|
if(((jump_4entries & (jump_3entries_read | jump_3entries_write | jump_1entry))|
|
|
(jump_3entries_read & ( jump_3entries_write | jump_1entry))|
|
|
(jump_3entries_write & ( jump_1entry)))
|
|
& $time>0)
|
|
$display("ERROR>>detected more than one jump for launcher mechanism in cell %m");
|
|
// synthesis translate_on
|
|
|
|
|
|
endmodule // link_txo_launcher
|
|
module link_txo_mesh_channel (/*AUTOARG*/
|
|
// Outputs
|
|
emesh_wait_out, mesh_wait_out, txo_launch_req_tlc,
|
|
txo_rotate_dis_tlc, tran_frame_tlc, tran_byte_even_tlc,
|
|
tran_byte_odd_tlc,
|
|
// Inputs
|
|
cclk, cclk_en, txo_lclk, reset, ext_yid_k, ext_xid_k, who_am_i,
|
|
txo_rd, txo_cid, cfg_multicast_dis, cfg_burst_dis, emesh_tran_in,
|
|
emesh_frame_in, mesh_access_in, mesh_write_in, mesh_dstaddr_in,
|
|
mesh_srcaddr_in, mesh_data_in, mesh_datamode_in, mesh_ctrlmode_in,
|
|
txo_launch_ack_tlc
|
|
);
|
|
|
|
parameter AW = `CFG_AW ;//address width
|
|
parameter DW = `CFG_DW ;//data width
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
parameter FW = `CFG_NW*`CFG_LW;
|
|
parameter FAD = 5; // Number of bits to access all the entries (2^FAD + 1) > AE*PE
|
|
|
|
//##########
|
|
//# INPUTS
|
|
//##########
|
|
|
|
input cclk; // clock of the score the emesh comes from
|
|
input cclk_en; // clock enable
|
|
input txo_lclk; // clock of the link transmitter
|
|
input reset;
|
|
input [3:0] ext_yid_k; //external y-id
|
|
input [3:0] ext_xid_k; //external x-id
|
|
input [3:0] who_am_i; // specifies what link is that (north,east,south,west)
|
|
|
|
input txo_rd; // this is read transactions channel
|
|
input [1:0] txo_cid; // transmitter channel ID
|
|
input cfg_multicast_dis; // control register multicast disable
|
|
input cfg_burst_dis; // control register bursting disable
|
|
|
|
//# from the EMESH
|
|
input [2*LW-1:0] emesh_tran_in; // serialized transaction
|
|
input emesh_frame_in; // transaction frame
|
|
|
|
//# from the MESH
|
|
input mesh_access_in; // access control from the mesh
|
|
input mesh_write_in; // write control from the mesh
|
|
input [AW-1:0] mesh_dstaddr_in; // destination address from the mesh
|
|
input [AW-1:0] mesh_srcaddr_in; // source address from the mesh
|
|
input [DW-1:0] mesh_data_in; // data from the mesh
|
|
input [1:0] mesh_datamode_in;// data mode from the mesh
|
|
input [3:0] mesh_ctrlmode_in;// ctrl mode from the mesh
|
|
|
|
//# from the arbiter
|
|
input txo_launch_ack_tlc;
|
|
|
|
//###########
|
|
//# OUTPUTS
|
|
//###########
|
|
//# to emesh
|
|
output emesh_wait_out; // wait to the emesh
|
|
|
|
//# to mesh
|
|
output mesh_wait_out; // wait to the mesh
|
|
|
|
//# to the arbiter
|
|
output txo_launch_req_tlc; // Launch request
|
|
output txo_rotate_dis_tlc; // Arbiter's rotate disable
|
|
|
|
//# to the output mux/buffer
|
|
output tran_frame_tlc; // Frame of the transaction
|
|
output [LW-1:0] tran_byte_even_tlc; // Even byte of the transaction
|
|
output [LW-1:0] tran_byte_odd_tlc; // Odd byte of the transaction
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
|
wire access_reg; // From mesh_interface of e16_mesh_interface.v
|
|
wire check_next_dstaddr_tlc; // From link_txo_launcher of link_txo_launcher.v
|
|
wire [3:0] ctrlmode_reg; // From mesh_interface of e16_mesh_interface.v
|
|
wire [DW-1:0] data_reg; // From mesh_interface of e16_mesh_interface.v
|
|
wire [1:0] datamode_reg; // From mesh_interface of e16_mesh_interface.v
|
|
wire [AW-1:0] dstaddr_reg; // From mesh_interface of e16_mesh_interface.v
|
|
wire [2*LW-1:0] fifo_out_tlc; // From link_txo_fifo of link_txo_fifo.v
|
|
wire mesh_frame; // From link_txo_mesh_launcher of link_txo_mesh_launcher.v
|
|
wire mesh_req; // From link_txo_mesh_launcher of link_txo_mesh_launcher.v
|
|
wire mesh_rotate_dis; // From link_txo_mesh_launcher of link_txo_mesh_launcher.v
|
|
wire [2*LW-1:0] mesh_tran; // From link_txo_mesh_launcher of link_txo_mesh_launcher.v
|
|
wire mesh_wait_int; // From link_txo_mesh_launcher of link_txo_mesh_launcher.v
|
|
wire next_access_tlc; // From link_txo_fifo of link_txo_fifo.v
|
|
wire [3:0] next_ctrlmode_tlc; // From link_txo_fifo of link_txo_fifo.v
|
|
wire [1:0] next_datamode_tlc; // From link_txo_fifo of link_txo_fifo.v
|
|
wire [AW-1:0] next_dstaddr_tlc; // From link_txo_fifo of link_txo_fifo.v
|
|
wire next_write_tlc; // From link_txo_fifo of link_txo_fifo.v
|
|
wire [FAD:0] rd_read_tlc; // From link_txo_launcher of link_txo_launcher.v
|
|
wire [AW-1:0] srcaddr_reg; // From mesh_interface of e16_mesh_interface.v
|
|
wire tran_written_tlc; // From link_txo_fifo of link_txo_fifo.v
|
|
wire wr_fifo_full; // From link_txo_fifo of link_txo_fifo.v
|
|
wire write_reg; // From mesh_interface of e16_mesh_interface.v
|
|
// End of automatics
|
|
|
|
//#######################
|
|
//# Transaction Launcher
|
|
//#######################
|
|
|
|
/* link_txo_launcher AUTO_TEMPLATE (
|
|
.txo_rotate_dis (txo_rotate_dis_tlc),
|
|
.reset (reset),
|
|
.txo_lclk (txo_lclk),
|
|
.txo_rd (txo_rd),
|
|
.txo_cid (txo_cid[1:0]),
|
|
.cfg_burst_dis (cfg_burst_dis),
|
|
.\(.*\) (\1_tlc[]),
|
|
);
|
|
*/
|
|
|
|
link_txo_launcher #(.FAD(FAD)) link_txo_launcher(/*AUTOINST*/
|
|
// Outputs
|
|
.rd_read (rd_read_tlc[FAD:0]), // Templated
|
|
.check_next_dstaddr (check_next_dstaddr_tlc), // Templated
|
|
.txo_launch_req (txo_launch_req_tlc), // Templated
|
|
.txo_rotate_dis (txo_rotate_dis_tlc), // Templated
|
|
.tran_frame (tran_frame_tlc), // Templated
|
|
.tran_byte_even (tran_byte_even_tlc[LW-1:0]), // Templated
|
|
.tran_byte_odd (tran_byte_odd_tlc[LW-1:0]), // Templated
|
|
// Inputs
|
|
.reset (reset), // Templated
|
|
.txo_lclk (txo_lclk), // Templated
|
|
.txo_rd (txo_rd), // Templated
|
|
.txo_cid (txo_cid[1:0]), // Templated
|
|
.cfg_burst_dis (cfg_burst_dis), // Templated
|
|
.fifo_out (fifo_out_tlc[2*LW-1:0]), // Templated
|
|
.tran_written (tran_written_tlc), // Templated
|
|
.next_ctrlmode (next_ctrlmode_tlc[3:0]), // Templated
|
|
.next_dstaddr (next_dstaddr_tlc[AW-1:0]), // Templated
|
|
.next_datamode (next_datamode_tlc[1:0]), // Templated
|
|
.next_write (next_write_tlc), // Templated
|
|
.next_access (next_access_tlc), // Templated
|
|
.txo_launch_ack (txo_launch_ack_tlc)); // Templated
|
|
|
|
//########
|
|
//# FIFO
|
|
//########
|
|
|
|
link_txo_fifo #(.FAD(FAD)) link_txo_fifo(.tran_in (mesh_tran[2*LW-1:0]),
|
|
.frame_in (mesh_frame),
|
|
/*AUTOINST*/
|
|
// Outputs
|
|
.wr_fifo_full (wr_fifo_full),
|
|
.fifo_out_tlc (fifo_out_tlc[2*LW-1:0]),
|
|
.tran_written_tlc (tran_written_tlc),
|
|
.next_ctrlmode_tlc (next_ctrlmode_tlc[3:0]),
|
|
.next_dstaddr_tlc (next_dstaddr_tlc[AW-1:0]),
|
|
.next_datamode_tlc (next_datamode_tlc[1:0]),
|
|
.next_write_tlc (next_write_tlc),
|
|
.next_access_tlc (next_access_tlc),
|
|
// Inputs
|
|
.reset (reset),
|
|
.cclk (cclk),
|
|
.cclk_en (cclk_en),
|
|
.txo_lclk (txo_lclk),
|
|
.rd_read_tlc (rd_read_tlc[FAD:0]),
|
|
.check_next_dstaddr_tlc(check_next_dstaddr_tlc));
|
|
|
|
|
|
//##################################
|
|
//# Interface with mesh
|
|
//# on input transactions only
|
|
//# * output to the mesh is driven
|
|
//# by a diferent block
|
|
//##################################
|
|
|
|
/*e16_mesh_interface AUTO_TEMPLATE (
|
|
.clk (cclk),
|
|
.clk_en (cclk_en),
|
|
.wait_int (mesh_wait_int),
|
|
.wait_out (mesh_wait_out),
|
|
.\(.*\)_out (),
|
|
.wait_in (1'b0),
|
|
.\(.*\)_in (mesh_\1_in[]),
|
|
.access (1'b0),
|
|
.write (1'b0),
|
|
.datamode (2'b00),
|
|
.ctrlmode (4'b0000),
|
|
.data ({(DW){1'b0}}),
|
|
.dstaddr ({(AW){1'b0}}),
|
|
.srcaddr ({(AW){1'b0}}),
|
|
);
|
|
*/
|
|
e16_mesh_interface mesh_interface(/*AUTOINST*/
|
|
// Outputs
|
|
.wait_out (mesh_wait_out), // Templated
|
|
.access_out (), // Templated
|
|
.write_out (), // Templated
|
|
.datamode_out (), // Templated
|
|
.ctrlmode_out (), // Templated
|
|
.data_out (), // Templated
|
|
.dstaddr_out (), // Templated
|
|
.srcaddr_out (), // Templated
|
|
.access_reg (access_reg),
|
|
.write_reg (write_reg),
|
|
.datamode_reg (datamode_reg[1:0]),
|
|
.ctrlmode_reg (ctrlmode_reg[3:0]),
|
|
.data_reg (data_reg[DW-1:0]),
|
|
.dstaddr_reg (dstaddr_reg[AW-1:0]),
|
|
.srcaddr_reg (srcaddr_reg[AW-1:0]),
|
|
// Inputs
|
|
.clk (cclk), // Templated
|
|
.clk_en (cclk_en), // Templated
|
|
.reset (reset),
|
|
.wait_in (1'b0), // Templated
|
|
.access_in (mesh_access_in), // Templated
|
|
.write_in (mesh_write_in), // Templated
|
|
.datamode_in (mesh_datamode_in[1:0]), // Templated
|
|
.ctrlmode_in (mesh_ctrlmode_in[3:0]), // Templated
|
|
.data_in (mesh_data_in[DW-1:0]), // Templated
|
|
.dstaddr_in (mesh_dstaddr_in[AW-1:0]), // Templated
|
|
.srcaddr_in (mesh_srcaddr_in[AW-1:0]), // Templated
|
|
.wait_int (mesh_wait_int), // Templated
|
|
.access (1'b0), // Templated
|
|
.write (1'b0), // Templated
|
|
.datamode (2'b00), // Templated
|
|
.ctrlmode (4'b0000), // Templated
|
|
.data ({(DW){1'b0}}), // Templated
|
|
.dstaddr ({(AW){1'b0}}), // Templated
|
|
.srcaddr ({(AW){1'b0}})); // Templated
|
|
|
|
|
|
//#################################
|
|
//# MESH Transaction Launcher
|
|
//#################################
|
|
|
|
link_txo_mesh_launcher link_txo_mesh_launcher(.mesh_grant (~wr_fifo_full),
|
|
/*AUTOINST*/
|
|
// Outputs
|
|
.mesh_wait_int (mesh_wait_int),
|
|
.mesh_req (mesh_req),
|
|
.mesh_rotate_dis (mesh_rotate_dis),
|
|
.mesh_tran (mesh_tran[2*LW-1:0]),
|
|
.mesh_frame (mesh_frame),
|
|
// Inputs
|
|
.cclk (cclk),
|
|
.cclk_en (cclk_en),
|
|
.reset (reset),
|
|
.ext_yid_k (ext_yid_k[3:0]),
|
|
.ext_xid_k (ext_xid_k[3:0]),
|
|
.who_am_i (who_am_i[3:0]),
|
|
.cfg_multicast_dis (cfg_multicast_dis),
|
|
.access_reg (access_reg),
|
|
.write_reg (write_reg),
|
|
.datamode_reg (datamode_reg[1:0]),
|
|
.ctrlmode_reg (ctrlmode_reg[3:0]),
|
|
.data_reg (data_reg[DW-1:0]),
|
|
.dstaddr_reg (dstaddr_reg[AW-1:0]),
|
|
.srcaddr_reg (srcaddr_reg[AW-1:0]));
|
|
|
|
endmodule // link_txo_mesh_channel
|
|
module link_txo_mesh_launcher(/*AUTOARG*/
|
|
// Outputs
|
|
mesh_wait_int, mesh_req, mesh_rotate_dis, mesh_tran, mesh_frame,
|
|
// Inputs
|
|
cclk, cclk_en, reset, ext_yid_k, ext_xid_k, who_am_i,
|
|
cfg_multicast_dis, access_reg, write_reg, datamode_reg,
|
|
ctrlmode_reg, data_reg, dstaddr_reg, srcaddr_reg, mesh_grant
|
|
);
|
|
|
|
parameter AW = `CFG_AW ;//address width
|
|
parameter DW = `CFG_DW ;//data width
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
|
|
//##########
|
|
//# INPUTS
|
|
//##########
|
|
input cclk; // clock of the score the emesh comes from
|
|
input cclk_en; // clock enable
|
|
input reset;
|
|
input [3:0] ext_yid_k; // external y-id
|
|
input [3:0] ext_xid_k; // external x-id
|
|
input [3:0] who_am_i; // specifies what link is that (north,east,south,west)
|
|
|
|
input cfg_multicast_dis; // control register multicast disable
|
|
|
|
//# input transaction (after mesh interface)
|
|
input access_reg;
|
|
input write_reg;
|
|
input [1:0] datamode_reg;
|
|
input [3:0] ctrlmode_reg;
|
|
input [DW-1:0] data_reg;
|
|
input [AW-1:0] dstaddr_reg;
|
|
input [AW-1:0] srcaddr_reg;
|
|
|
|
//# from the mesh/emesh arbiter
|
|
input mesh_grant;
|
|
|
|
//############
|
|
//# OUTPUTS
|
|
//############
|
|
|
|
//# to the mesh interface
|
|
output mesh_wait_int; // Wait indication
|
|
|
|
//# to the arbiter
|
|
output mesh_req; // Launch request to the arbiter
|
|
output mesh_rotate_dis; // Arbiter's rotate disable
|
|
|
|
//# to the output mux/buffer
|
|
output [2*LW-1:0] mesh_tran; // transaction data
|
|
output mesh_frame; // mesh frame
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
|
|
//#############
|
|
//# REGS
|
|
//#############
|
|
reg [2:0] mesh_pointer;
|
|
|
|
//#############
|
|
//# WIRES
|
|
//#############
|
|
wire multicast_tran_valid; // Valid multicast transaction
|
|
wire multicast_tran; // transaction is of the multicast type
|
|
wire [3:0] ycoord_k_n; // inverted external y coordinates
|
|
wire [3:0] xcoord_k_n; // inverted external x coordinates
|
|
wire [3:0] addr_y; // external y coordinates of the source address
|
|
wire [3:0] addr_x; // external x coordinates of the source address
|
|
wire ext_yzero;
|
|
wire ext_xzero;
|
|
wire [4:0] ext_xdiff;
|
|
wire [4:0] ext_ydiff;
|
|
wire ext_xcarry;
|
|
wire ext_ycarry;
|
|
wire ext_xgt;
|
|
wire ext_xlt;
|
|
wire ext_ygt;
|
|
wire ext_ylt;
|
|
wire route_east;
|
|
wire route_west;
|
|
wire route_north;
|
|
wire route_south;
|
|
wire route_east_normal;
|
|
wire route_west_normal;
|
|
wire route_north_normal;
|
|
wire route_south_normal;
|
|
wire route_east_multicast;
|
|
wire route_west_multicast;
|
|
wire route_north_multicast;
|
|
wire route_south_multicast;
|
|
wire [3:0] route_sides; // where to route {north,east,south,west}
|
|
wire route_out; // Route out of this link was detected
|
|
wire mesh_ack;
|
|
wire mesh_ack_n;
|
|
wire mesh_last_tran;
|
|
wire [2:0] mesh_pointer_incr;
|
|
wire [6:0] launcher_sel;
|
|
wire [14*LW-1:0] mesh_tran_in;
|
|
|
|
//###########################################
|
|
//# Valid MESH-to-LINK transaction detection
|
|
//###########################################
|
|
|
|
//# Multicast transaction detection
|
|
assign multicast_tran = write_reg &
|
|
(ctrlmode_reg[1:0]==2'b11) & ~(datamode_reg[1:0] == 2'b11);
|
|
|
|
//# External source or destination address of the transaction for the comparison
|
|
// assign addr_y[2:0] = multicast_tran ? srcaddr_reg[31:29] : dstaddr_reg[31:29];
|
|
// assign addr_x[2:0] = multicast_tran ? srcaddr_reg[28:26] : dstaddr_reg[28:26];
|
|
assign addr_y[3:0] = multicast_tran ? srcaddr_reg[31:28] : dstaddr_reg[31:28];
|
|
assign addr_x[3:0] = multicast_tran ? srcaddr_reg[25:22] : dstaddr_reg[25:22];
|
|
|
|
//# External address based router
|
|
assign ycoord_k_n[3:0] = ~ext_yid_k[3:0];
|
|
assign xcoord_k_n[3:0] = ~ext_xid_k[3:0];
|
|
|
|
//# External address comparison
|
|
assign ext_yzero = addr_y[3:0]==ext_yid_k[3:0];
|
|
assign ext_xzero = addr_x[3:0]==ext_xid_k[3:0];
|
|
assign ext_ydiff[4:0] = addr_y[3:0] + ycoord_k_n[3:0] + 1'b1 ;
|
|
assign ext_xdiff[4:0] = addr_x[3:0] + xcoord_k_n[3:0] + 1'b1 ;
|
|
assign ext_xcarry = ext_xdiff[4]; //result is positive or zero
|
|
assign ext_ycarry = ext_ydiff[4]; //result is positive or zero
|
|
assign ext_xgt = ext_xcarry & ~ext_xzero;// src/dst X-address is greater than
|
|
assign ext_xlt = ~ext_xcarry; // src/dst X-address is less than
|
|
assign ext_ygt = ext_ycarry & ~ext_yzero;// src/dst Y-address is greater than
|
|
assign ext_ylt = ~ext_ycarry; // src/dst Y-address is less than
|
|
|
|
//# NON-MULTICAST ROUTING
|
|
assign route_east_normal = ext_xgt;
|
|
assign route_west_normal = ext_xlt;
|
|
assign route_south_normal = ext_ygt & ext_xzero;
|
|
assign route_north_normal = ext_ylt & ext_xzero;
|
|
|
|
//# MULTICAST ROUTING
|
|
assign route_east_multicast = (ext_xlt | ext_xzero) & ext_yzero;
|
|
assign route_west_multicast = (ext_xgt | ext_xzero) & ext_yzero;
|
|
assign route_south_multicast = ext_ylt | ext_yzero;
|
|
assign route_north_multicast = ext_ygt | ext_yzero;
|
|
|
|
//# normal-multicast selection
|
|
assign route_east = multicast_tran ? route_east_multicast : route_east_normal;
|
|
assign route_west = multicast_tran ? route_west_multicast : route_west_normal;
|
|
assign route_south = multicast_tran ? route_south_multicast : route_south_normal;
|
|
assign route_north = multicast_tran ? route_north_multicast : route_north_normal;
|
|
|
|
assign route_sides[3:0] = 4'b1111;//{route_north,route_east,route_south,route_west};
|
|
assign route_out = |(who_am_i[3:0] & route_sides[3:0]);
|
|
|
|
//# Request
|
|
assign mesh_req = access_reg & route_out & ((multicast_tran & ~cfg_multicast_dis) |
|
|
~multicast_tran);
|
|
|
|
//# Wait
|
|
assign mesh_ack_n = mesh_req & ~mesh_grant;
|
|
assign mesh_ack = mesh_req & mesh_grant;
|
|
assign mesh_wait_int = mesh_req & ~mesh_last_tran | mesh_ack_n;
|
|
|
|
//############################################
|
|
//# Transaction launcher state machine
|
|
//############################################
|
|
|
|
assign mesh_last_tran = mesh_pointer[2] & mesh_pointer[1] & ~mesh_pointer[0];
|
|
|
|
assign mesh_pointer_incr[2:0] = mesh_last_tran ? 3'b000 :
|
|
(mesh_pointer[2:0] + 3'b001);
|
|
|
|
always @ (posedge cclk or posedge reset)
|
|
if(reset)
|
|
mesh_pointer[2:0] <= 3'b000;
|
|
else if(cclk_en)
|
|
if (mesh_ack)
|
|
mesh_pointer[2:0] <= mesh_pointer_incr[2:0];
|
|
|
|
assign launcher_sel[0] = (mesh_pointer[2:0] == 3'b000);
|
|
assign launcher_sel[1] = (mesh_pointer[2:0] == 3'b001);
|
|
assign launcher_sel[2] = (mesh_pointer[2:0] == 3'b010);
|
|
assign launcher_sel[3] = (mesh_pointer[2:0] == 3'b011);
|
|
assign launcher_sel[4] = (mesh_pointer[2:0] == 3'b100);
|
|
assign launcher_sel[5] = (mesh_pointer[2:0] == 3'b101);
|
|
assign launcher_sel[6] = (mesh_pointer[2:0] == 3'b110);
|
|
|
|
assign mesh_frame = mesh_req & ~mesh_last_tran;
|
|
assign mesh_rotate_dis = |(mesh_pointer[2:0]);
|
|
|
|
//#############################
|
|
//# mesh transaction 7:1 mux
|
|
//#############################
|
|
|
|
//# We are launching in the following order (MSBs first):
|
|
assign mesh_tran_in[14*LW-1:0]={
|
|
srcaddr_reg[7:0],{(LW){1'b0}},
|
|
srcaddr_reg[23:8],
|
|
data_reg[7:0],srcaddr_reg[31:24],
|
|
data_reg[23:8],
|
|
dstaddr_reg[3:0],datamode_reg[1:0],write_reg,access_reg,data_reg[31:24],
|
|
dstaddr_reg[19:4],
|
|
ctrlmode_reg[3:0],dstaddr_reg[31:20]
|
|
};
|
|
|
|
e16_mux7 #(2*LW) mux7(// Outputs
|
|
.out (mesh_tran[2*LW-1:0]),
|
|
// Inputs
|
|
.in0 (mesh_tran_in[2*LW-1:0]), .sel0 (launcher_sel[0]),
|
|
.in1 (mesh_tran_in[4*LW-1:2*LW]), .sel1 (launcher_sel[1]),
|
|
.in2 (mesh_tran_in[6*LW-1:4*LW]), .sel2 (launcher_sel[2]),
|
|
.in3 (mesh_tran_in[8*LW-1:6*LW]), .sel3 (launcher_sel[3]),
|
|
.in4 (mesh_tran_in[10*LW-1:8*LW]), .sel4 (launcher_sel[4]),
|
|
.in5 (mesh_tran_in[12*LW-1:10*LW]), .sel5 (launcher_sel[5]),
|
|
.in6 (mesh_tran_in[14*LW-1:12*LW]), .sel6 (launcher_sel[6]));
|
|
|
|
|
|
endmodule // link_txo_mesh_launcher
|
|
//#############################################################
|
|
//# This block is a transmitter of the read transactions only
|
|
//# Read transactions can be sent out off the chip from
|
|
//# rdmesh only
|
|
//#############################################################
|
|
|
|
module link_txo_rd (/*AUTOARG*/
|
|
// Outputs
|
|
txo_rd_data_even, txo_rd_data_odd, txo_rd_frame,
|
|
txo_rd_launch_req_tlc, txo_rd_rotate_dis, c0_rdmesh_wait_out,
|
|
c1_rdmesh_wait_out, c2_rdmesh_wait_out, c3_rdmesh_wait_out,
|
|
// Inputs
|
|
txo_lclk, reset, txo_rd_wait, txo_rd_wait_int, c0_clk_in,
|
|
c1_clk_in, c2_clk_in, c3_clk_in, c0_rdmesh_tran_in,
|
|
c0_rdmesh_frame_in, c1_rdmesh_tran_in, c1_rdmesh_frame_in,
|
|
c2_rdmesh_tran_in, c2_rdmesh_frame_in, c3_rdmesh_tran_in,
|
|
c3_rdmesh_frame_in
|
|
);
|
|
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
|
|
// #########
|
|
// # Inputs
|
|
// #########
|
|
|
|
input txo_lclk; //transmit clock to be used internally
|
|
input reset;
|
|
|
|
// # from io
|
|
input txo_rd_wait; // Wait from the receiver
|
|
input txo_rd_wait_int; //wait indicator for read transactions
|
|
// # Clocks
|
|
input c0_clk_in; //clock of the core
|
|
input c1_clk_in; //clock of the core
|
|
input c2_clk_in; //clock of the core
|
|
input c3_clk_in; //clock of the core
|
|
|
|
// # RDMESH
|
|
input [2*LW-1:0] c0_rdmesh_tran_in; // serialized transaction
|
|
input c0_rdmesh_frame_in; // transaction frame
|
|
input [2*LW-1:0] c1_rdmesh_tran_in; // serialized transaction
|
|
input c1_rdmesh_frame_in; // transaction frame
|
|
input [2*LW-1:0] c2_rdmesh_tran_in; // serialized transaction
|
|
input c2_rdmesh_frame_in; // transaction frame
|
|
input [2*LW-1:0] c3_rdmesh_tran_in; // serialized transaction
|
|
input c3_rdmesh_frame_in; // transaction frame
|
|
|
|
// ##############
|
|
// # Outputs
|
|
// ##############
|
|
|
|
// to the txo_interface
|
|
output [LW-1:0] txo_rd_data_even; //Even byte word
|
|
output [LW-1:0] txo_rd_data_odd; //Odd byte word
|
|
output txo_rd_frame; //indicates new transmission
|
|
output txo_rd_launch_req_tlc;
|
|
output txo_rd_rotate_dis;
|
|
|
|
output c0_rdmesh_wait_out; // wait to the rdmesh
|
|
output c1_rdmesh_wait_out; // wait to the rdmesh
|
|
output c2_rdmesh_wait_out; // wait to the rdmesh
|
|
output c3_rdmesh_wait_out; // wait to the rdmesh
|
|
|
|
/*AUTOINPUT*/
|
|
/*AUTOWIRE*/
|
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
|
wire [LW-1:0] c0_tran_byte_even_tlc; // From c0_link_txo_channel of link_txo_channel.v
|
|
wire [LW-1:0] c0_tran_byte_odd_tlc; // From c0_link_txo_channel of link_txo_channel.v
|
|
wire c0_tran_frame_tlc; // From c0_link_txo_channel of link_txo_channel.v
|
|
wire c0_txo_launch_ack_tlc; // From link_txo_arbiter of link_txo_arbiter.v
|
|
wire c0_txo_launch_req_tlc; // From c0_link_txo_channel of link_txo_channel.v
|
|
wire c0_txo_rotate_dis; // From c0_link_txo_channel of link_txo_channel.v
|
|
wire [LW-1:0] c1_tran_byte_even_tlc; // From c1_link_txo_channel of link_txo_channel.v
|
|
wire [LW-1:0] c1_tran_byte_odd_tlc; // From c1_link_txo_channel of link_txo_channel.v
|
|
wire c1_tran_frame_tlc; // From c1_link_txo_channel of link_txo_channel.v
|
|
wire c1_txo_launch_ack_tlc; // From link_txo_arbiter of link_txo_arbiter.v
|
|
wire c1_txo_launch_req_tlc; // From c1_link_txo_channel of link_txo_channel.v
|
|
wire c1_txo_rotate_dis; // From c1_link_txo_channel of link_txo_channel.v
|
|
wire [LW-1:0] c2_tran_byte_even_tlc; // From c2_link_txo_channel of link_txo_channel.v
|
|
wire [LW-1:0] c2_tran_byte_odd_tlc; // From c2_link_txo_channel of link_txo_channel.v
|
|
wire c2_tran_frame_tlc; // From c2_link_txo_channel of link_txo_channel.v
|
|
wire c2_txo_launch_ack_tlc; // From link_txo_arbiter of link_txo_arbiter.v
|
|
wire c2_txo_launch_req_tlc; // From c2_link_txo_channel of link_txo_channel.v
|
|
wire c2_txo_rotate_dis; // From c2_link_txo_channel of link_txo_channel.v
|
|
wire [LW-1:0] c3_tran_byte_even_tlc; // From c3_link_txo_channel of link_txo_channel.v
|
|
wire [LW-1:0] c3_tran_byte_odd_tlc; // From c3_link_txo_channel of link_txo_channel.v
|
|
wire c3_tran_frame_tlc; // From c3_link_txo_channel of link_txo_channel.v
|
|
wire c3_txo_launch_ack_tlc; // From link_txo_arbiter of link_txo_arbiter.v
|
|
wire c3_txo_launch_req_tlc; // From c3_link_txo_channel of link_txo_channel.v
|
|
wire c3_txo_rotate_dis; // From c3_link_txo_channel of link_txo_channel.v
|
|
// End of automatics
|
|
|
|
// ##########
|
|
// # WIRES
|
|
// ##########
|
|
|
|
wire [1:0] c0_txo_cid;//channel 0 ID
|
|
wire [1:0] c1_txo_cid;//channel 1 ID
|
|
wire [1:0] c2_txo_cid;//channel 2 ID
|
|
wire [1:0] c3_txo_cid;//channel 3 ID
|
|
|
|
// ################################
|
|
// # Transmit buffer instantiation
|
|
// ################################
|
|
|
|
/*link_txo_buffer AUTO_TEMPLATE(
|
|
.txo_data_even (txo_rd_data_even[]),
|
|
.txo_data_odd (txo_rd_data_odd[]),
|
|
.txo_frame (txo_rd_frame),
|
|
);
|
|
*/
|
|
link_txo_buffer link_txo_buffer(/*AUTOINST*/
|
|
// Outputs
|
|
.txo_data_even (txo_rd_data_even[LW-1:0]), // Templated
|
|
.txo_data_odd (txo_rd_data_odd[LW-1:0]), // Templated
|
|
.txo_frame (txo_rd_frame), // Templated
|
|
// Inputs
|
|
.c0_tran_frame_tlc (c0_tran_frame_tlc),
|
|
.c0_tran_byte_even_tlc(c0_tran_byte_even_tlc[LW-1:0]),
|
|
.c0_tran_byte_odd_tlc(c0_tran_byte_odd_tlc[LW-1:0]),
|
|
.c1_tran_frame_tlc (c1_tran_frame_tlc),
|
|
.c1_tran_byte_even_tlc(c1_tran_byte_even_tlc[LW-1:0]),
|
|
.c1_tran_byte_odd_tlc(c1_tran_byte_odd_tlc[LW-1:0]),
|
|
.c2_tran_frame_tlc (c2_tran_frame_tlc),
|
|
.c2_tran_byte_even_tlc(c2_tran_byte_even_tlc[LW-1:0]),
|
|
.c2_tran_byte_odd_tlc(c2_tran_byte_odd_tlc[LW-1:0]),
|
|
.c3_tran_frame_tlc (c3_tran_frame_tlc),
|
|
.c3_tran_byte_even_tlc(c3_tran_byte_even_tlc[LW-1:0]),
|
|
.c3_tran_byte_odd_tlc(c3_tran_byte_odd_tlc[LW-1:0]));
|
|
|
|
// #########################
|
|
// # Arbiter instantiation
|
|
// #########################
|
|
|
|
/*link_txo_arbiter AUTO_TEMPLATE(
|
|
.txo_wait (txo_rd_wait),
|
|
.txo_wait_int (txo_rd_wait_int),
|
|
.txo_launch_req_tlc (txo_rd_launch_req_tlc),
|
|
.txo_rotate_dis_tlc (txo_rd_rotate_dis),
|
|
);
|
|
*/
|
|
link_txo_arbiter link_txo_arbiter (/*AUTOINST*/
|
|
// Outputs
|
|
.txo_launch_req_tlc(txo_rd_launch_req_tlc), // Templated
|
|
.txo_rotate_dis_tlc(txo_rd_rotate_dis), // Templated
|
|
.c0_txo_launch_ack_tlc(c0_txo_launch_ack_tlc),
|
|
.c1_txo_launch_ack_tlc(c1_txo_launch_ack_tlc),
|
|
.c2_txo_launch_ack_tlc(c2_txo_launch_ack_tlc),
|
|
.c3_txo_launch_ack_tlc(c3_txo_launch_ack_tlc),
|
|
// Inputs
|
|
.txo_lclk (txo_lclk),
|
|
.reset (reset),
|
|
.txo_wait (txo_rd_wait), // Templated
|
|
.txo_wait_int (txo_rd_wait_int), // Templated
|
|
.c0_txo_launch_req_tlc(c0_txo_launch_req_tlc),
|
|
.c0_txo_rotate_dis(c0_txo_rotate_dis),
|
|
.c1_txo_launch_req_tlc(c1_txo_launch_req_tlc),
|
|
.c1_txo_rotate_dis(c1_txo_rotate_dis),
|
|
.c2_txo_launch_req_tlc(c2_txo_launch_req_tlc),
|
|
.c2_txo_rotate_dis(c2_txo_rotate_dis),
|
|
.c3_txo_launch_req_tlc(c3_txo_launch_req_tlc),
|
|
.c3_txo_rotate_dis(c3_txo_rotate_dis));
|
|
|
|
// #########################
|
|
// # Channels instantiation
|
|
// #########################
|
|
|
|
/*link_txo_channel AUTO_TEMPLATE (
|
|
.cclk (@"(substring vl-cell-name 0 2)"_clk_in),
|
|
.cclk_en (1'b1),
|
|
.txo_rd (1'b1),
|
|
.txo_lclk (txo_lclk),
|
|
.reset (reset),
|
|
.cfg_burst_dis (1'b1),
|
|
.emesh_\(.*\) (@"(substring vl-cell-name 0 2)"_rdmesh_\1[]),
|
|
.\(.*\) (@"(substring vl-cell-name 0 2)"_\1[]),
|
|
);
|
|
*/
|
|
|
|
//# channel 0
|
|
link_txo_channel #(.FAD(3)) c0_link_txo_channel (/*AUTOINST*/
|
|
// Outputs
|
|
.emesh_wait_out (c0_rdmesh_wait_out), // Templated
|
|
.txo_launch_req_tlc (c0_txo_launch_req_tlc), // Templated
|
|
.txo_rotate_dis (c0_txo_rotate_dis), // Templated
|
|
.tran_frame_tlc (c0_tran_frame_tlc), // Templated
|
|
.tran_byte_even_tlc (c0_tran_byte_even_tlc[LW-1:0]), // Templated
|
|
.tran_byte_odd_tlc (c0_tran_byte_odd_tlc[LW-1:0]), // Templated
|
|
// Inputs
|
|
.cclk (c0_clk_in), // Templated
|
|
.cclk_en (1'b1), // Templated
|
|
.txo_lclk (txo_lclk), // Templated
|
|
.reset (reset), // Templated
|
|
.txo_rd (1'b1), // Templated
|
|
.txo_cid (c0_txo_cid[1:0]), // Templated
|
|
.cfg_burst_dis (1'b1), // Templated
|
|
.emesh_tran_in (c0_rdmesh_tran_in[2*LW-1:0]), // Templated
|
|
.emesh_frame_in (c0_rdmesh_frame_in), // Templated
|
|
.txo_launch_ack_tlc (c0_txo_launch_ack_tlc)); // Templated
|
|
|
|
//# channel 1
|
|
link_txo_channel #(.FAD(3)) c1_link_txo_channel (/*AUTOINST*/
|
|
// Outputs
|
|
.emesh_wait_out (c1_rdmesh_wait_out), // Templated
|
|
.txo_launch_req_tlc (c1_txo_launch_req_tlc), // Templated
|
|
.txo_rotate_dis (c1_txo_rotate_dis), // Templated
|
|
.tran_frame_tlc (c1_tran_frame_tlc), // Templated
|
|
.tran_byte_even_tlc (c1_tran_byte_even_tlc[LW-1:0]), // Templated
|
|
.tran_byte_odd_tlc (c1_tran_byte_odd_tlc[LW-1:0]), // Templated
|
|
// Inputs
|
|
.cclk (c1_clk_in), // Templated
|
|
.cclk_en (1'b1), // Templated
|
|
.txo_lclk (txo_lclk), // Templated
|
|
.reset (reset), // Templated
|
|
.txo_rd (1'b1), // Templated
|
|
.txo_cid (c1_txo_cid[1:0]), // Templated
|
|
.cfg_burst_dis (1'b1), // Templated
|
|
.emesh_tran_in (c1_rdmesh_tran_in[2*LW-1:0]), // Templated
|
|
.emesh_frame_in (c1_rdmesh_frame_in), // Templated
|
|
.txo_launch_ack_tlc (c1_txo_launch_ack_tlc)); // Templated
|
|
|
|
//# channel 2
|
|
link_txo_channel #(.FAD(3)) c2_link_txo_channel (/*AUTOINST*/
|
|
// Outputs
|
|
.emesh_wait_out (c2_rdmesh_wait_out), // Templated
|
|
.txo_launch_req_tlc (c2_txo_launch_req_tlc), // Templated
|
|
.txo_rotate_dis (c2_txo_rotate_dis), // Templated
|
|
.tran_frame_tlc (c2_tran_frame_tlc), // Templated
|
|
.tran_byte_even_tlc (c2_tran_byte_even_tlc[LW-1:0]), // Templated
|
|
.tran_byte_odd_tlc (c2_tran_byte_odd_tlc[LW-1:0]), // Templated
|
|
// Inputs
|
|
.cclk (c2_clk_in), // Templated
|
|
.cclk_en (1'b1), // Templated
|
|
.txo_lclk (txo_lclk), // Templated
|
|
.reset (reset), // Templated
|
|
.txo_rd (1'b1), // Templated
|
|
.txo_cid (c2_txo_cid[1:0]), // Templated
|
|
.cfg_burst_dis (1'b1), // Templated
|
|
.emesh_tran_in (c2_rdmesh_tran_in[2*LW-1:0]), // Templated
|
|
.emesh_frame_in (c2_rdmesh_frame_in), // Templated
|
|
.txo_launch_ack_tlc (c2_txo_launch_ack_tlc)); // Templated
|
|
|
|
//# channel 3
|
|
link_txo_channel #(.FAD(3)) c3_link_txo_channel (/*AUTOINST*/
|
|
// Outputs
|
|
.emesh_wait_out (c3_rdmesh_wait_out), // Templated
|
|
.txo_launch_req_tlc (c3_txo_launch_req_tlc), // Templated
|
|
.txo_rotate_dis (c3_txo_rotate_dis), // Templated
|
|
.tran_frame_tlc (c3_tran_frame_tlc), // Templated
|
|
.tran_byte_even_tlc (c3_tran_byte_even_tlc[LW-1:0]), // Templated
|
|
.tran_byte_odd_tlc (c3_tran_byte_odd_tlc[LW-1:0]), // Templated
|
|
// Inputs
|
|
.cclk (c3_clk_in), // Templated
|
|
.cclk_en (1'b1), // Templated
|
|
.txo_lclk (txo_lclk), // Templated
|
|
.reset (reset), // Templated
|
|
.txo_rd (1'b1), // Templated
|
|
.txo_cid (c3_txo_cid[1:0]), // Templated
|
|
.cfg_burst_dis (1'b1), // Templated
|
|
.emesh_tran_in (c3_rdmesh_tran_in[2*LW-1:0]), // Templated
|
|
.emesh_frame_in (c3_rdmesh_frame_in), // Templated
|
|
.txo_launch_ack_tlc (c3_txo_launch_ack_tlc)); // Templated
|
|
|
|
endmodule // link_txo_rd
|
|
//#############################################################
|
|
//# This block is a transmitter of the write transactions only
|
|
//# Write transactions can be sent out off the chip from
|
|
//# emesh and mesh but not from rdmesh
|
|
//#############################################################
|
|
|
|
module link_txo_wr (/*AUTOARG*/
|
|
// Outputs
|
|
txo_wr_data_even, txo_wr_data_odd, txo_wr_frame,
|
|
txo_wr_launch_req_tlc, txo_wr_rotate_dis, c0_emesh_wait_out,
|
|
c1_emesh_wait_out, c2_emesh_wait_out, c3_emesh_wait_out,
|
|
c0_mesh_wait_out, c3_mesh_wait_out,
|
|
// Inputs
|
|
txo_lclk, reset, ext_yid_k, ext_xid_k, who_am_i, cfg_burst_dis,
|
|
cfg_multicast_dis, txo_wr_wait, txo_wr_wait_int, c0_clk_in,
|
|
c1_clk_in, c2_clk_in, c3_clk_in, c0_emesh_tran_in,
|
|
c0_emesh_frame_in, c1_emesh_tran_in, c1_emesh_frame_in,
|
|
c2_emesh_tran_in, c2_emesh_frame_in, c3_emesh_tran_in,
|
|
c3_emesh_frame_in, c0_mesh_access_in, c0_mesh_write_in,
|
|
c0_mesh_dstaddr_in, c0_mesh_srcaddr_in, c0_mesh_data_in,
|
|
c0_mesh_datamode_in, c0_mesh_ctrlmode_in, c3_mesh_access_in,
|
|
c3_mesh_write_in, c3_mesh_dstaddr_in, c3_mesh_srcaddr_in,
|
|
c3_mesh_data_in, c3_mesh_datamode_in, c3_mesh_ctrlmode_in,
|
|
c1_tran_byte_even_tlc, c1_tran_byte_odd_tlc, c1_tran_frame_tlc,
|
|
c2_tran_byte_even_tlc, c2_tran_byte_odd_tlc, c2_tran_frame_tlc
|
|
);
|
|
|
|
parameter LW = `CFG_LW ;//lvds tranceiver pairs per side
|
|
parameter AW = `CFG_AW ;//address width
|
|
parameter DW = `CFG_DW ;//data width
|
|
|
|
// #########
|
|
// # Inputs
|
|
// #########
|
|
|
|
input txo_lclk; //transmit clock to be used internally
|
|
input reset;
|
|
input [3:0] ext_yid_k; //external y-id
|
|
input [3:0] ext_xid_k; //external x-id
|
|
input [3:0] who_am_i; //specifies what link is that (north,east,south,west)
|
|
input cfg_burst_dis; //control register bursting disable
|
|
input cfg_multicast_dis;//control register multicast disable
|
|
// # from io
|
|
input txo_wr_wait; // Wait from the receiver
|
|
input txo_wr_wait_int; // Wait from the txo_interface (have to stall immediately)
|
|
// # Clocks
|
|
input c0_clk_in; //clock of the core
|
|
input c1_clk_in; //clock of the core
|
|
input c2_clk_in; //clock of the core
|
|
input c3_clk_in; //clock of the core
|
|
|
|
// # EMESH
|
|
input [2*LW-1:0] c0_emesh_tran_in; // serialized transaction
|
|
input c0_emesh_frame_in; // transaction frame
|
|
input [2*LW-1:0] c1_emesh_tran_in; // serialized transaction
|
|
input c1_emesh_frame_in; // transaction frame
|
|
input [2*LW-1:0] c2_emesh_tran_in; // serialized transaction
|
|
input c2_emesh_frame_in; // transaction frame
|
|
input [2*LW-1:0] c3_emesh_tran_in; // serialized transaction
|
|
input c3_emesh_frame_in; // transaction frame
|
|
|
|
// # MESH
|
|
// # core0 (external corners and multicast)
|
|
input c0_mesh_access_in; // access control from the mesh
|
|
input c0_mesh_write_in; // write control from the mesh
|
|
input [AW-1:0] c0_mesh_dstaddr_in; // destination address from the mesh
|
|
input [AW-1:0] c0_mesh_srcaddr_in; // source address from the mesh
|
|
input [DW-1:0] c0_mesh_data_in; // data from the mesh
|
|
input [1:0] c0_mesh_datamode_in;// data mode from the mesh
|
|
input [3:0] c0_mesh_ctrlmode_in;// ctrl mode from the mesh
|
|
// # core3 (external corners only)
|
|
input c3_mesh_access_in; // access control from the mesh
|
|
input c3_mesh_write_in; // write control from the mesh
|
|
input [AW-1:0] c3_mesh_dstaddr_in; // destination address from the mesh
|
|
input [AW-1:0] c3_mesh_srcaddr_in; // source address from the mesh
|
|
input [DW-1:0] c3_mesh_data_in; // data from the mesh
|
|
input [1:0] c3_mesh_datamode_in;// data mode from the mesh
|
|
input [3:0] c3_mesh_ctrlmode_in;// ctrl mode from the mesh
|
|
|
|
// ##############
|
|
// # Outputs
|
|
// ##############
|
|
|
|
// to the txo_interface
|
|
output [LW-1:0] txo_wr_data_even; //Even byte word
|
|
output [LW-1:0] txo_wr_data_odd; //Odd byte word
|
|
output txo_wr_frame; //indicates new transmission
|
|
output txo_wr_launch_req_tlc;
|
|
output txo_wr_rotate_dis;
|
|
|
|
output c0_emesh_wait_out; //wait to the emesh
|
|
output c1_emesh_wait_out; //wait to the emesh
|
|
output c2_emesh_wait_out; //wait to the emesh
|
|
output c3_emesh_wait_out; //wait to the emesh
|
|
|
|
output c0_mesh_wait_out; //wait to the mesh
|
|
output c3_mesh_wait_out; //wait to the mesh
|
|
|
|
/*AUTOINPUT*/
|
|
// Beginning of automatic inputs (from unused autoinst inputs)
|
|
input [LW-1:0] c1_tran_byte_even_tlc; // To link_txo_buffer of link_txo_buffer.v
|
|
input [LW-1:0] c1_tran_byte_odd_tlc; // To link_txo_buffer of link_txo_buffer.v
|
|
input c1_tran_frame_tlc; // To link_txo_buffer of link_txo_buffer.v
|
|
input [LW-1:0] c2_tran_byte_even_tlc; // To link_txo_buffer of link_txo_buffer.v
|
|
input [LW-1:0] c2_tran_byte_odd_tlc; // To link_txo_buffer of link_txo_buffer.v
|
|
input c2_tran_frame_tlc; // To link_txo_buffer of link_txo_buffer.v
|
|
// End of automatics
|
|
/*AUTOWIRE*/
|
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
|
wire [LW-1:0] c0_tran_byte_even_tlc; // From c0_link_txo_mesh_channel of link_txo_mesh_channel.v
|
|
wire [LW-1:0] c0_tran_byte_odd_tlc; // From c0_link_txo_mesh_channel of link_txo_mesh_channel.v
|
|
wire c0_tran_frame_tlc; // From c0_link_txo_mesh_channel of link_txo_mesh_channel.v
|
|
wire c0_txo_launch_ack_tlc; // From link_txo_arbiter of link_txo_arbiter.v
|
|
wire c0_txo_launch_req_tlc; // From c0_link_txo_mesh_channel of link_txo_mesh_channel.v
|
|
wire c0_txo_rotate_dis; // From c0_link_txo_mesh_channel of link_txo_mesh_channel.v
|
|
wire c1_txo_launch_ack_tlc; // From link_txo_arbiter of link_txo_arbiter.v
|
|
wire c2_txo_launch_ack_tlc; // From link_txo_arbiter of link_txo_arbiter.v
|
|
wire [LW-1:0] c3_tran_byte_even_tlc; // From c3_link_txo_mesh_channel of link_txo_mesh_channel.v
|
|
wire [LW-1:0] c3_tran_byte_odd_tlc; // From c3_link_txo_mesh_channel of link_txo_mesh_channel.v
|
|
wire c3_tran_frame_tlc; // From c3_link_txo_mesh_channel of link_txo_mesh_channel.v
|
|
wire c3_txo_launch_ack_tlc; // From link_txo_arbiter of link_txo_arbiter.v
|
|
wire c3_txo_launch_req_tlc; // From c3_link_txo_mesh_channel of link_txo_mesh_channel.v
|
|
wire c3_txo_rotate_dis; // From c3_link_txo_mesh_channel of link_txo_mesh_channel.v
|
|
// End of automatics
|
|
|
|
// ##########
|
|
// # WIRES
|
|
// ##########
|
|
|
|
wire [1:0] c0_txo_cid;//channel 0 ID
|
|
wire [1:0] c1_txo_cid;//channel 1 ID
|
|
wire [1:0] c2_txo_cid;//channel 2 ID
|
|
wire [1:0] c3_txo_cid;//channel 3 ID
|
|
|
|
// #####################################
|
|
// # Transmitter channels instantiation
|
|
// #####################################
|
|
|
|
assign c0_txo_cid[1:0] = 2'b00;
|
|
assign c1_txo_cid[1:0] = 2'b01;
|
|
assign c2_txo_cid[1:0] = 2'b10;
|
|
assign c3_txo_cid[1:0] = 2'b11;
|
|
|
|
// ################################
|
|
// # Transmit buffer instantiation
|
|
// ################################
|
|
|
|
/*link_txo_buffer AUTO_TEMPLATE(
|
|
.txo_data_even (txo_wr_data_even[]),
|
|
.txo_data_odd (txo_wr_data_odd[]),
|
|
.txo_frame (txo_wr_frame),
|
|
);
|
|
*/
|
|
link_txo_buffer link_txo_buffer(/*AUTOINST*/
|
|
// Outputs
|
|
.txo_data_even (txo_wr_data_even[LW-1:0]), // Templated
|
|
.txo_data_odd (txo_wr_data_odd[LW-1:0]), // Templated
|
|
.txo_frame (txo_wr_frame), // Templated
|
|
// Inputs
|
|
.c0_tran_frame_tlc (c0_tran_frame_tlc),
|
|
.c0_tran_byte_even_tlc(c0_tran_byte_even_tlc[LW-1:0]),
|
|
.c0_tran_byte_odd_tlc(c0_tran_byte_odd_tlc[LW-1:0]),
|
|
.c1_tran_frame_tlc (c1_tran_frame_tlc),
|
|
.c1_tran_byte_even_tlc(c1_tran_byte_even_tlc[LW-1:0]),
|
|
.c1_tran_byte_odd_tlc(c1_tran_byte_odd_tlc[LW-1:0]),
|
|
.c2_tran_frame_tlc (c2_tran_frame_tlc),
|
|
.c2_tran_byte_even_tlc(c2_tran_byte_even_tlc[LW-1:0]),
|
|
.c2_tran_byte_odd_tlc(c2_tran_byte_odd_tlc[LW-1:0]),
|
|
.c3_tran_frame_tlc (c3_tran_frame_tlc),
|
|
.c3_tran_byte_even_tlc(c3_tran_byte_even_tlc[LW-1:0]),
|
|
.c3_tran_byte_odd_tlc(c3_tran_byte_odd_tlc[LW-1:0]));
|
|
|
|
// #########################
|
|
// # Arbiter instantiation
|
|
// #########################
|
|
|
|
/*link_txo_arbiter AUTO_TEMPLATE(
|
|
.txo_wait (txo_wr_wait),
|
|
.txo_wait_int (txo_wr_wait_int),
|
|
.txo_launch_req_tlc (txo_wr_launch_req_tlc),
|
|
.txo_rotate_dis_tlc (txo_wr_rotate_dis),
|
|
);
|
|
*/
|
|
link_txo_arbiter link_txo_arbiter (.c1_txo_launch_req_tlc(1'b0),
|
|
.c1_txo_rotate_dis(1'b0),
|
|
.c2_txo_launch_req_tlc(1'b0),
|
|
.c2_txo_rotate_dis(1'b0),
|
|
.c3_txo_launch_req_tlc(1'b0),
|
|
.c3_txo_rotate_dis(1'b0),
|
|
/*AUTOINST*/
|
|
// Outputs
|
|
.txo_launch_req_tlc(txo_wr_launch_req_tlc), // Templated
|
|
.txo_rotate_dis_tlc(txo_wr_rotate_dis), // Templated
|
|
.c0_txo_launch_ack_tlc(c0_txo_launch_ack_tlc),
|
|
.c1_txo_launch_ack_tlc(c1_txo_launch_ack_tlc),
|
|
.c2_txo_launch_ack_tlc(c2_txo_launch_ack_tlc),
|
|
.c3_txo_launch_ack_tlc(c3_txo_launch_ack_tlc),
|
|
// Inputs
|
|
.txo_lclk (txo_lclk),
|
|
.reset (reset),
|
|
.txo_wait (txo_wr_wait), // Templated
|
|
.txo_wait_int (txo_wr_wait_int), // Templated
|
|
.c0_txo_launch_req_tlc(c0_txo_launch_req_tlc),
|
|
.c0_txo_rotate_dis(c0_txo_rotate_dis));
|
|
|
|
// #########################
|
|
// # Channels instantiation
|
|
// #########################
|
|
|
|
/*link_txo_mesh_channel AUTO_TEMPLATE (
|
|
.cclk (@"(substring vl-cell-name 0 2)"_clk_in),
|
|
.cclk_en (1'b1),
|
|
.txo_rd (1'b0),
|
|
.txo_lclk (txo_lclk),
|
|
.reset (reset),
|
|
.cfg_burst_dis (cfg_burst_dis),
|
|
.txo_rotate_dis_tlc (@"(substring vl-cell-name 0 2)"_txo_rotate_dis),
|
|
.emesh_\(.*\) (@"(substring vl-cell-name 0 2)"_emesh_\1[]),
|
|
.\(.*\) (@"(substring vl-cell-name 0 2)"_\1[]),
|
|
.ext_yid_k (ext_yid_k[]),
|
|
.ext_xid_k (ext_xid_k[]),
|
|
.who_am_i (who_am_i[]),
|
|
);
|
|
*/
|
|
|
|
//# channel 0 (emesh + mesh for external corners + mesh for multicast)
|
|
link_txo_mesh_channel c0_link_txo_mesh_channel(.cfg_multicast_dis (cfg_multicast_dis),
|
|
/*AUTOINST*/
|
|
// Outputs
|
|
.emesh_wait_out (c0_emesh_wait_out), // Templated
|
|
.mesh_wait_out (c0_mesh_wait_out), // Templated
|
|
.txo_launch_req_tlc (c0_txo_launch_req_tlc), // Templated
|
|
.txo_rotate_dis_tlc (c0_txo_rotate_dis), // Templated
|
|
.tran_frame_tlc (c0_tran_frame_tlc), // Templated
|
|
.tran_byte_even_tlc (c0_tran_byte_even_tlc[LW-1:0]), // Templated
|
|
.tran_byte_odd_tlc (c0_tran_byte_odd_tlc[LW-1:0]), // Templated
|
|
// Inputs
|
|
.cclk (c0_clk_in), // Templated
|
|
.cclk_en (1'b1), // Templated
|
|
.txo_lclk (txo_lclk), // Templated
|
|
.reset (reset), // Templated
|
|
.ext_yid_k (ext_yid_k[3:0]), // Templated
|
|
.ext_xid_k (ext_xid_k[3:0]), // Templated
|
|
.who_am_i (who_am_i[3:0]), // Templated
|
|
.txo_rd (1'b0), // Templated
|
|
.txo_cid (c0_txo_cid[1:0]), // Templated
|
|
.cfg_burst_dis (cfg_burst_dis), // Templated
|
|
.emesh_tran_in (c0_emesh_tran_in[2*LW-1:0]), // Templated
|
|
.emesh_frame_in (c0_emesh_frame_in), // Templated
|
|
.mesh_access_in (c0_mesh_access_in), // Templated
|
|
.mesh_write_in (c0_mesh_write_in), // Templated
|
|
.mesh_dstaddr_in (c0_mesh_dstaddr_in[AW-1:0]), // Templated
|
|
.mesh_srcaddr_in (c0_mesh_srcaddr_in[AW-1:0]), // Templated
|
|
.mesh_data_in (c0_mesh_data_in[DW-1:0]), // Templated
|
|
.mesh_datamode_in (c0_mesh_datamode_in[1:0]), // Templated
|
|
.mesh_ctrlmode_in (c0_mesh_ctrlmode_in[3:0]), // Templated
|
|
.txo_launch_ack_tlc (c0_txo_launch_ack_tlc)); // Templated
|
|
|
|
//# channel 3 (emesh + mesh for external corners)
|
|
link_txo_mesh_channel c3_link_txo_mesh_channel(.cfg_multicast_dis (1'b1),
|
|
/*AUTOINST*/
|
|
// Outputs
|
|
.emesh_wait_out (c3_emesh_wait_out), // Templated
|
|
.mesh_wait_out (c3_mesh_wait_out), // Templated
|
|
.txo_launch_req_tlc (c3_txo_launch_req_tlc), // Templated
|
|
.txo_rotate_dis_tlc (c3_txo_rotate_dis), // Templated
|
|
.tran_frame_tlc (c3_tran_frame_tlc), // Templated
|
|
.tran_byte_even_tlc (c3_tran_byte_even_tlc[LW-1:0]), // Templated
|
|
.tran_byte_odd_tlc (c3_tran_byte_odd_tlc[LW-1:0]), // Templated
|
|
// Inputs
|
|
.cclk (c3_clk_in), // Templated
|
|
.cclk_en (1'b1), // Templated
|
|
.txo_lclk (txo_lclk), // Templated
|
|
.reset (reset), // Templated
|
|
.ext_yid_k (ext_yid_k[3:0]), // Templated
|
|
.ext_xid_k (ext_xid_k[3:0]), // Templated
|
|
.who_am_i (who_am_i[3:0]), // Templated
|
|
.txo_rd (1'b0), // Templated
|
|
.txo_cid (c3_txo_cid[1:0]), // Templated
|
|
.cfg_burst_dis (cfg_burst_dis), // Templated
|
|
.emesh_tran_in (c3_emesh_tran_in[2*LW-1:0]), // Templated
|
|
.emesh_frame_in (c3_emesh_frame_in), // Templated
|
|
.mesh_access_in (c3_mesh_access_in), // Templated
|
|
.mesh_write_in (c3_mesh_write_in), // Templated
|
|
.mesh_dstaddr_in (c3_mesh_dstaddr_in[AW-1:0]), // Templated
|
|
.mesh_srcaddr_in (c3_mesh_srcaddr_in[AW-1:0]), // Templated
|
|
.mesh_data_in (c3_mesh_data_in[DW-1:0]), // Templated
|
|
.mesh_datamode_in (c3_mesh_datamode_in[1:0]), // Templated
|
|
.mesh_ctrlmode_in (c3_mesh_ctrlmode_in[3:0]), // Templated
|
|
.txo_launch_ack_tlc (c3_txo_launch_ack_tlc)); // Templated
|
|
|
|
|
|
endmodule // link_txo_wr
|
|
module _MAGMA_CELL_FF_ (DATA, CLOCK, CLEAR, PRESET, SLAVE_CLOCK, OUT);
|
|
|
|
input DATA;
|
|
input CLOCK;
|
|
input CLEAR;
|
|
input PRESET;
|
|
input SLAVE_CLOCK;
|
|
output OUT;
|
|
reg OUT;
|
|
|
|
// synopsys one_hot "PRESET, CLEAR"
|
|
always @(posedge CLOCK or posedge PRESET or posedge CLEAR)
|
|
if (CLEAR)
|
|
OUT <= 1'b0;
|
|
else
|
|
if (PRESET)
|
|
OUT <= 1'b1;
|
|
else
|
|
OUT <= DATA;
|
|
endmodule
|
|
|
|
// Entity:dffnq Model:DFFNQX3A12TR Library:cmos10sf_5_20_02_scadv12
|
|
module DFFNQX3A12TR (CKN, D, Q);
|
|
input CKN, D;
|
|
output Q;
|
|
supply0 N7;
|
|
_MAGMA_CELL_FF_ C1 (.DATA(D), .CLOCK(CKN__br_in_not), .CLEAR(N7), .PRESET(N7), .SLAVE_CLOCK(N7), .OUT(Q));
|
|
not (CKN__br_in_not, CKN);
|
|
endmodule // DFFNQX3A12TR
|
|
|
|
module DFFQX4A12TR (CK, D, Q);
|
|
input CK, D;
|
|
output Q;
|
|
supply0 N6;
|
|
_MAGMA_CELL_FF_ C1 (.DATA(D), .CLOCK(CK), .CLEAR(N6), .PRESET(N6), .SLAVE_CLOCK(N6), .OUT(Q));
|
|
endmodule
|
|
|
|
module MX2X4A12TR (A, B, S0, Y);
|
|
input A, B, S0;
|
|
output Y;
|
|
wire N3, N6;
|
|
and C1 (N3, S0, B);
|
|
and C3 (N6, S0__br_in_not, A);
|
|
not (S0__br_in_not, S0);
|
|
or C4 (Y, N3, N6);
|
|
endmodule
|
|
|
|
|
|
|
|
|