Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Spidergon Networks-on-Chips verilog code implementation

Status
Not open for further replies.

promach

Advanced Member level 4
Joined
Feb 22, 2016
Messages
1,199
Helped
2
Reputation
4
Reaction score
5
Trophy points
1,318
Activity points
11,636
I am working on Spidergon Networks-on-Chips verilog code implementation

Please see Spidergon NoC introduction

I am having two problems (I am a bit stucked) with spidergon_node.v and spidergon_top.v respectively.


1) In spidergon_node.v , how should I code the virtual_channels[] such that 'flit_data_input' is assigned to available virtual_channels[] ?



Code:
		 	.flit_data_input(flit_data_input[][]), 
		 	.flit_data_output(flit_data_output[][])

2) In spidergon_top.v , how do I code the verilog such that I could connect 'flit_data_input' and 'flit_data_output' according to the following spidergon architecture ?

9WPlKYw.png


spidergon_top.v


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// [url]https://www.reddit.com/r/algorithms/comments/au94ak/spidergon_networksonchips/[/url]
 
module spidergon_top 
#(parameter 
    NUM_OF_NODES=32, 
    NODE_BUFFER_WIDTH=4, 
    NUM_OF_VIRTUAL_CHANNELS=2, 
    FLIT_DATA_WIDTH=16
) 
(clk, reset, data_input, data_output);
 
 
// the most significant two bits are to indicate head and/or tail flits,
// followed by dest_node and flit_data_payload
// See [url]https://www.lisnoc.org/packets.html[/url]
 
// 01 = head_flit , 00 = data_flit (body_flit), 10 = tail_flit, 11 = flit_without_data_payload
localparam HEAD_TAIL = 2;
localparam DEST_NODE_WIDTH = $clog2(NUM_OF_NODES);
localparam FLIT_TOTAL_WIDTH = HEAD_TAIL+FLIT_DATA_WIDTH;
 
localparam NUM_OF_PORTS = 3; // clockwise, anti-clockwise, across
 
 
input clk, reset;
input [FLIT_TOTAL_WIDTH-1:0] data_input;
output signed [FLIT_DATA_WIDTH-1:0] data_output;
 
 
wire [FLIT_TOTAL_WIDTH-1:0] flit_data_input [NUM_OF_NODES-1:0][NUM_OF_PORTS-1:0];
wire [FLIT_TOTAL_WIDTH-1:0] flit_data_output [NUM_OF_NODES-1:0][NUM_OF_PORTS-1:0];
 
 
// data entrance and exit for the NoC
assign flit_data_input[0][0] = data_input;
assign data_output = flit_data_output[NUM_OF_NODES-1][NUM_OF_PORTS-1][0 +: FLIT_DATA_WIDTH];
 
 
localparam STOP = 3;
localparam ACROSS = 2;
localparam CLOCKWISE = 1;
localparam ANTI_CLOCKWISE = 0;
 
 
generate 
    // generates all the nodes of spidergon as well as the connecting edges between nodes
 
    genvar node_num;
 
    for(node_num = 0; node_num < NUM_OF_NODES; node_num = node_num + 1)
    begin
 
        spidergon_node node
        #( 
            NUM_OF_NODES, 
            node_num, 
            NODE_BUFFER_WIDTH, 
            NUM_OF_VIRTUAL_CHANNELS, 
            FLIT_DATA_WIDTH
        ) 
        (
            .clk(clk), .reset(reset), 
            .flit_data_input(flit_data_input[][]), 
            .flit_data_output(flit_data_output[][])
        );
 
    end
 
endgenerate
 
endmodule



spidergon_node.v


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// a single node within the Spidergon
 
module spidergon_node 
#(parameter 
    NUM_OF_NODES=32, 
    NODE_IDENTIFIER=0, 
    NODE_BUFFER_WIDTH=4, 
    NUM_OF_VIRTUAL_CHANNELS=2, 
    FLIT_DATA_WIDTH=16
) 
(clk, reset, flit_data_input, flit_data_output);
 
 
localparam STOP = 3;
localparam ACROSS = 2;
localparam CLOCKWISE = 1;
localparam ANTI_CLOCKWISE = 0;
 
 
// the most significant two bits are to indicate head and/or tail flits,
// followed by dest_node and flit_data_payload
// See [url]https://www.lisnoc.org/packets.html[/url]
 
// 01 = head_flit , 00 = data_flit (body_flit), 10 = tail_flit, 11 = flit_without_data_payload
localparam HEAD_TAIL = 2;
localparam DEST_NODE_WIDTH = $clog2(NUM_OF_NODES);
localparam FLIT_TOTAL_WIDTH = HEAD_TAIL+FLIT_DATA_WIDTH;
 
 
localparam NUM_OF_PORTS = 3; // clockwise, anti-clockwise, across
localparam BIDIRECTIONAL_PER_PORT = 2; // two-way data traffic
 
 
input clk, reset;
 
input [FLIT_TOTAL_WIDTH-1:0] flit_data_input [NUM_OF_PORTS-1:0];
output reg [FLIT_TOTAL_WIDTH-1:0] flit_data_output [NUM_OF_PORTS-1:0];
 
 
reg signed [NODE_BUFFER_WIDTH-1:0] virtual_channels [NUM_OF_VIRTUAL_CHANNELS-1:0][NUM_OF_PORTS-1:0];
 
// requests for the input data (from one of the 3 input ports) 
// to be routed to  destination node (via one of the 3 output ports)
// this 'req' is not a one-hot vector: reg [vc_num] req [out_port];
// multiple input data streams from different virtual channels could compete for the same output port
reg [NUM_OF_VIRTUAL_CHANNELS-1:0] req [NUM_OF_PORTS-1:0];
 
reg [NUM_OF_VIRTUAL_CHANNELS-1:0] req_previous [NUM_OF_PORTS-1:0];
 
// note that 'grant' is one-hot vector, 
// when asserted, it means the corresponding 'req' is approved/granted
// and only a single priority line is serviced (granted) at any given clock cycle
wire [NUM_OF_VIRTUAL_CHANNELS-1:0] grant [NUM_OF_PORTS-1:0];
 
wire [NUM_OF_VIRTUAL_CHANNELS-1:0] grant_previous [NUM_OF_PORTS-1:0];
 
 
localparam DIRECTION_WIDTH = 2;
wire [DIRECTION_WIDTH-1:0] direction [NUM_OF_PORTS-1:0]; // stop, clockwise, anti-clockwise, across
 
wire [DEST_NODE_WIDTH-1:0] dest_node [NUM_OF_PORTS-1:0];
 
 
genvar port_num;
genvar vc_num;
 
generate
 
    for(port_num=0; port_num<NUM_OF_PORTS; port_num=port_num+1)
    begin
 
        for(vc_num=0; vc_num<NUM_OF_VIRTUAL_CHANNELS; vc_num=vc_num+1)
        begin
 
            always @(posedge clk) 
            begin
                if(reset) virtual_channels[port_num][vc_num] <= 0;
 
                else begin
 
                    virtual_channels[port_num][vc_num] <= 0;
 
                    if() virtual_channels[dest_node][vc_num] <= flit_data_input[port_num];
 
                    else virtual_channels[dest_node][vc_num] <= 0;
                    
                end
            end
        
 
            always @(posedge clk) 
            begin
                if(reset) req_previous[port_num][vc_num] <= 0;
 
                else req_previous[port_num][vc_num] <= req[port_num][vc_num];
            end
 
 
            always @(posedge clk) 
            begin
                if(reset) req[direction[port_num]][vc_num] <= 0;
 
                else begin
 
                    // check the flit header to determine the flit nature
                    case(flit_data_input[port_num][(FLIT_TOTAL_WIDTH-1) -: HEAD_TAIL]) 
                    begin
                        // body_flit
                        // to keep 'req' stable before the arrival of tail_flit
                        'b00 : req[direction[port_num]][vc_num] <= req_previous[direction[port_num]][vc_num];
 
                        // tail_flit
                        'b01 : req[direction[port_num]][vc_num] <= 0;
 
                        // head_flit
                        'b10 : req[direction[port_num]][vc_num] <= 1;
 
                        // flit_without_data_payload
                        'b11 : req[direction[port_num]][vc_num] <= 1;
 
                        default : req[direction[port_num]][vc_num] <= 0;
                    end
                end
            end
        end
 
 
        // virtual channel (VC) buffers round-robin arbitration
        arbiter rr_arb #(NUM_OF_VIRTUAL_CHANNELS)
        (.req(req[port_num]), .grant(grant[port_num]), .base(base[port_num]));
 
 
        always @(posedge clk) 
        begin
            if(reset) grant_previous[port_num] <= 0;
 
            else grant_previous[port_num] <= grant[port_num];
        end
 
 
        always @(posedge clk)
        begin
            // starts round-robin arbiter with priority #1 getting prioritized first
            if(reset) base[port_num] <= 1;
 
            // 'base' is a one-hot signal 
            //  which rotates upon 'req' is granted (and tail_flit had arrived), 
            //  and wraps around upon reaching MSB
 
            else if((grant_previous[port_num] != grant[port_num]) && (req[port_num] == 0))
 
                base[port_num] <= (base[port_num][NUM_OF_VIRTUAL_CHANNELS-1]) ? 1 : (base[port_num] << 1);
        end
 
 
        assign dest_node[port_num] = flit_data_input[port_num][(FLIT_DATA_WIDTH-1) +: DEST_NODE_WIDTH];
 
        // path routing computation block for each input ports
        router rt 
        (
            .clk(clk), 
            .reset(reset), 
            .dest_node(dest_node[port_num]), 
            .current_node(NODE_IDENTIFIER), 
            .direction(direction[port_num])
        );
 
 
        always @(posedge clk)
        begin
            if(reset) flit_data_output[NUM_OF_PORTS-1:0] <= 0;
            
            else begin
                // for Spidergon NoC functional verification and testing
                flit_data_output[direction[port_num]] <= virtual_channels[direction[port_num]][grant];
 
                // user-defined module (arithmetic operations) within each Spidergon node
                /*multiply mty #()
                (.clk(clk), .reset(reset), .in_valid(in_valid), .out_valid(out_valid), 
                 .in_A(in_A), .in_B(in_B), .out_C(out_C));*/
            end
        end
 
    end
 
endgenerate
 
endmodule



router.v


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// shortest path routing algorithm of Spidergon
 
module router #(parameter NUM_OF_NODES = 32) (clk, reset, dest_node, current_node, direction)
 
localparam DIRECTION_WIDTH = 2;
 
localparam STOP = 3;
localparam ACROSS = 2;
localparam CLOCKWISE = 1;
localparam ANTI_CLOCKWISE = 0;
 
input clk, reset;
input [$clog2(NUM_OF_NODES)-1:0] dest_node, current_node;
output reg [DIRECTION_WIDTH-1:0] direction; // stop, clockwise, anti-clockwise, across
 
// RelAd = ((dest-current) mod (NUM_OF_NODES)) * 4
// [url]https://en.wikipedia.org/wiki/Modulo_operation#Performance_issues[/url]
// x % 2^n == x < 0 ? x | ~(2^n - 1) : x & (2^n - 1)
 
wire signed [$clog2(NUM_OF_NODES)-1:0] diff;
wire [$clog2(NUM_OF_NODES)-1:0] RelAd;
 
assign diff = dest_node - current_node;
assign RelAd = (diff < 0) ? (diff | ~(NUM_OF_NODES-1)) | (diff & (NUM_OF_NODES-1));
 
localparam SHIFT_BY_TWO = 2; // multiply by four
localparam NUM_OF_NODES_TIMES_THREE = 3*NUM_OF_NODES;
localparam NUM_OF_NODES_TIMES_FOUR = 4*NUM_OF_NODES;
 
always @(posedge clk)
begin
    if(reset) direction <= STOP;
 
    else begin
        // [url]https://www.verificationguide.com/p/systemverilog-constraint-inside.html[/url]
        case(RelAd << SHIFT_BY_TWO) inside
        begin
            0 : direction <= STOP;
 
            [NUM_OF_NODES:1] : direction <= CLOCKWISE;
 
            [NUM_OF_NODES_TIMES_FOUR:NUM_OF_NODES_TIMES_THREE] : direction <= ANTI_CLOCKWISE;
 
            default : direction <= ACROSS;
        end
    end
end
 
endmodule



arbiter.v


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// Credit: [url]https://github.com/thomasrussellmurphy/stx_cookbook/blob/master/arbitration/arbiter.v[/url]
 
// Copyright 2007 Altera Corporation. All rights reserved.  
// Altera products are protected under numerous U.S. and foreign patents, 
// maskwork rights, copyrights and other intellectual property laws.  
//
// This reference design file, and your use thereof, is subject to and governed
// by the terms and conditions of the applicable Altera Reference Design 
// License Agreement (either as signed by you or found at [url]www.altera.com[/url]).  By
// using this reference design file, you indicate your acceptance of such terms
// and conditions between you and Altera Corporation.  In the event that you do
// not agree with such terms and conditions, you may not use the reference 
// design file and please promptly destroy any copies you have made.
//
// This reference design file is being provided on an "as-is" basis and as an 
// accommodation and therefore all warranties, representations or guarantees of 
// any kind (whether express, implied or statutory) including, without 
// limitation, warranties of merchantability, non-infringement, or fitness for
// a particular purpose, are specifically disclaimed.  By making this reference
// design file available, Altera expressly does not recommend, suggest or 
// require that this reference design file be used in combination with any 
// other product not provided by Altera.
/////////////////////////////////////////////////////////////////////////////
 
 
// baeckler - 02-13-2007
//
// 'base' is a one hot signal indicating the first request
// that should be considered for a grant.  Followed by higher
// indexed requests, then wrapping around.
//
 
// [url]https://www.reddit.com/r/FPGA/comments/axutbt/understanding_a_simple_roundrobin_arbiter_verilog/[/url]
 
module arbiter (
    req, grant, base
);
 
parameter WIDTH = 16;
 
input [WIDTH-1:0] req;
output [WIDTH-1:0] grant;
input [WIDTH-1:0] base;
 
wire [2*WIDTH-1:0] double_req = {req,req};
wire [2*WIDTH-1:0] double_grant = double_req & ~(double_req-base);
assign grant = double_grant[WIDTH-1:0] | double_grant[2*WIDTH-1:WIDTH];
    
endmodule

 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top