view modules/bluespec/Pygar/core/Processor.bsv~ @ 15:a1833d9f6e3d pygar svn.16

[svn r16] Recent
author punk
date Tue, 27 Apr 2010 13:11:45 -0400
parents 6d461680c6d9
children
line wrap: on
line source
1 /// The MIT License
3 // Copyright (c) 2009 Massachusetts Institute of Technology
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE.
23 import Connectable::*;
24 import GetPut::*;
25 import ClientServer::*;
26 import RegFile::*;
28 import FIFO::*;
29 import FIFOF::*;
30 import SFIFO::*;
31 import RWire::*;
33 import Trace::*;
34 import BFIFO::*;
35 import MemTypes::*;
36 import ProcTypes::*;
37 import BRegFile::*;
38 import BranchPred::*;
39 //import PathTypes::*; This is only there to force the debugging
41 //AWB includes
42 `include "asim/provides/low_level_platform_interface.bsh"
43 `include "asim/provides/soft_connections.bsh"
44 `include "asim/provides/common_services.bsh"
46 // Local includes
47 //`include "asim/provides/processor_library.bsh" (included above directly)
48 `include "asim/rrr/remote_server_stub_AUDIOCORERRR.bsh"
49 `include "asim/provides/common_services.bsh"
50 `include "asim/dict/STATS_PROCESSOR.bsh"
51 `include "asim/provides/audio_pipe_types.bsh"
53 // Local includes. Look for the correspondingly named .awb files
54 // workspace/labs/src/mit-6.375/modules/bluespec/mit-6.375/common/
55 // to find the actual Bluespec files which are used to generate
56 // these includes. These files are specific to this audio processing
57 // pipeline
59 `include "asim/provides/audio_pipe_types.bsh"
61 //interface CPUToHost;
62 // method Bit#(32) cpuToHost(int req);
63 //endinterface
65 interface Proc;
67 // Interface from processor to caches
68 interface Client#(DataReq,DataResp) dmem_client;
69 interface Client#(InstReq,InstResp) imem_client;
71 // Interface for enabling/disabling statistics on the rest of the core
72 interface Get#(Bool) statsEn_get;
74 // // Interface to host
75 // interface CPUToHost tohost;
77 // Interface to Audio Pipeline
78 interface AudioOut audioOut;
80 endinterface
82 //The full interface for this is as below in the common file for audioProcessorTypes.bsv
83 interface AudioOut;
84 interface Get#(AudioProcessorUnit) audioSampleOutput;
85 endinterface
87 //interface AudioIn;
88 // interface Put#(AudioProcessorUnit) audioSampleInput;
89 //endinterface
91 typedef enum { PCgen, Exec, Writeback } Stage deriving(Eq,Bits);
93 //-----------------------------------------------------------
94 // Register file module
95 //-----------------------------------------------------------
97 interface BRFile;
98 method Action wr( Rindx rindx, Bit#(32) data );
99 method Bit#(32) rd1( Rindx rindx );
100 method Bit#(32) rd2( Rindx rindx );
101 endinterface
103 module mkBRFile( BRFile );
105 RegFile#(Rindx,Bit#(32)) rfile <- mkBRegFile();
107 method Action wr( Rindx rindx, Bit#(32) data );
108 rfile.upd( rindx, data );
109 endmethod
111 method Bit#(32) rd1( Rindx rindx );
112 return ( rindx == 0 ) ? 0 : rfile.sub(rindx);
113 endmethod
115 method Bit#(32) rd2( Rindx rindx );
116 return ( rindx == 0 ) ? 0 : rfile.sub(rindx);
117 endmethod
119 endmodule
121 //-----------------------------------------------------------
122 // Helper functions
123 //-----------------------------------------------------------
125 function Bit#(32) slt( Bit#(32) val1, Bit#(32) val2 );
126 return zeroExtend( pack( signedLT(val1,val2) ) );
127 endfunction
129 function Bit#(32) sltu( Bit#(32) val1, Bit#(32) val2 );
130 return zeroExtend( pack( val1 < val2 ) );
131 endfunction
133 function Bit#(32) rshft( Bit#(32) val );
134 return zeroExtend(val[4:0]);
135 endfunction
138 //-----------------------------------------------------------
139 // Find funct for wbQ
140 //-----------------------------------------------------------
141 function Bool findwbf(Rindx fVal, WBResult cmpVal);
142 case (cmpVal) matches
143 tagged WB_ALU {data:.res, dest:.rd} :
144 return (fVal == rd);
145 tagged WB_Load .rd :
146 return (fVal == rd);
147 tagged WB_Store .st :
148 return False;
149 tagged WB_Host .x :
150 return False;
151 endcase
152 endfunction
155 //-----------------------------------------------------------
156 // Stall funct for wbQ
157 //-----------------------------------------------------------
158 function Bool stall(Instr inst, SFIFO#(WBResult, Rindx) f);
159 case (inst) matches
160 // -- Memory Ops ------------------------------------------------
161 tagged LW .it :
162 return f.find(it.rbase);
163 tagged SW {rsrc:.dreg, rbase:.addr, offset:.o} :
164 return (f.find(addr) || f.find2(dreg));
166 // -- Simple Ops ------------------------------------------------
167 tagged ADDIU .it : return f.find(it.rsrc);
168 tagged SLTI .it : return f.find(it.rsrc);
169 tagged SLTIU .it : return f.find(it.rsrc);
170 tagged ANDI .it : return f.find(it.rsrc);
171 tagged ORI .it : return f.find(it.rsrc);
172 tagged XORI .it : return f.find(it.rsrc);
174 tagged LUI .it : return f.find(it.rdst); //this rds/wrs itself
175 tagged SLL .it : return f.find(it.rsrc);
176 tagged SRL .it : return f.find(it.rsrc);
177 tagged SRA .it : return f.find(it.rsrc);
178 tagged SLLV .it : return (f.find(it.rsrc) || f.find(it.rshamt));
179 tagged SRLV .it : return (f.find(it.rsrc) || f.find(it.rshamt));
180 tagged SRAV .it : return (f.find(it.rsrc) || f.find(it.rshamt));
181 tagged ADDU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
182 tagged SUBU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
183 tagged AND .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
184 tagged OR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
185 tagged XOR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
186 tagged NOR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
187 tagged SLT .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
188 tagged SLTU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
191 // -- Branches --------------------------------------------------
193 tagged BLEZ .it : return (f.find(it.rsrc));
194 tagged BGTZ .it : return (f.find(it.rsrc));
195 tagged BLTZ .it : return (f.find(it.rsrc));
196 tagged BGEZ .it : return (f.find(it.rsrc));
197 tagged BEQ .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
198 tagged BNE .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));
200 // -- Jumps -----------------------------------------------------
202 tagged J .it : return False;
203 tagged JR .it : return f.find(it.rsrc);
204 tagged JALR .it : return f.find(it.rsrc);
205 tagged JAL .it : return False;
207 // -- Cop0 ------------------------------------------------------
209 tagged MTC0 .it : return f.find(it.rsrc);
210 tagged MFC0 .it : return False;
212 // -- Illegal ---------------------------------------------------
214 default : return False;
216 endcase
217 endfunction
218 //-----------------------------------------------------------
219 // Reference processor
220 //-----------------------------------------------------------
223 //(* doc = "synthesis attribute ram_style mkProc distributed;" *)
224 //(* synthesize *)
226 module [CONNECTED_MODULE] mkProc( Proc );
228 //-----------------------------------------------------------
229 // Debug port
231 ServerStub_AUDIOCORERRR server_stub <- mkServerStub_AUDIOCORERRR();
234 //-----------------------------------------------------------
235 // State
237 // Standard processor state
239 Reg#(Addr) pc <- mkReg(32'h00001000);
240 Reg#(Epoch) epoch <- mkReg(0);
241 Reg#(Stage) stage <- mkReg(PCgen);
242 BRFile rf <- mkBRFile;
244 // Branch Prediction
245 BranchPred bp <- mkBranchPred();
246 FIFO#(PCStat) execpc <- mkLFIFO();
248 // Pipelines
249 FIFO#(PCStat) pcQ <-mkSizedFIFO(3);
250 SFIFO#(WBResult, Rindx) wbQ <-mkSFIFO(findwbf);
252 Reg#(Bit#(32)) cp0_tohost <- mkReg(0);
253 Reg#(Bit#(32)) cp0_fromhost <- mkReg(0);
254 Reg#(Bool) cp0_statsEn <- mkReg(False);
256 // Memory request/response state
258 FIFO#(InstReq) instReqQ <- mkBFIFO1();
259 FIFO#(InstResp) instRespQ <- mkFIFO();
261 FIFO#(DataReq) dataReqQ <- mkBFIFO1();
262 FIFO#(DataResp) dataRespQ <- mkFIFO();
264 // Audio I/O
265 FIFO#(AudioProcessorUnit) inAudioFifo <- mkFIFO;
266 FIFO#(AudioProcessorUnit) outAudioFifo <- mkFIFO;
269 // Statistics state (2010)
270 // Reg#(Stat) num_cycles <- mkReg(0);
271 // Reg#(Stat) num_inst <- mkReg(0);
273 //Or:
274 // Statistics state
275 STAT num_cycles <- mkStatCounter(`STATS_PROCESSOR_CYCLE_COUNT);
276 STAT num_inst <- mkStatCounter(`STATS_PROCESSOR_INST_COUNT);
278 //-----------------------------------------------------------
279 // Rules
281 (* descending_urgency = "exec, pcgen" *)
282 rule pcgen; //( stage == PCgen );
283 let pc_plus4 = pc + 4;
285 traceTiny("mkProc", "pc",pc);
286 traceTiny("mkProc", "pcgen","P");
287 instReqQ.enq( LoadReq{ addr:pc, tag:epoch} );
289 let next_pc = bp.get(pc);
290 if (next_pc matches tagged Valid .npc)
291 begin
292 pcQ.enq(PCStat {qpc:pc, qnxtpc:npc, qepoch:epoch});
293 pc <= npc;
294 end
295 else
296 begin
297 pcQ.enq(PCStat {qpc:pc, qnxtpc:pc_plus4, qepoch:epoch});
298 pc <= pc_plus4;
299 end
301 endrule
303 rule discard (instRespQ.first() matches tagged LoadResp .ld
304 &&& ld.tag != epoch);
305 traceTiny("mkProc", "stage", "D");
306 instRespQ.deq();
307 endrule
309 (* conflict_free = "exec, writeback" *)
310 rule exec (instRespQ.first() matches tagged LoadResp.ld
311 &&& (ld.tag == epoch)
312 &&& unpack(ld.data) matches .inst
313 &&& !stall(inst, wbQ));
315 // Some abbreviations
316 let sext = signExtend;
317 let zext = zeroExtend;
318 let sra = signedShiftRight;
320 // Get the instruction
322 instRespQ.deq();
323 Instr inst
324 = case ( instRespQ.first() ) matches
325 tagged LoadResp .ld : return unpack(ld.data);
326 tagged StoreResp .st : return ?;
327 endcase;
329 // Get the PC info
330 let instrpc = pcQ.first().qpc;
331 let pc_plus4 = instrpc + 4;
333 Bool branchTaken = False;
334 Addr newPC = pc_plus4;
336 // Tracing
337 traceTiny("mkProc", "exec","X");
338 traceTiny("mkProc", "exInstTiny",inst);
339 traceFull("mkProc", "exInstFull",inst);
341 case ( inst ) matches
343 // -- Memory Ops ------------------------------------------------
345 tagged LW .it :
346 begin
347 Addr addr = rf.rd1(it.rbase) + sext(it.offset);
348 dataReqQ.enq( LoadReq{ addr:addr, tag:zeroExtend(it.rdst) } );
349 wbQ.enq(tagged WB_Load it.rdst);
350 end
352 tagged SW .it :
353 begin
354 Addr addr = rf.rd1(it.rbase) + sext(it.offset);
355 dataReqQ.enq( StoreReq{ tag:0, addr:addr, data:rf.rd2(it.rsrc) } );
356 wbQ.enq(tagged WB_Store);
357 end
359 // -- Simple Ops ------------------------------------------------
361 tagged ADDIU .it :
362 begin
363 Bit#(32) result = rf.rd1(it.rsrc) + sext(it.imm);
364 wbQ.enq(tagged WB_ALU {data:result, dest:it.rdst});
365 end
366 tagged SLTI .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:slt( rf.rd1(it.rsrc), sext(it.imm) )});
367 tagged SLTIU .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:sltu( rf.rd1(it.rsrc), sext(it.imm) ) });
368 tagged ANDI .it :
369 begin
370 Bit#(32) zext_it_imm = zext(it.imm);
371 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) & zext_it_imm)} );
372 end
373 tagged ORI .it :
374 begin
375 Bit#(32) zext_it_imm = zext(it.imm);
376 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) | zext_it_imm)} );
377 end
378 tagged XORI .it :
379 begin
380 Bit#(32) zext_it_imm = zext(it.imm);
381 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) ^ zext_it_imm )});
382 end
383 tagged LUI .it :
384 begin
385 Bit#(32) zext_it_imm = zext(it.imm);
386 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(zext_it_imm << 32'd16) });
387 end
389 tagged SLL .it :
390 begin
391 Bit#(32) zext_it_shamt = zext(it.shamt);
392 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << zext_it_shamt )} );
393 end
394 tagged SRL .it :
395 begin
396 Bit#(32) zext_it_shamt = zext(it.shamt);
397 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> zext_it_shamt )});
398 end
399 tagged SRA .it :
400 begin
401 Bit#(32) zext_it_shamt = zext(it.shamt);
402 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), zext_it_shamt )});
403 end
404 tagged SLLV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << rshft(rf.rd2(it.rshamt)) )});
405 tagged SRLV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> rshft(rf.rd2(it.rshamt)) )} );
406 tagged SRAV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), rshft(rf.rd2(it.rshamt)) ) });
407 tagged ADDU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) + rf.rd2(it.rsrc2) )} );
408 tagged SUBU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) - rf.rd2(it.rsrc2) )} );
409 tagged AND .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) & rf.rd2(it.rsrc2) )} );
410 tagged OR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2) )} );
411 tagged XOR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) ^ rf.rd2(it.rsrc2) )} );
412 tagged NOR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(~(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2)) )} );
413 tagged SLT .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:slt( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) });
414 tagged SLTU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sltu( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) });
416 // -- Branches --------------------------------------------------
418 tagged BLEZ .it :
419 if ( signedLE( rf.rd1(it.rsrc), 0 ) )
420 begin
421 newPC = pc_plus4 + (sext(it.offset) << 2);
422 branchTaken = True;
423 end
425 tagged BGTZ .it :
426 if ( signedGT( rf.rd1(it.rsrc), 0 ) )
427 begin
428 newPC = pc_plus4 + (sext(it.offset) << 2);
429 branchTaken = True;
430 end
432 tagged BLTZ .it :
433 if ( signedLT( rf.rd1(it.rsrc), 0 ) )
434 begin
435 newPC = pc_plus4 + (sext(it.offset) << 2);
436 branchTaken = True;
437 end
439 tagged BGEZ .it :
440 if ( signedGE( rf.rd1(it.rsrc), 0 ) )
441 begin
442 newPC = pc_plus4 + (sext(it.offset) << 2);
443 branchTaken = True;
444 end
446 tagged BEQ .it :
447 if ( rf.rd1(it.rsrc1) == rf.rd2(it.rsrc2) )
448 begin
449 newPC = pc_plus4 + (sext(it.offset) << 2);
450 branchTaken = True;
451 end
453 tagged BNE .it :
454 if ( rf.rd1(it.rsrc1) != rf.rd2(it.rsrc2) )
455 begin
456 newPC = pc_plus4 + (sext(it.offset) << 2);
457 branchTaken = True;
458 end
460 // -- Jumps -----------------------------------------------------
462 tagged J .it :
463 begin
464 newPC = { pc_plus4[31:28], it.target, 2'b0 };
465 branchTaken = True;
466 end
468 tagged JR .it :
469 begin
470 newPC = rf.rd1(it.rsrc);
471 branchTaken = True;
472 end
474 tagged JAL .it :
475 begin
476 wbQ.enq(tagged WB_ALU {dest:31, data:pc_plus4 });
477 newPC = { pc_plus4[31:28], it.target, 2'b0 };
478 branchTaken = True;
479 end
481 tagged JALR .it :
482 begin
483 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:pc_plus4 });
484 newPC = rf.rd1(it.rsrc);
485 branchTaken = True;
486 end
488 // -- Cop0 ------------------------------------------------------
490 tagged MTC0 .it :
491 begin
492 case ( it.cop0dst )
493 5'd10 : cp0_statsEn <= unpack(truncate(rf.rd1(it.rsrc)));
494 5'd21 : cp0_tohost <= truncate(rf.rd1(it.rsrc));
495 default :
496 $display( " RTL-ERROR : %m : Illegal MTC0 cop0dst register!" );
497 endcase
498 wbQ.enq(tagged WB_Host 0); //no idea wwhat this actually should be.
499 end
501 //this is host stuff?
502 tagged MFC0 .it :
503 begin
504 case ( it.cop0src )
505 // not actually an ALU instruction but don't have the format otherwise
506 5'd10 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:zext(pack(cp0_statsEn)) });
507 5'd20 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_fromhost });
508 5'd21 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_tohost });
509 default :
510 $display( " RTL-ERROR : %m : Illegal MFC0 cop0src register!" );
511 endcase
512 end
514 // -- Illegal ---------------------------------------------------
516 default :
517 $display( " RTL-ERROR : %m : Illegal instruction !" );
519 endcase
521 //evaluate branch prediction
522 Addr ppc = pcQ.first().qnxtpc; //predicted branch
523 if (ppc != newPC) //prediction wrong
524 begin
525 epoch <= pcQ.first().qepoch + 1;
526 bp.upd(instrpc, newPC); //update branch predictor
527 pcQ.clear();
528 pc <= newPC;
529 end
530 else
531 pcQ.deq();
533 if ( cp0_statsEn )
534 num_inst.incr();
536 endrule
538 rule writeback; // ( stage == Writeback );
539 traceTiny("mkProc", "writeback","W");
542 // get what to do off the writeback queue
543 wbQ.deq();
544 case (wbQ.first()) matches
545 tagged WB_ALU {data:.res, dest:.rdst} : rf.wr(rdst, res);
546 tagged WB_Load .regWr :
547 begin
548 dataRespQ.deq();
549 if (dataRespQ.first() matches tagged LoadResp .ld)
550 rf.wr(truncate(ld.tag), ld.data); // no need to use Rindx from queue? Duplicate?
551 end
552 tagged WB_Store : dataRespQ.deq();
553 tagged WB_Host .dat : noAction;
554 endcase
556 endrule
558 rule inc_num_cycles;
559 if ( cp0_statsEn )
560 num_cycles.incr();
561 endrule
563 (* conservative_implicit_conditions *)
564 rule handleCPUToHost;
565 let req <- server_stub.acceptRequest_ReadCPUToHost();
566 case (req)
567 0: server_stub.sendResponse_ReadCPUToHost(cp0_tohost);
568 1: server_stub.sendResponse_ReadCPUToHost(pc);
569 2: server_stub.sendResponse_ReadCPUToHost(zeroExtend(pack(stage)));
570 endcase
571 endrule
573 // for now, we don't do anything.
574 rule connectAudioReqResp;
575 $display("FIR copies a data");
576 outAudioFifo.enq(inAudioFifo.first);
577 outAudioFifo.deq;
578 endrule
580 // Server items & rules:
582 rule feedInput;
583 let command <- server_stub.acceptRequest_SendUnprocessedStream();
584 AudioProcessorControl ctrl = unpack(truncate(command.ctrl));
586 if(ctrl == EndOfFile)
587 begin
588 inAudioFifo.enq(tagged EndOfFile);
589 end
590 else
591 begin
592 inAudioFifo.enq(tagged Sample unpack(truncate(command.sample)));
593 end
594 endrule
597 //-----------------------------------------------------------
598 // Methods
600 interface Client imem_client;
601 interface Get request = toGet(instReqQ);
602 interface Put response = toPut(instRespQ);
603 endinterface
605 interface Client dmem_client;
606 interface Get request = toGet(dataReqQ);
607 interface Put response = toPut(dataRespQ);
608 endinterface
610 interface Get statsEn_get = toGet(asReg(cp0_statsEn));
612 // interface CPUToHost tohost;
613 // method Bit#(32) cpuToHost(int req);
614 // return (case (req)
615 // 0: cp0_tohost;
616 // 1: pc;
617 // 2: zeroExtend(pack(stage));
618 // endcase);
619 // endmethod
620 // endinterface
622 interface AudioOut audio;
623 interface audioSampleOutput = fifoToGet(outAudioFifo);
624 endinterface
627 endmodule