1// BUF from Chapter 4 of FoCs User's Manual (www.haifa.il.ibm.com/projects/verification/focs/)
2// with sender, BUF, receiver clocked on clk1, clk2, clk3 respectively.
3//---------------------------------- Sender ----------------------------------
4// Send the sequence 0, 1, 2, ... , 99
5
6module Sender (clk, BtoS_ACK, StoB_REQ, DI);
7
8input         clk;
9input         BtoS_ACK;
10output        StoB_REQ;
11output [31:0] DI;
12
13// Can't assign to output wires, so need to connect them to registers
14reg           StoB_REQ_reg;      // Drives StoB_REQ
15reg    [31:0] DI_reg;            // Drives DI (with 0, 1, 2, ... , 99)
16
17assign StoB_REQ = StoB_REQ_reg;  // Drive wire StoB_REQ
18assign DI       = DI_reg;        // Drive wire DI (actually a 32-bit bus)
19
20initial
21 begin
22  DI_reg = 0;
23 end
24
25always @(posedge clk)
26 begin
27  #10
28  if (DI_reg < 10)
29   begin
30    StoB_REQ_reg = 1;            // Assert request
31     @(posedge BtoS_ACK)         // Wait for ack to be asserted
32     #10                         // Wait 10 time units
33     StoB_REQ_reg = 0;           // Deassert request
34     #10                         // Wait 10 time units
35     @(negedge BtoS_ACK)         // Wait for ack to be de-asserted
36     #10                         // Wait 10 time units before incrementing data
37     DI_reg = DI_reg + 1;        // Increment data to be sent next iteration
38    end
39  else
40  #10 $finish;
41 end
42
43endmodule
44
45//---------------------------------- BUF -------------------------------------
46// Receive data from Sender and then send it to Receiver
47
48module BUF (clk,StoB_REQ, RtoB_ACK, DI, BtoS_ACK, BtoR_REQ, DO);
49
50input         clk;
51input         StoB_REQ;
52input         RtoB_ACK;
53input  [31:0] DI;
54output        BtoS_ACK;
55output        BtoR_REQ;
56output [31:0] DO;
57
58// Can't assign to output wires, so need to connect them to registers
59reg           BtoS_ACK_reg;      // Drives BtoS_ACK
60reg           BtoR_REQ_reg;      // Drives BtoR_REQ
61reg    [31:0] DO_reg;            // Drives DO
62
63// BUF internal state registers
64reg           free;              // Flag to say if BUF is free to receive new data
65reg    [31:0] data;              // Data last read from Sender
66
67assign BtoS_ACK = BtoS_ACK_reg;  // Drive wire BtoS_ACK
68assign BtoR_REQ = BtoR_REQ_reg;  // Drive wire BtoR_REQ
69assign DO       = DO_reg;        // Drive wire DO (actually a 32-bit bus)
70
71initial 
72 begin 
73  BtoS_ACK_reg = 0;              // Initially BtoS_ACK not asserted
74  BtoR_REQ_reg = 0;              // Initially BtoR_REQ not asserted
75  free = 1;                      // Initially free is true
76 end  
77
78always @(posedge clk)
79 if (StoB_REQ && free)           // Wait for StoB_REQ to be asserted and BUF free
80  begin 
81   free = 0;                     // Set BUF to be not free
82   data = DI;                    // Read data
83   #10 BtoS_ACK_reg = 1;         // Tell Sender data is aquired
84   #10 DO_reg = data;            // Put dat on DO
85   #10 BtoR_REQ_reg = 1;         // Assert BtoR_REQ
86   @(posedge RtoB_ACK)           // Wait for Receiver to acknowledge receipt of data
87   #10 BtoR_REQ_reg = 0;         // Deassert BtoR_REQ
88   #10 BtoS_ACK_reg = 0;         // Deassert BtoS_ACK
89   free = 1;                     // Set BUF to be free
90  end
91 else 
92  #10 begin end
93
94endmodule
95
96
97
98//---------------------------------- Receiver --------------------
99// Receive data from BUF
100
101module Receiver (clk, BtoR_REQ, DO, RtoB_ACK);
102
103input         clk;
104input         BtoR_REQ;
105input  [31:0] DO;
106output        RtoB_ACK;
107
108// Can't assign to output wire RtoB_ACK, so need to connect it to a register
109reg           RtoB_ACK_reg;      // Drives BtoR_REQ
110
111// Receiver internal state registers
112reg    [31:0] data;              // Data last read from BUF
113
114assign RtoB_ACK = RtoB_ACK_reg;  // Drive wire RtoB_ACK
115
116initial RtoB_ACK_reg = 0;        // Initially RtoB_ACK not asserted
117
118always @(posedge clk)
119 @(posedge BtoR_REQ)             // Wait for BtoR_REQ to be asserted
120 begin
121  #10 data = DO;                 // Copy data from DO
122  #10 RtoB_ACK_reg = 1;          // Assert RtoB_ACK to say data aquired
123  #10 @(negedge BtoR_REQ)        // Wait for BtoR_REQ to be deasserted
124  #10 RtoB_ACK_reg = 0;          // Deassert RtoB_ACK
125 end
126
127endmodule
128
129//---------------------------------- Test ------------------------------------
130// Top level module linking Sender, BUF and Receiver
131
132module test ();
133
134wire         StoB_REQ, BtoS_ACK, BtoR_REQ, RtoB_ACK;
135wire  [31:0] DI, DO;
136reg          clk1, clk2, clk3;
137
138Sender   M1(clk1, BtoS_ACK, StoB_REQ, DI);
139BUF      M2(clk2, StoB_REQ, RtoB_ACK, DI, BtoS_ACK, BtoR_REQ, DO);
140Receiver M3(clk3, BtoR_REQ, DO, RtoB_ACK);
141
142// Make clocks tick
143initial
144 forever 
145  begin
146   #10 clk1 = 0;
147   #10 clk1 = 1;
148  end
149
150initial
151 forever 
152  begin
153   #13 clk2 = 0;
154   #10 clk2 = 1;
155  end
156
157initial
158 forever 
159  begin
160   #17 clk3 = 0;
161   #17 clk3 = 1;
162  end
163
164
165// Xtreme kludge to generate output that can be munged
166// into SimRun example in test (have eliminated strings)
167
168//initial
169// begin
170// $monitor 
171//   ("Time = %0d, clk = %0d, StoB_REQ = %0d, BtoS_ACK = %0d, DI = %0d, BtoR_REQ = %0d, RtoB_ACK = %0d, DO = %0d",
172//    $time, clk, StoB_REQ, BtoS_ACK, DI, BtoR_REQ, RtoB_ACK, DO);
173// end
174
175initial
176 begin
177 $monitor 
178  ("((if %0d=1 then {clk1} else {}) UNION\
179(if %0d=1 then {clk2} else {}) UNION\
180(if %0d=1 then {clk3} else {}) UNION\
181(if %0d=1 then {StoB_REQ} else {}) UNION\
182(if %0d=1 then {BtoS_ACK} else {}) UNION\
183(if %0d=1 then {BtoR_REQ} else {}) UNION\
184(if %0d=1 then {RtoB_ACK} else {}));",
185   clk1, clk2, clk3, StoB_REQ, BtoS_ACK, BtoR_REQ, RtoB_ACK);
186 end
187
188endmodule
189
190
191
192//initial
193// $monitor 
194//  ("val At_%0d = ``(StoB_REQ = %0d) /\\ (BtoS_ACK = %0d) /\\ (BtoR_REQ = %0d) /\\ (RtoB_ACK = %0d)``;",
195//   $time, StoB_REQ, BtoS_ACK, BtoR_REQ, RtoB_ACK);
196
197
198
199//initial
200// begin
201// $monitor 
202//   ("Time = %0d, clk = %0d, StoB_REQ = %0d, BtoS_ACK = %0d, DI = %0d, BtoR_REQ = %0d, RtoB_ACK = %0d, DO = %0d",
203//    $time, clk, StoB_REQ, BtoS_ACK, DI, BtoR_REQ, RtoB_ACK, DO);
204// end
205
206
207
208