mirror of
https://github.com/aolofsson/oh.git
synced 2025-01-21 22:12:54 +08:00
d541a261a6
This is pretty big, wonder if anybody will notice? Why am I doing this? Because the elink has been haunting us for years. This way we will finally have a "golden reference" simulator model for those who insist on designing their own elink protocol (aginst my recommendation). This is equivalent to having a "bfm-bus functional model" for AXI. The spec is nice, but it's always up for interpretation. We have had some issues with documenting the protocol corretly. While we will fix the documentation, please note that the source code and design verification environment will always be the golden version. This is after all "the silicon". For me and everyone else, it becomes part of the open source design verification environment to test the elink. Enjoy....
6042 lines
230 KiB
Verilog
6042 lines
230 KiB
Verilog
/*
|
|
Copyright (C) 2009-2015 Adapteva, Inc.
|
|
Contributed by Roman Trogan <roman@adapteva.com>
|
|
Contributed by Andreas Olofsson <andreas@adapteva.com>
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.This program is distributed in the hope
|
|
that it will be useful,but WITHOUT ANY WARRANTY; without even the implied
|
|
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details. You should have received a copy
|
|
of the GNU General Public License along with this program (see the file
|
|
COPYING). If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
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 // e16_arbiter_priority
|
|
|
|
|
|
/*
|
|
* FUNCTION: Simple round robin arbiter.
|
|
*
|
|
* NOTES: Responsibility of requester to retain request until he gets grant
|
|
* Request "zero" has the highest priority
|
|
* There is no pipelining in module
|
|
* There can be multiple requests arriving at the same time
|
|
* Grant vector is one hot
|
|
* Module is parametrized with ARW
|
|
* Priority Pointer Gets Rotated on Grant
|
|
*
|
|
*
|
|
* FEATURES: -the rotate enable should be lockable, set to zero
|
|
* -it should also be possible to set the rotate frequency, up to 16 bits
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
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 // e16_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)
|
|
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 // e16_clock_divider
|
|
|
|
|
|
|
|
`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*/
|
|
|
|
|
|
`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 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, c0_emesh_wait_in, c0_rdmesh_wait_in,
|
|
c1_rdmesh_wait_in, c2_rdmesh_wait_in, c3_emesh_wait_in,
|
|
c3_mesh_wait_in, c3_rdmesh_wait_in, txo_cfg_reg
|
|
);
|
|
|
|
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
|
|
|
|
wire [3:0] ext_yid_k=4'h8;
|
|
wire [3:0] ext_xid_k=4'h4;
|
|
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*/
|
|
// Beginning of automatic inputs (from unused autoinst inputs)
|
|
input c0_emesh_wait_in; // To link_port of link_port.v
|
|
input c0_rdmesh_wait_in; // To link_port of link_port.v
|
|
input c1_rdmesh_wait_in; // To link_port of link_port.v
|
|
input c2_rdmesh_wait_in; // To link_port of link_port.v
|
|
input c3_emesh_wait_in; // To link_port of link_port.v
|
|
input c3_mesh_wait_in; // To link_port of link_port.v
|
|
input c3_rdmesh_wait_in; // To link_port of link_port.v
|
|
input [5:0] txo_cfg_reg; // To link_port of link_port.v
|
|
// End of automatics
|
|
/*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),
|
|
);
|
|
*/
|
|
|
|
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, access,
|
|
access_in, ctrlmode, ctrlmode_in, data, data_in, datamode,
|
|
datamode_in, dstaddr, dstaddr_in, srcaddr, srcaddr_in, wait_in,
|
|
wait_int, write, write_in
|
|
);
|
|
|
|
parameter LW = `CFG_LW;//lvds tranceiver pairs per side
|
|
parameter DW = 32;
|
|
parameter AW = 32;
|
|
|
|
//#########
|
|
//#########
|
|
|
|
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*/
|
|
// Beginning of automatic inputs (from unused autoinst inputs)
|
|
input access; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input access_in; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input [3:0] ctrlmode; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input [3:0] ctrlmode_in; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input [DW-1:0] data; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input [DW-1:0] data_in; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input [1:0] datamode; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input [1:0] datamode_in; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input [AW-1:0] dstaddr; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input [AW-1:0] dstaddr_in; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input [AW-1:0] srcaddr; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input [AW-1:0] srcaddr_in; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input wait_in; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input wait_int; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input write; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
input write_in; // To rde16_mesh_interface of e16_mesh_interface.v
|
|
// End of automatics
|
|
/*AUTOWIRE*/
|
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
|
wire access_out; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire access_reg; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire [3:0] ctrlmode_out; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire [3:0] ctrlmode_reg; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire [DW-1:0] data_out; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire [DW-1:0] data_reg; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire [1:0] datamode_out; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire [1:0] datamode_reg; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire [AW-1:0] dstaddr_out; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire [AW-1:0] dstaddr_reg; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire fifo_empty; // From link_rxi_fifo of link_rxi_fifo.v
|
|
wire fifo_read; // From link_rxi_launcher of link_rxi_launcher.v
|
|
wire [14*LW-1:0] fifo_tran_out; // From link_rxi_fifo of link_rxi_fifo.v
|
|
wire rdmesh_frame; // From link_rxi_launcher of link_rxi_launcher.v
|
|
wire [2*LW-1:0] rdmesh_tran; // From link_rxi_launcher of link_rxi_launcher.v
|
|
wire [AW-1:0] srcaddr_out; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire [AW-1:0] srcaddr_reg; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire wait_out; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire write_out; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
wire write_reg; // From rde16_mesh_interface of e16_mesh_interface.v
|
|
// End of automatics
|
|
|
|
// #########
|
|
// # WIRES
|
|
// #########
|
|
|
|
//#########
|
|
//# FIFO
|
|
//#########
|
|
|
|
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 RDmesh
|
|
//###################################
|
|
|
|
/*link_rxi_launcher AUTO_TEMPLATE(
|
|
.emesh_\(.*\) (rdmesh_\1[]),
|
|
);
|
|
*/
|
|
|
|
link_rxi_launcher link_rxi_launcher(/*AUTOINST*/
|
|
// Outputs
|
|
.fifo_read (fifo_read),
|
|
.emesh_tran (rdmesh_tran[2*LW-1:0]), // Templated
|
|
.emesh_frame (rdmesh_frame), // Templated
|
|
// Inputs
|
|
.reset (reset),
|
|
.cclk (cclk),
|
|
.cclk_en (cclk_en),
|
|
.fifo_tran_out (fifo_tran_out[14*LW-1:0]),
|
|
.fifo_empty (fifo_empty),
|
|
.emesh_wait_in (rdmesh_wait_in)); // Templated
|
|
|
|
//##################################
|
|
//# Interface with emesh
|
|
//# on output transactions only
|
|
//# * input from the emesh is driven
|
|
//# by a diferent block
|
|
//##################################
|
|
|
|
/* e16_mesh_interface AUTO_TEMPLATE (
|
|
.clk (cclk),
|
|
.clk_en (cclk_en),
|
|
.emesh_wait_int (1'b0),
|
|
.emesh_tran_in ({(2*LW){1'b0}}),
|
|
.emesh_frame_in (1'b0),
|
|
.emesh_tran_reg (),
|
|
.emesh_frame_reg (),
|
|
.emesh_wait_out (),
|
|
.emesh_tran (rdmesh_tran[]),
|
|
.emesh_\(.*\) (@"(substring vl-cell-name 0 6)"_\1[]),
|
|
);
|
|
*/
|
|
|
|
e16_mesh_interface rde16_mesh_interface(/*AUTOINST*/
|
|
// Outputs
|
|
.wait_out (wait_out),
|
|
.access_out (access_out),
|
|
.write_out (write_out),
|
|
.datamode_out (datamode_out[1:0]),
|
|
.ctrlmode_out (ctrlmode_out[3:0]),
|
|
.data_out (data_out[DW-1:0]),
|
|
.dstaddr_out (dstaddr_out[AW-1:0]),
|
|
.srcaddr_out (srcaddr_out[AW-1:0]),
|
|
.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 (wait_in),
|
|
.access_in (access_in),
|
|
.write_in (write_in),
|
|
.datamode_in (datamode_in[1:0]),
|
|
.ctrlmode_in (ctrlmode_in[3:0]),
|
|
.data_in (data_in[DW-1:0]),
|
|
.dstaddr_in (dstaddr_in[AW-1:0]),
|
|
.srcaddr_in (srcaddr_in[AW-1:0]),
|
|
.wait_int (wait_int),
|
|
.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_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 e16_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) e16_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 e16_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)) e16_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)) e16_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 | c1_tran_frame_tlc |
|
|
c2_tran_frame_tlc | c3_tran_frame_tlc;
|
|
|
|
assign txo_data_even[LW-1:0] = c0_tran_byte_even_tlc[LW-1:0] |
|
|
c1_tran_byte_even_tlc[LW-1:0] |
|
|
c2_tran_byte_even_tlc[LW-1:0] |
|
|
c3_tran_byte_even_tlc[LW-1:0];
|
|
|
|
assign txo_data_odd[LW-1:0] = c0_tran_byte_odd_tlc[LW-1:0] |
|
|
c1_tran_byte_odd_tlc[LW-1:0] |
|
|
c2_tran_byte_odd_tlc[LW-1:0] |
|
|
c3_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, access,
|
|
access_in, ctrlmode, ctrlmode_in, data, data_in, datamode,
|
|
datamode_in, dstaddr, dstaddr_in, frame_in, srcaddr, srcaddr_in,
|
|
tran_in, wait_in, wait_int, write, write_in
|
|
);
|
|
|
|
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*/
|
|
// Beginning of automatic inputs (from unused autoinst inputs)
|
|
input access; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input access_in; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input [3:0] ctrlmode; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input [3:0] ctrlmode_in; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input [DW-1:0] data; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input [DW-1:0] data_in; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input [1:0] datamode; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input [1:0] datamode_in; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input [AW-1:0] dstaddr; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input [AW-1:0] dstaddr_in; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input frame_in; // To link_txo_fifo of link_txo_fifo.v
|
|
input [AW-1:0] srcaddr; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input [AW-1:0] srcaddr_in; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input [2*LW-1:0] tran_in; // To link_txo_fifo of link_txo_fifo.v
|
|
input wait_in; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input wait_int; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input write; // To e16_mesh_interface of e16_mesh_interface.v
|
|
input write_in; // To e16_mesh_interface of e16_mesh_interface.v
|
|
// End of automatics
|
|
/*AUTOWIRE*/
|
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
|
wire access_out; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire access_reg; // From e16_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_out; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire [3:0] ctrlmode_reg; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire [DW-1:0] data_out; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire [DW-1:0] data_reg; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire [1:0] datamode_out; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire [1:0] datamode_reg; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire [AW-1:0] dstaddr_out; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire [AW-1:0] dstaddr_reg; // From e16_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 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_out; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire [AW-1:0] srcaddr_reg; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire tran_written_tlc; // From link_txo_fifo of link_txo_fifo.v
|
|
wire wait_out; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire wr_fifo_full; // From link_txo_fifo of link_txo_fifo.v
|
|
wire write_out; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire write_reg; // From e16_mesh_interface of e16_mesh_interface.v
|
|
// End of automatics
|
|
|
|
//##################################
|
|
//# Interface with emesh
|
|
//# on input transactions only
|
|
//# * output to the emesh is driven
|
|
//# by a diferent block
|
|
//##################################
|
|
|
|
/* e16_mesh_interface AUTO_TEMPLATE (
|
|
.clk (cclk),
|
|
.clk_en (cclk_en),
|
|
.emesh_tran_reg (tran_in[]),
|
|
.emesh_frame_reg (frame_in),
|
|
.emesh_wait_int (wr_fifo_full),
|
|
.emesh_tran_out (),
|
|
.emesh_frame_out (),
|
|
.emesh_wait_in (1'b0),
|
|
.emesh_tran ({(2*LW){1'b0}}),
|
|
.emesh_frame (1'b0),
|
|
);
|
|
*/
|
|
e16_mesh_interface e16_mesh_interface(/*AUTOINST*/
|
|
// Outputs
|
|
.wait_out (wait_out),
|
|
.access_out (access_out),
|
|
.write_out (write_out),
|
|
.datamode_out (datamode_out[1:0]),
|
|
.ctrlmode_out (ctrlmode_out[3:0]),
|
|
.data_out (data_out[DW-1:0]),
|
|
.dstaddr_out (dstaddr_out[AW-1:0]),
|
|
.srcaddr_out (srcaddr_out[AW-1:0]),
|
|
.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 (wait_in),
|
|
.access_in (access_in),
|
|
.write_in (write_in),
|
|
.datamode_in (datamode_in[1:0]),
|
|
.ctrlmode_in (ctrlmode_in[3:0]),
|
|
.data_in (data_in[DW-1:0]),
|
|
.dstaddr_in (dstaddr_in[AW-1:0]),
|
|
.srcaddr_in (srcaddr_in[AW-1:0]),
|
|
.wait_int (wait_int),
|
|
.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]));
|
|
|
|
|
|
//########
|
|
//# FIFO
|
|
//########
|
|
|
|
link_txo_fifo #(.FAD(FAD)) link_txo_fifo(/*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),
|
|
.tran_in (tran_in[2*LW-1:0]),
|
|
.frame_in (frame_in),
|
|
.rd_read_tlc (rd_read_tlc[FAD:0]),
|
|
.check_next_dstaddr_tlc(check_next_dstaddr_tlc));
|
|
|
|
|
|
//#######################
|
|
//# Transaction Launcher
|
|
//#######################
|
|
|
|
/* link_txo_launcher AUTO_TEMPLATE (
|
|
.txo_rotate_dis (txo_rotate_dis),
|
|
.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), // 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
|
|
|
|
|
|
|
|
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-1: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 e16_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 e16_mesh_interface of e16_mesh_interface.v
|
|
wire [DW-1:0] data_reg; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire [1:0] datamode_reg; // From e16_mesh_interface of e16_mesh_interface.v
|
|
wire [AW-1:0] dstaddr_reg; // From e16_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 e16_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 e16_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 e16_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] = {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) e16_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,
|
|
c1_txo_launch_req_tlc, c1_txo_rotate_dis, c2_tran_byte_even_tlc,
|
|
c2_tran_byte_odd_tlc, c2_tran_frame_tlc, c2_txo_launch_req_tlc,
|
|
c2_txo_rotate_dis
|
|
);
|
|
|
|
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 c1_txo_launch_req_tlc; // To link_txo_arbiter of link_txo_arbiter.v
|
|
input c1_txo_rotate_dis; // To link_txo_arbiter of link_txo_arbiter.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
|
|
input c2_txo_launch_req_tlc; // To link_txo_arbiter of link_txo_arbiter.v
|
|
input c2_txo_rotate_dis; // To link_txo_arbiter of link_txo_arbiter.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 (/*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),
|
|
.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_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 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 // e16_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 // e16_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
|
|
e16_pulse2toggle e16_pulse2toggle(
|
|
// Outputs
|
|
.out (intoggle),
|
|
// Inputs
|
|
.clk (inclk),
|
|
.in (in),
|
|
.reset (reset));
|
|
|
|
//metastability e16_synchronizer
|
|
e16_synchronizer #(1) e16_synchronizer(
|
|
// Outputs
|
|
.out (insync),
|
|
// Inputs
|
|
.in (intoggle),
|
|
.clk (outclk),
|
|
.reset (reset));
|
|
|
|
|
|
//toogle to pulse
|
|
e16_toggle2pulse e16_toggle2pulse(
|
|
// Outputs
|
|
.out (out),
|
|
// Inputs
|
|
.clk (outclk),
|
|
.in (insync),
|
|
.reset (reset));
|
|
|
|
|
|
|
|
endmodule // e16_pulse2pulse
|
|
|
|
|
|
|
|
/* This e16_synchronizer is based on a Feb 20,2003 EDN article by
|
|
* Michael Crews and Yong Yenyongsgool from Philips called:
|
|
* "Practical design for transferring signals between clock domains"
|
|
*
|
|
* There are no assumptions on clock ratios or phases, which makes the
|
|
* circuit very robust!
|
|
*
|
|
* Theory:
|
|
* Converts pulse to toggle, synchronizes, then converts back to pulse
|
|
*
|
|
* Naming:
|
|
* svre-->valid on rising edge for source clock
|
|
* dvre-->valid on rising edge for destination clock
|
|
* Only place this e16_synchronizer on access type signals
|
|
*
|
|
*/
|
|
|
|
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 // e16_pulse2toggle
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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_e16_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
|
|
|
|
|
|
|
|
|
|
|