add peripherals
[shakti-peripherals.git] / src / peripherals / vme / vme_master.bsv
1 /*
2 Copyright (c) 2013, IIT Madras
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 * Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
13 */
14 /*
15 Generating VME master requests
16
17 */
18
19 package vme_master;
20 //import TriState ::*;
21 import FIFOF ::*;
22 import vme_defines ::*;
23 //import Clocks ::*;
24
25
26
27 /*
28 READ CYCLE
29
30
31 1.STATE 0 : receives req (function codes,r/w,siz1,siz0,addrbus) latched
32
33 2.STATE 1 : assert address strobe and data strobe
34
35 3. STATE 2 : Wait
36
37 4. STATE 3 : Check for acknowledgement
38
39 5. STATE 4 : latch data
40
41 6. STATE 5: Release address strobe and data strobe(acknowledge lines will be released one cycle later)
42
43 WRITE CYCLE
44
45
46 1.STATE 0: receives req (function codes,r/w,siz1,siz0,addrbus) latched
47
48 2.STATE 1 : assert address strobe
49
50 3. STATE 2 : place data on the bus and wait for acknowledgement
51
52 4. STATE 3 : assert data and strobe and enable required data lines
53
54 5. STATE 4 : No operation
55
56 6. STATE 5:Release address strobe and data strobe(acknowledge lines will be released one cycle later)READ CYCLE
57
58 Data_mode :01 byte
59 10 Word
60 00 Long word
61 */
62
63 typedef enum
64
65
66 {RCV_REQ,PRC_REQ_1,PRC_REQ_2,PRC_REQ_3,LATCH_DATA,END_REQ,ADDR_INVALID,HALT
67 }State_master deriving (Bits,Eq);
68
69 typedef enum
70 {LW,BYTE,WORD,TRI_BYTE}Data_mode deriving (Bits,Eq);
71
72 interface Vme_out;
73 (*always_enabled,always_ready*)
74 method Bit#(1) wr_as_l();
75 (*always_enabled,always_ready*)
76 method Bit#(1) wr_ds_l();
77 (*always_enabled,always_ready*)
78 method Bit#(1) wr_wr_l();
79 (*always_ready*)
80 method Action rd_dsack_0_l(Bit#(1) x);
81 (*always_ready*)
82 method Action rd_dsack_1_l(Bit#(1) y);
83 (*always_ready*)
84 method Action rd_berr_l(Bit#(1) z);
85 (*always_ready*)
86 method Action rd_halt_l(Bit#(1) u);
87 endinterface:Vme_out
88
89 interface Data_bus_inf;
90
91 method Bit#(8) wr_byte_31_24();
92 (*always_enabled,always_ready*)
93 method Bit#(1) wr_siz1();
94 (*always_enabled,always_ready*)
95 method Bit#(1) wr_siz0();
96 method Bool wr_mode_en();
97 (*always_enabled,always_ready*)
98 method Bit#(32) wr_addr();
99 method Bool wr_addr_en();
100 method Bit#(4) wr_en();
101
102 method Bit#(3) wr_fun_code();
103 method Bool wr_fun_code_en();
104 method Bit#(8) wr_byte_23_16();
105 method Bit#(8) wr_byte_15_8();
106 method Bit#(8) wr_byte_7_0();
107
108 method Action rd_byte_31_24(Bit #(8) d3);
109 method Action rd_byte_23_16(Bit #(8) d2);
110 method Action rd_byte_15_8 (Bit #(8) d1);
111 method Action rd_byte_7_0 (Bit #(8) d0);
112
113 endinterface
114
115 interface Vme_master ;
116 method Action get_req (Req_vme req);
117 interface Vme_out vme_interface;
118 interface Data_bus_inf data_bus;
119 method ActionValue #(Resp_vme) resp();
120 endinterface:Vme_master
121
122 (*synthesize*)
123
124 module mkvmemaster(Vme_master);
125
126
127 //Fifos to get request and send response
128 FIFOF #(Req_vme) cpu_req <- mkFIFOF;
129 FIFOF #(Resp_vme) cpu_resp <- mkFIFOF;
130 //............................................................//
131
132 Reg #(State_master) master_state <- mkReg (RCV_REQ);
133 Reg#(Bit#(2)) mode<-mkReg(0);
134 Reg#(Bool) mode_en<-mkReg(False);//Enable SIZ1,SIZ0
135 Reg#(Bit#(3)) fun_code<-mkReg(0);
136 Reg#(Bool) fun_code_en<-mkReg(False);
137 Reg#(Bit#(1)) as_l<-mkReg(1);//address_stop
138 Reg#(Bit#(1)) ds_l<-mkReg(1);//data_strobe
139 Reg#(Bit#(1)) stop<-mkReg(0);//Indicates processor stopped
140 Reg#(Bit#(1)) retry<-mkReg(0);//Indicates retry mode
141 Wire#(Bit#(1)) dsack_0_l<-mkDWire(1);//ack from VIC controller,indicates port size 0-32 bit port,1-8 bit port,2-16 bit port
142 Wire#(Bit#(1)) dsack_1_l<-mkDWire(1);
143 Wire#(Bit#(1)) berr_l <-mkDWire(1);//Bus error from slave
144 Wire#(Bit#(1)) halt_l<-mkDWire(1);//halt signal from the slave
145 //Wire#(Bit#(3)) ipl_l<-mkDWire(1);//interrupt prioritylevel
146
147 Reg #(Bit#(32)) addr<-mkReg(0);//addr_bus
148 Reg #(Bool) addr_en<-mkReg(False);
149 Reg #(Bit#(8)) data_out_4<-mkReg(0);//wr_data_4
150 Reg #(Bit#(8)) data_out_3<-mkReg(0);//wr_data_3
151 Reg #(Bit#(8)) data_out_2<-mkReg(0);//wr_data_2
152 Reg #(Bit#(8)) data_out_1<-mkReg(0);//wr_data_1
153
154 Wire #(Bit#(8)) data_in_4<-mkDWire(0);//rd_data_4
155 Wire #(Bit#(8)) data_in_3<-mkDWire(0);//rd_data_3
156 Wire #(Bit#(8)) data_in_2<-mkDWire(0);//rd_data_2
157 Wire #(Bit#(8)) data_in_1<-mkDWire(0);//rd_data_1
158
159
160 Reg #(Bit#(1)) wr_l <-mkReg(1'd1);//read : 1,write:0
161 Reg #(Bit#(4)) data_control <-mkReg(0);//Enable bits to data and control registers
162 Reg #(Bit#(2)) cntl_wd<-mkReg(0); //To synchronize if more than one cycle is required to r/w data
163 //.........Tristate signals...............//
164 /*
165
166 /*
167 */
168 (* mutually_exclusive = "rcv_req_new,prc_req,prc_req_1,prc_req_2,req_wait,end_req" *)
169
170 /* REQ_RCV master_state....
171 1. Master receives request
172 2. address,FC2-FC0,Data,Write lines are driven
173 */
174 rule rcv_req_new(master_state==RCV_REQ && cntl_wd==2'b00 && (halt_l==1'b1) && (berr_l==1'b1)) ;//To recieve new request
175
176 let req =cpu_req.first();
177 $display("MASTER_STATE 1: receiving request to address %h req_type:%h",req.addr,req.rd_req,$time);
178 cpu_req.deq();
179 addr<=req.addr;
180 addr_en<=True;
181 fun_code_en<=True;
182 mode_en<=True;
183 mode<=req.mode;
184 $display("mode of operation %b",req.mode);
185 fun_code<=req.fun_code;
186 wr_l<=req.rd_req;
187 master_state<=PRC_REQ_1;
188
189 //............Multiplexing logic to route data to data bus......................................................................................................
190
191 if (req.mode==2'b01)//For 8 bit data operations
192 case({req.addr[1],req.addr[0]})
193
194 2'b00:data_out_4<=req.wr_data[7:0];
195
196 2'b01:begin
197 data_out_4<=req.wr_data[7:0];
198 data_out_3<=req.wr_data[7:0];
199 end
200
201 2'b10:begin
202 data_out_4<=req.wr_data[7:0];
203 data_out_2<=req.wr_data[7:0];
204 end
205 2'b11:begin
206 data_out_4<=req.wr_data[7:0];
207 data_out_3<=req.wr_data[7:0];
208 data_out_1<=req.wr_data[7:0];
209 end
210 endcase
211
212
213 else if (req.mode==2'b10)//For 16 data operations
214 case({req.addr[1],req.addr[0]})
215
216 2'b00:begin
217
218 data_out_4<=req.wr_data[7:0];
219 data_out_3<=req.wr_data[15:8];
220
221 end
222
223 2'b10: begin
224 data_out_4<=req.wr_data[7:0];
225 data_out_3<=req.wr_data[15:8];
226 data_out_1<=req.wr_data[15:8];
227 data_out_2<=req.wr_data[7:0];
228 end
229 endcase
230
231 else if (req.mode==2'b00)//for 32 bit operation
232
233 case({req.addr[1],req.addr[0]})
234
235 2'b00:
236 begin
237 data_out_1<=req.wr_data[31:24];
238 data_out_2<=req.wr_data[23:16];
239 data_out_3<=req.wr_data[15:8];
240 data_out_4<=req.wr_data[7:0];
241 $display("Data to be written = %h",req.wr_data);
242 end
243 endcase
244 //..............................................................................................................................................................
245 endrule
246
247 rule prc_req(master_state==RCV_REQ && cntl_wd!=2'b00);//If a request takes multiple cycles
248
249 if(cntl_wd==2'b01)//32 bit operation from 8 bit or 16 bit slave
250
251
252 begin
253
254 data_out_4<=data_out_3;
255 data_out_3<=data_out_2;
256 data_out_2<=data_out_1;
257 data_out_1<=8'b0;
258 addr <=addr+1;
259 mode <=mode-1;
260 end
261 else
262 begin//32 bit operation on a 16 bit slave
263
264 data_out_4<=data_out_2;
265 data_out_3<=data_out_1;
266 data_out_2<=8'b0;
267 data_out_1<=8'b0;
268 addr <= addr+2;
269 mode <=2'b10;
270 end
271 master_state<=PRC_REQ_1;
272
273 endrule
274 /*
275 InPRC_REQ_1....
276
277 1.Address strobe is asserted
278
279 2.Data Strobe is asserted if it is a read cycle
280
281 3. Data lines are enabled for write cycle
282
283
284 */
285
286 rule prc_req_1(master_state==PRC_REQ_1);
287
288
289
290 $display("MASTER_STATE 2: Activating address strobe",$time);
291 as_l<=0;
292 master_state<=PRC_REQ_2;
293 ds_l<=0;
294 if(wr_l==1'b0)
295 data_control<=4'b1111;
296
297 endrule
298 /*
299 In PRC_REQ_2
300 1. Data strobe is asserted in write cycle on receiving ack,halt or bus error cycle
301 */
302 rule prc_req_2(master_state==PRC_REQ_2);
303
304 begin
305 $display("MASTER_STATE_3 ",$time);
306 if (({dsack_0_l,dsack_1_l}!=2'b11)||(berr_l==1'b0)||(halt_l==1'b0))
307 begin
308 master_state<=PRC_REQ_3;
309 end
310
311
312 end
313 endrule
314 /*In WAIT_RESP
315 1. Master waits for response
316 2. On receiving response,goes to next state
317 */
318
319 rule req_wait((master_state==PRC_REQ_3)&&(({dsack_0_l,dsack_1_l}!=2'b11)||(berr_l==1'b0)||(halt_l==1'b0)));
320
321 // if (wr_l==1'b0)
322
323 // ds_l<=0;
324
325 master_state<=LATCH_DATA;
326 $display(" MASTER_STATE_4:",$time);
327 if({dsack_0_l,dsack_1_l}==mode)
328 begin
329 // $display("detected response %h",$time);
330 // master_state<=LATCH_DATA;
331 cntl_wd<=2'b00;//Done can take the next request
332 end
333 //if a 32 bit word r/w fro/to a 16 bit port
334 else if({dsack_0_l,dsack_1_l}==2'b10 && mode==2'b00)
335
336 begin
337 cntl_wd<=2'b10;
338 // mode <=2'b10;
339 end
340
341 // If a 32 bit word or 1 16 bit is r/w fro/to a 8 bit port
342 else if({dsack_0_l,dsack_1_l}==2'b01 && mode!=2'b01)
343
344 begin
345 cntl_wd<=2'b01;
346 // mode<=mode-1;
347 end
348
349
350
351 endrule
352 //.......................Latch_data when not using tristatebuffers.............................................................................
353 //In LATCH DATA state
354 //Latches on-to data and response
355 rule latch_data(master_state==LATCH_DATA);
356
357 if(berr_l==1'b0 && halt_l==1'b0)
358 begin
359 retry<=1;
360 end
361
362 else if(berr_l!=1'b0 && halt_l==1'b0)
363 begin
364 stop<=1;
365 end
366
367 else if(berr_l==1'b0)
368 begin
369
370
371 let resp_data = Resp_vme{ data:{data_in_4,
372 data_in_3,
373 data_in_2,8'b0},berr:1};
374 cpu_resp.enq(resp_data);
375 end
376
377
378 else
379 if (mode==2'b01 )//Receiving 8 bit data
380 case({dsack_0_l,dsack_1_l})
381 //......................................SLAVE PORT..............................//:-32 byte
382 //.......................................................................................
383 2'b00 :
384
385 case({addr[1],addr[0]})//Position where byte read from depends on A1,A0
386 2'b00 :begin
387 $display("Master recieved data %h addr:00",data_in_4);
388 let resp_data = Resp_vme{ data:{24'b0,
389 data_in_4},berr:0,port_type:{dsack_0_l,dsack_1_l}};
390 cpu_resp.enq(resp_data);
391 end
392 2'b01 :begin
393 let resp_data = Resp_vme{ data:{24'b0,
394
395 data_in_3},berr:0,port_type:{dsack_0_l,dsack_1_l}};
396 cpu_resp.enq(resp_data);
397 $display("Master recieved data %h addr 01",data_in_3);
398 end
399 2'b10 :begin
400 let resp_data = Resp_vme{ data:{24'b0,
401 data_in_2},berr:0,port_type:{dsack_0_l,dsack_1_l}};
402
403 $display("Master recieved data %h addr :10",data_in_2);
404 cpu_resp.enq(resp_data);
405 end
406 2'b11 :begin
407 let resp_data = Resp_vme{ data:{24'b0,
408 data_in_1},berr:0,port_type:{dsack_0_l,dsack_1_l}};
409
410
411
412 $display("Master recieved data %h addr: 11",data_in_1);
413 cpu_resp.enq(resp_data);
414 end
415 endcase
416 //If slave is an 8 bit port
417 2'b01 : begin
418
419 let resp_data = Resp_vme{data:{24'b0,data_in_4
420 },berr:0,port_type:{dsack_0_l,dsack_1_l}};
421 cpu_resp.enq(resp_data);
422
423 end
424 //if slave is a 16 bit port
425 2'b10 :
426 if (addr[0]==1'b0)
427 begin
428 let resp_data =Resp_vme{ data:{24'b0,data_in_4
429 },berr:0,port_type:{dsack_0_l,dsack_1_l}};
430
431 cpu_resp.enq(resp_data);
432 end
433 else
434
435 begin
436
437 let resp_data =Resp_vme{ data:{24'b0,data_in_3
438 },berr:0,port_type:{dsack_0_l,dsack_1_l}};
439
440 cpu_resp.enq(resp_data);
441 end
442 endcase
443 else
444 if(mode==2'b10)//Receiving 16 bit data
445
446 case({dsack_0_l,dsack_1_l})
447 //...........SLAVE PORT....................:-32 byte
448 2'b00 :
449
450 case({addr[1],addr[0]})//Position where byte read from depends on A1,A0
451 2'b00 :begin
452 let resp_data = Resp_vme{ data:{16'b0,data_in_3,
453 data_in_4},berr:0,port_type:{dsack_0_l,dsack_1_l}};
454 cpu_resp.enq(resp_data);
455 end
456
457 2'b10 :begin
458 let resp_data = Resp_vme{ data:{16'b0,data_in_1,
459 data_in_2},berr:0,port_type:{dsack_0_l,dsack_1_l}};
460
461 cpu_resp.enq(resp_data);
462 end
463 endcase
464 //If slave is an 8 bit port
465 2'b01 :begin
466
467 let resp_data = Resp_vme{data:{24'b0,data_in_4
468 },berr:0,port_type:{dsack_0_l,dsack_1_l}};
469 cpu_resp.enq(resp_data);
470
471 end
472 //if slave is a 16 bit port
473 2'b10 :
474
475 begin
476 let resp_data =Resp_vme{ data:{16'b0,data_in_3,
477 data_in_4},berr:0,port_type:{dsack_0_l,dsack_1_l}};
478
479 cpu_resp.enq(resp_data);
480 end
481 endcase
482 else
483 if(mode==2'b00)//Receiving 32 bit data
484
485 case({dsack_0_l,dsack_1_l})
486 //...........SLAVE PORT....................:-32 bit port
487 2'b00 :begin
488
489 let resp_data = Resp_vme{ data:{data_in_1,
490 data_in_2,data_in_3,data_in_4},berr:0,port_type:{dsack_0_l,dsack_1_l}};
491 $display("Master recieved data %h",{data_in_1,data_in_2,data_in_3,data_in_4});
492 cpu_resp.enq(resp_data);
493
494 end
495 //.......................................16 bit port
496 2'b10 :begin
497 let resp_data = Resp_vme{ data:{16'b0,data_in_3,
498 data_in_4},berr:0,port_type:{dsack_0_l,dsack_1_l}};
499
500 cpu_resp.enq(resp_data);
501 end
502
503 //........................If slave is an 8 bit port
504 2'b01 : begin
505
506 let resp_data = Resp_vme{data:{24'b0,data_in_4
507 },berr:0,port_type:{dsack_0_l,dsack_1_l}};
508 cpu_resp.enq(resp_data);
509
510 // $display("Data_latched",data_in_4);
511
512 end
513
514
515 endcase
516 else
517 begin
518
519 let resp_data = Resp_vme{data:{24'b0,data_in_4
520 },berr:0,port_type:{dsack_0_l,dsack_1_l}};
521 cpu_resp.enq(resp_data);
522
523
524 end
525
526 master_state<=END_REQ;
527
528
529 endrule
530 /*
531 1.Releases address and data strobe and data bus
532
533 2. DSACK lines are deasserted one cycle after
534
535 One more stage should be inserted here
536 */
537
538 rule end_req(master_state==END_REQ);
539
540 $display("\tMASTER_STATE_6:Releasing data strobes",$time);
541 ds_l<=1;
542 as_l<=1;
543 data_control<=4'b0000;
544 master_state<=ADDR_INVALID;
545 endrule
546
547 rule rel_addr(master_state==ADDR_INVALID);//Release the address and data bus when transfer is finished
548
549 if(stop==0 && retry==0)
550 begin
551 if(((dsack_0_l!=0)&&(dsack_1_l!=0))||(berr_l!=1'b0))
552 master_state<=RCV_REQ;
553 if(cntl_wd==2'b00)
554
555 begin
556 $display("\tMASTER_STATE_7:Releasing address strobes",$time);
557 addr_en<=False;
558 mode_en<=False;
559 fun_code_en<=False;
560 end
561
562 $display("Ready to receive a new request",$time);
563
564 end
565
566 else
567 master_state<=HALT;
568
569 endrule
570
571
572 rule stop_wait(master_state==HALT);
573
574 //If HALT.....resume when halt signal is negated
575 if(stop==1)
576 if (halt_l!=0)
577 begin
578 stop<=0;
579 master_state<=RCV_REQ;
580 $display("\tMASTER_STATE_7:Releasing address strobes",$time);
581 addr_en<=False;
582 mode_en<=False;
583 fun_code_en<=False;
584
585 end
586 else
587 master_state<=HALT;
588
589
590 //If Retry.........start retry cycle when bus error and halt are negated
591 else
592 if(halt_l!=0 && berr_l!=0)
593 begin
594 retry<=0;
595 master_state<=PRC_REQ_1;
596 end
597 else
598
599 master_state<=HALT;
600
601
602 endrule
603
604 //Methods for driving signals in and out of master
605
606
607 interface Vme_out vme_interface;
608
609
610 method Bit#(1) wr_as_l();
611 return as_l;
612 endmethod
613
614 method Bit#(1) wr_ds_l();
615 return ds_l;
616 endmethod
617
618
619 method Bit#(1) wr_wr_l();
620 return wr_l;
621 endmethod
622
623
624 method Action rd_dsack_0_l(Bit#(1) x);
625 dsack_0_l<=x;
626 endmethod
627
628 method Action rd_dsack_1_l(Bit#(1) y);
629 dsack_1_l<=y;
630 endmethod
631
632 method Action rd_berr_l(Bit#(1) z);
633 berr_l<=z;
634 endmethod
635
636 method Action rd_halt_l(Bit#(1) u);
637 halt_l<=u;
638 endmethod
639 endinterface
640
641 /*Methods to emulate tristate functionality*/
642
643 interface Data_bus_inf data_bus;
644
645
646 method Bit#(1) wr_siz0();
647 return mode[0];
648 endmethod
649
650 method Bit#(1) wr_siz1();
651 return mode[1];
652 endmethod
653
654 method Bit#(32) wr_addr();
655 return addr;
656 endmethod
657 method Bit#(8) wr_byte_31_24();
658 return data_out_4;
659 endmethod
660
661 method Bit#(8) wr_byte_23_16();
662 return data_out_3;
663 endmethod
664
665 method Bit#(8) wr_byte_15_8();
666 return data_out_2;
667 endmethod
668
669 method Bit#(3) wr_fun_code();
670 return fun_code;
671 endmethod
672
673 method Bit#(8) wr_byte_7_0();
674 return data_out_1;
675 endmethod
676
677 method Action rd_byte_31_24(Bit #(8) d4);
678 data_in_4<=d4;
679 endmethod
680
681 method Action rd_byte_23_16(Bit #(8) d3);
682 data_in_3<=d3;
683 endmethod
684
685 method Action rd_byte_15_8 (Bit #(8) d2);
686 data_in_2<=d2;
687 endmethod
688
689 method Action rd_byte_7_0 (Bit #(8) d1);
690 data_in_1<=d1;
691 endmethod
692
693
694 method Bit#(4) wr_en();
695 return data_control;
696 endmethod
697
698 method Bool wr_mode_en();
699 return mode_en;
700 endmethod
701
702
703 method Bool wr_addr_en();
704 return addr_en;
705 endmethod
706
707
708 method Bool wr_fun_code_en();
709 return fun_code_en;
710 endmethod
711
712
713 endinterface
714
715 method Action get_req (Req_vme req) if(!(cpu_req.notEmpty()));
716 cpu_req.enq(req);
717 endmethod
718
719 method ActionValue #(Resp_vme) resp();
720 cpu_resp.deq();
721 return cpu_resp.first();
722 endmethod
723
724
725
726 endmodule
727
728 endpackage
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750