initial
[fpgammix.git] / doc / interconnection.txt
blob81085b250fe911499feb72a343e5cb6ec5866b54
1 I've rejected WISHBONE as being too low performance.  Altera's Avalon
2 represents the golden standard for me, but it's _very_ general and
3 would take much effort to replicate.
5 For my needs I only need:
6 - all reads are pipelined with variable latency
7 - multi master support
8 - burst support
11 Basics
12 ~~~~~~
14 Master raises transfer_request to initial a transfer.  Slave
15 asynchronously raises wait_request when it's not ready.  The master is
16 expected to hold the request and associated parameters stable until
17 wait goes down.
19 Example, a master side state machine issuing two requests (no bust)
20 will look like:
22   always @(posedge clock) case (state)
23   S1: begin
24     ... <parameters> ... <= .... params for 1st req ....
25     transfer_request     <= 1;
26     state <= S2;
27   end
29   S2: if (~wait_request) begin
30     ... <parameters> ... <= .... params for 1st req ....
31     state <= S3;
32   end
34   S3: if (~wait_request) begin
35     transfer_request <= 0;
36     ....
37   end
40 Pipelined Reading
41 ~~~~~~~~~~~~~~~~~
43 Read requests are just like write requests, except that one or more
44 cycles in the future replies will arrive, in the order issued, raising
45 data_valid for one cycle for each reply.
47 Extending the above example, we need a separate state machine
48 collecting the data as we can't assume anything about how long we will
49 have to wait in S2.
51   always @(posedge clock) begin
52     if (data_valid)
53       if (waiting_for_1st) begin
54         first <= port_read_data;
55         waiting_for_1st <= 0;
56       end else begin
57         second <= port_read_data;
58         waiting_for_2nd <= 0;
59       end
61     case (state)
62     S1: begin
63       ... <parameters> ... <= .... params for 1st req ....
64       transfer_request     <= 1;
65       waiting_for_1st      <= 1;
66       state <= S2;
67     end
69     S2: if (~wait_request) begin
70       ... <parameters> ... <= .... params for 2nd req ....
71       waiting_for_2nd      <= 1;
72       state <= S3;
73     end
75     S3: if (~wait_request) begin
76       transfer_request <= 0;
77       state <= S4;
78     end
80     S4: if (~waiting_for_1st & ~waiting_for_2nd) begin
81       ... process data
82     end
83   end
86 In many cases burst transfers can replace the need for multiple
87 issues.
90 Multi Master
91 ~~~~~~~~~~~~
93 I really like the shared based approach to arbitration that Avalon
94 has.  Let's see if we can replicate it.
96   Constants
97     A_SHARES, B_SHARES
99   if (transfer_request_a & (shares_left_for_a | ~transfer_request_b))
100      go ahead and let A get access
101      if (shares_left_for_a == 0)
102         shares_left_for_a = A_SHARES
103      else
104         --shares_left_for_a
105   else if (transfer_request_b & (shares_left_for_b | ~transfer_request_a))
106      go ahead and let B get access
107      if (shares_left_for_b == 0)
108         shares_left_for_b = A_SHARES
109      else
110         --shares_left_for_b
111   else /* ~transfer_request_a & ~transfer_request_b */
112      shares_left_for_a = A_SHARES
113      shares_left_for_b = A_SHARES
114      do nothing else
116 Puh, not tooo complicated?  Just wait until we throw burst support into the mix.
118 Also, I failed to show how to support routing the read data back to
119 theirs masters.  A simple 1-bit FIFO of length A_SHARES + B_SHARES
120 (??)  should be sufficient.  (Careful about the latency of the FIFO
121 itself.)  However, the arbitration must know which requests will
122 result in a reply.  (Should simply all requests result in a reply to
123 simplify?)
126 Burst support
127 ~~~~~~~~~~~~~
129 I haven't found documentation for how Avalon handles this, but it
130 seems that simply extending the basic strategy with a burst count
131 should suffice.
133 Example: lets show the client side for a change (as the master looks
134 almost exactly the same as for a single request).  This simple client
135 can only handle one outstanding request at a time, but it does support
136 bursts.
138   wire wait_request = count != 0;
140   always @(posedge clock) begin
141     pipeline[N:1] <= pipeline[N-1:0];
142     pipeline[0] <= 0;
143     if (count) begin
144       addr <= addr + 1;
145       pipeline[0] <= 1;
146       count <= count - 1;
147     else if (transfer_request) begin
148            count <= burst_length;
149            addr <= request_addr
150     end
151   end
153 (Of course the counting down to -1 and using the sign bit would be
154 better).
157 The only extension needed for the arbitration is knowing about the
158 burst size.