Mercurial > pygar
view modules/bluespec/Pygar/core/Processor.bsv @ 56:4449e17a2237 pygar svn.57
[svn r57] added useless stuff that should work but doesn't.
author | rlm |
---|---|
date | Sun, 09 May 2010 23:12:15 -0400 |
parents | 2991344775f8 |
children | 1d5cbb5343d2 |
line wrap: on
line source
1 // The MIT License3 // Copyright (c) 2009 Massachusetts Institute of Technology5 // Permission is hereby granted, free of charge, to any person obtaining a copy6 // of this software and associated documentation files (the "Software"), to deal7 // in the Software without restriction, including without limitation the rights8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell9 // copies of the Software, and to permit persons to whom the Software is10 // furnished to do so, subject to the following conditions:12 // The above copyright notice and this permission notice shall be included in13 // all copies or substantial portions of the Software.15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19 // 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 IN21 // THE SOFTWARE.24 import Connectable::*;25 import GetPut::*;26 import ClientServer::*;27 import RegFile::*;29 import FIFO::*;30 import FIFOF::*;31 import SFIFO::*;32 import RWire::*;34 import Trace::*;35 import BFIFO::*;36 import MemTypes::*;37 import ProcTypes::*;38 import BRegFile::*;39 import BranchPred::*;40 //import PathTypes::*; This is only there to force the debugging42 //AWB includes43 `include "asim/provides/low_level_platform_interface.bsh"44 `include "asim/provides/soft_connections.bsh"45 `include "asim/provides/common_services.bsh"47 // Local includes48 //`include "asim/provides/processor_library.bsh" (included above directly)50 `include "asim/provides/common_services.bsh"51 `include "asim/provides/processor_library.bsh"53 // Local includes. Look for the correspondingly named .awb files54 // workspace/labs/src/mit-6.375/modules/bluespec/mit-6.375/common/55 // to find the actual Bluespec files which are used to generate56 // these includes. These files are specific to this audio processing57 // pipeline59 `include "asim/provides/audio_pipe_types.bsh"61 //interface CPUToHost;62 // method Bit#(32) cpuToHost(int req);63 //endinterface65 interface Proc;67 // Interface from processor to caches68 interface Client#(DataReq,DataResp) dmem_client;69 interface Client#(InstReq,InstResp) imem_client;71 // Interface for enabling/disabling statistics on the rest of the core72 interface Get#(Bool) statsEn_get;74 // // Interface to host75 // interface CPUToHost tohost;77 // Interface to Audio Pipeline78 interface Get#(AudioProcessorUnit) sampleOutput;79 interface Put#(AudioProcessorUnit) sampleInput;81 endinterface83 typedef enum { PCgen, Exec, Writeback } Stage deriving(Eq,Bits);85 //-----------------------------------------------------------86 // Register file module87 //-----------------------------------------------------------89 interface BRFile;90 method Action wr( Rindx rindx, Bit#(32) data );91 method Bit#(32) rd1( Rindx rindx );92 method Bit#(32) rd2( Rindx rindx );93 endinterface95 module mkBRFile( BRFile );97 RegFile#(Rindx,Bit#(32)) rfile <- mkBRegFile();99 method Action wr( Rindx rindx, Bit#(32) data );100 rfile.upd( rindx, data );101 endmethod103 method Bit#(32) rd1( Rindx rindx );104 return ( rindx == 0 ) ? 0 : rfile.sub(rindx);105 endmethod107 method Bit#(32) rd2( Rindx rindx );108 return ( rindx == 0 ) ? 0 : rfile.sub(rindx);109 endmethod111 endmodule113 //-----------------------------------------------------------114 // Helper functions115 //-----------------------------------------------------------117 function Bit#(32) slt( Bit#(32) val1, Bit#(32) val2 );118 return zeroExtend( pack( signedLT(val1,val2) ) );119 endfunction121 function Bit#(32) sltu( Bit#(32) val1, Bit#(32) val2 );122 return zeroExtend( pack( val1 < val2 ) );123 endfunction125 function Bit#(32) rshft( Bit#(32) val );126 return zeroExtend(val[4:0]);127 endfunction130 //-----------------------------------------------------------131 // Find funct for wbQ132 //-----------------------------------------------------------133 function Bool findwbf(Rindx fVal, WBResult cmpVal);134 case (cmpVal) matches135 tagged WB_ALU {data:.res, dest:.rd} :136 return (fVal == rd);137 tagged WB_Load .rd :138 return (fVal == rd);139 tagged WB_Store .st :140 return False;141 tagged WB_Host .x :142 return False;143 endcase144 endfunction147 //-----------------------------------------------------------148 // Stall funct for wbQ149 //-----------------------------------------------------------150 function Bool stall(Instr inst, SFIFO#(WBResult, Rindx) f);151 case (inst) matches152 // -- Memory Ops ------------------------------------------------153 tagged LW .it :154 return f.find(it.rbase);155 tagged SW {rsrc:.dreg, rbase:.addr, offset:.o} :156 return (f.find(addr) || f.find2(dreg));158 // -- Simple Ops ------------------------------------------------159 tagged ADDIU .it : return f.find(it.rsrc);160 tagged SLTI .it : return f.find(it.rsrc);161 tagged SLTIU .it : return f.find(it.rsrc);162 tagged ANDI .it : return f.find(it.rsrc);163 tagged ORI .it : return f.find(it.rsrc);164 tagged XORI .it : return f.find(it.rsrc);166 tagged LUI .it : return f.find(it.rdst); //this rds/wrs itself167 tagged SLL .it : return f.find(it.rsrc);168 tagged SRL .it : return f.find(it.rsrc);169 tagged SRA .it : return f.find(it.rsrc);170 tagged SLLV .it : return (f.find(it.rsrc) || f.find(it.rshamt));171 tagged SRLV .it : return (f.find(it.rsrc) || f.find(it.rshamt));172 tagged SRAV .it : return (f.find(it.rsrc) || f.find(it.rshamt));173 tagged ADDU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));174 tagged SUBU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));175 tagged AND .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));176 tagged OR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));177 tagged XOR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));178 tagged NOR .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));179 tagged SLT .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));180 tagged SLTU .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));183 // -- Branches --------------------------------------------------185 tagged BLEZ .it : return (f.find(it.rsrc));186 tagged BGTZ .it : return (f.find(it.rsrc));187 tagged BLTZ .it : return (f.find(it.rsrc));188 tagged BGEZ .it : return (f.find(it.rsrc));189 tagged BEQ .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));190 tagged BNE .it : return (f.find(it.rsrc1) || f.find2(it.rsrc2));192 // -- Jumps -----------------------------------------------------194 tagged J .it : return False;195 tagged JR .it : return f.find(it.rsrc);196 tagged JALR .it : return f.find(it.rsrc);197 tagged JAL .it : return False;199 // -- Cop0 ------------------------------------------------------201 tagged MTC0 .it : return f.find(it.rsrc);202 tagged MFC0 .it : return False;204 // -- Illegal ---------------------------------------------------206 default : return False;208 endcase209 endfunction210 //-----------------------------------------------------------211 // Reference processor212 //-----------------------------------------------------------215 //(* doc = "synthesis attribute ram_style mkProc distributed;" *)216 //(* synthesize *)218 module mkProc( Proc );220 //-----------------------------------------------------------221 // State223 // Standard processor state225 Reg#(Addr) pc <- mkReg(32'h00001000);226 Reg#(Epoch) epoch <- mkReg(0);227 Reg#(Stage) stage <- mkReg(PCgen);228 BRFile rf <- mkBRFile;230 // Branch Prediction231 BranchPred bp <- mkBranchPred();232 FIFO#(PCStat) execpc <- mkLFIFO();234 // Pipelines235 FIFO#(PCStat) pcQ <-mkSizedFIFO(3);236 SFIFO#(WBResult, Rindx) wbQ <-mkSFIFO(findwbf);238 // NEED TO ADD CAPABILITY FOR RESET (should be able to just say if I get valid in and these are flagged, clear them.239 Reg#(Bit#(32)) cp0_tohost <- mkReg(0);240 Reg#(Bit#(32)) cp0_fromhost <- mkReg(0);241 Reg#(Bool) cp0_statsEn <- mkReg(False);242 Reg#(Bool) cp0_audioEOF <- mkReg(False); // Register to let code that EOF is reached243 Reg#(Bool) cp0_progComp <- mkReg(False); // Register to let processor know that the program is complete (as this terminates)245 // Memory request/response state247 FIFO#(InstReq) instReqQ <- mkBFIFO1();248 FIFO#(InstResp) instRespQ <- mkFIFO();250 FIFO#(DataReq) dataReqQ <- mkBFIFO1();251 FIFO#(DataResp) dataRespQ <- mkFIFO();253 // Audio I/O254 FIFO#(AudioProcessorUnit) inAudioFifo <- mkSizedFIFO(512);255 FIFO#(AudioProcessorUnit) outAudioFifo <- mkFIFO;258 // Statistics state (2010)259 // Reg#(Stat) num_cycles <- mkReg(0);260 // Reg#(Stat) num_inst <- mkReg(0);262 //Or:263 // Statistics state265 //rlm: removing these to avoid their broken stupidness.266 //STAT num_cycles <- mkStatCounter(`STATS_PROCESSOR_CYCLE_COUNT);267 //STAT num_inst <- mkStatCounter(`STATS_PROCESSOR_INST_COUNT);269 //-----------------------------------------------------------270 // Rules272 (* descending_urgency = "exec, pcgen" *)273 rule pcgen; //( stage == PCgen );274 let pc_plus4 = pc + 4;276 traceTiny("mkProc", "pc",pc);277 traceTiny("mkProc", "pcgen","P");278 instReqQ.enq( LoadReq{ addr:pc, tag:epoch} );280 let next_pc = bp.get(pc);281 if (next_pc matches tagged Valid .npc)282 begin283 pcQ.enq(PCStat {qpc:pc, qnxtpc:npc, qepoch:epoch});284 pc <= npc;285 end286 else287 begin288 pcQ.enq(PCStat {qpc:pc, qnxtpc:pc_plus4, qepoch:epoch});289 pc <= pc_plus4;290 end292 endrule294 rule discard (instRespQ.first() matches tagged LoadResp .ld295 &&& ld.tag != epoch);296 traceTiny("mkProc", "stage", "D");297 instRespQ.deq();298 endrule300 (* conflict_free = "exec, writeback" *)301 rule exec (instRespQ.first() matches tagged LoadResp.ld302 &&& (ld.tag == epoch)303 &&& unpack(ld.data) matches .inst304 &&& !stall(inst, wbQ));306 // Some abbreviations307 let sext = signExtend;308 let zext = zeroExtend;309 let sra = signedShiftRight;311 // Get the instruction313 instRespQ.deq();314 Instr inst315 = case ( instRespQ.first() ) matches316 tagged LoadResp .ld : return unpack(ld.data);317 tagged StoreResp .st : return ?;318 endcase;320 // Get the PC info321 let instrpc = pcQ.first().qpc;322 let pc_plus4 = instrpc + 4;324 Bool branchTaken = False;325 Addr newPC = pc_plus4;327 // Tracing328 traceTiny("mkProc", "exec","X");329 traceTiny("mkProc", "exInstTiny",inst);330 traceFull("mkProc", "exInstFull",inst);332 case ( inst ) matches334 // -- Memory Ops ------------------------------------------------336 tagged LW .it :337 begin338 Addr addr = rf.rd1(it.rbase) + sext(it.offset);339 dataReqQ.enq( LoadReq{ addr:addr, tag:zeroExtend(it.rdst) } );340 wbQ.enq(tagged WB_Load it.rdst);341 end343 tagged SW .it :344 begin345 Addr addr = rf.rd1(it.rbase) + sext(it.offset);346 dataReqQ.enq( StoreReq{ tag:0, addr:addr, data:rf.rd2(it.rsrc) } );347 wbQ.enq(tagged WB_Store);348 end350 // -- Simple Ops ------------------------------------------------352 tagged ADDIU .it :353 begin354 Bit#(32) result = rf.rd1(it.rsrc) + sext(it.imm);355 wbQ.enq(tagged WB_ALU {data:result, dest:it.rdst});356 end357 tagged SLTI .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:slt( rf.rd1(it.rsrc), sext(it.imm) )});358 tagged SLTIU .it : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:sltu( rf.rd1(it.rsrc), sext(it.imm) ) });359 tagged ANDI .it :360 begin361 Bit#(32) zext_it_imm = zext(it.imm);362 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) & zext_it_imm)} );363 end364 tagged ORI .it :365 begin366 Bit#(32) zext_it_imm = zext(it.imm);367 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:(rf.rd1(it.rsrc) | zext_it_imm)} );368 end369 tagged XORI .it :370 begin371 Bit#(32) zext_it_imm = zext(it.imm);372 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) ^ zext_it_imm )});373 end374 tagged LUI .it :375 begin376 Bit#(32) zext_it_imm = zext(it.imm);377 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(zext_it_imm << 32'd16) });378 end380 tagged SLL .it :381 begin382 Bit#(32) zext_it_shamt = zext(it.shamt);383 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << zext_it_shamt )} );384 end385 tagged SRL .it :386 begin387 Bit#(32) zext_it_shamt = zext(it.shamt);388 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> zext_it_shamt )});389 end390 tagged SRA .it :391 begin392 Bit#(32) zext_it_shamt = zext(it.shamt);393 wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), zext_it_shamt )});394 end395 tagged SLLV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) << rshft(rf.rd2(it.rshamt)) )});396 tagged SRLV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc) >> rshft(rf.rd2(it.rshamt)) )} );397 tagged SRAV .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sra( rf.rd1(it.rsrc), rshft(rf.rd2(it.rshamt)) ) });398 tagged ADDU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) + rf.rd2(it.rsrc2) )} );399 tagged SUBU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) - rf.rd2(it.rsrc2) )} );400 tagged AND .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) & rf.rd2(it.rsrc2) )} );401 tagged OR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2) )} );402 tagged XOR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(rf.rd1(it.rsrc1) ^ rf.rd2(it.rsrc2) )} );403 tagged NOR .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:(~(rf.rd1(it.rsrc1) | rf.rd2(it.rsrc2)) )} );404 tagged SLT .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:slt( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) });405 tagged SLTU .it : wbQ.enq(tagged WB_ALU {dest: it.rdst, data:sltu( rf.rd1(it.rsrc1), rf.rd2(it.rsrc2) ) });407 // -- Branches --------------------------------------------------409 tagged BLEZ .it :410 if ( signedLE( rf.rd1(it.rsrc), 0 ) )411 begin412 newPC = pc_plus4 + (sext(it.offset) << 2);413 branchTaken = True;414 end416 tagged BGTZ .it :417 if ( signedGT( rf.rd1(it.rsrc), 0 ) )418 begin419 newPC = pc_plus4 + (sext(it.offset) << 2);420 branchTaken = True;421 end423 tagged BLTZ .it :424 if ( signedLT( rf.rd1(it.rsrc), 0 ) )425 begin426 newPC = pc_plus4 + (sext(it.offset) << 2);427 branchTaken = True;428 end430 tagged BGEZ .it :431 if ( signedGE( rf.rd1(it.rsrc), 0 ) )432 begin433 newPC = pc_plus4 + (sext(it.offset) << 2);434 branchTaken = True;435 end437 tagged BEQ .it :438 if ( rf.rd1(it.rsrc1) == rf.rd2(it.rsrc2) )439 begin440 newPC = pc_plus4 + (sext(it.offset) << 2);441 branchTaken = True;442 end444 tagged BNE .it :445 if ( rf.rd1(it.rsrc1) != rf.rd2(it.rsrc2) )446 begin447 newPC = pc_plus4 + (sext(it.offset) << 2);448 branchTaken = True;449 end451 // -- Jumps -----------------------------------------------------453 tagged J .it :454 begin455 newPC = { pc_plus4[31:28], it.target, 2'b0 };456 branchTaken = True;457 end459 tagged JR .it :460 begin461 newPC = rf.rd1(it.rsrc);462 branchTaken = True;463 end465 tagged JAL .it :466 begin467 wbQ.enq(tagged WB_ALU {dest:31, data:pc_plus4 });468 newPC = { pc_plus4[31:28], it.target, 2'b0 };469 branchTaken = True;470 end472 tagged JALR .it :473 begin474 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:pc_plus4 });475 newPC = rf.rd1(it.rsrc);476 branchTaken = True;477 end479 // -- Cop0 ------------------------------------------------------481 tagged MTC0 .it : //Recieve things from host computer482 begin483 // $display( " PROCESSOR MTC0 call\n");484 case ( it.cop0dst )485 5'd10 : cp0_statsEn <= unpack(truncate(rf.rd1(it.rsrc)));486 5'd21 : cp0_tohost <= truncate(rf.rd1(it.rsrc));487 5'd26 : cp0_progComp <= unpack(truncate(rf.rd1(it.rsrc))); //states audio program completed and termination okay488 5'd27 : outAudioFifo.enq(tagged Sample unpack(truncate(rf.rd1(it.rsrc)))); //Bit size is 16 not 32489 default :490 $display( " RTL-ERROR : %m : Illegal MTC0 cop0dst register!" );491 endcase492 wbQ.enq(tagged WB_Host 0); //no idea wwhat this actually should be.493 end495 //this is host stuff?496 tagged MFC0 .it : //Things out497 begin498 case ( it.cop0src )499 // not actually an ALU instruction but don't have the format otherwise500 5'd10 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:zext(pack(cp0_statsEn)) });501 5'd20 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_fromhost });502 5'd21 : wbQ.enq(tagged WB_ALU {dest:it.rdst, data:cp0_tohost });503 5'd25 : begin504 // $display( "**** EOF Requested\n ");505 let sample = inAudioFifo.first();506 case (sample) matches507 tagged EndOfFile :508 begin509 $display("PROCESSOR sent toC EOF");510 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:zext(pack(True)) }); // Reading clears bit511 inAudioFifo.deq;512 end513 tagged Sample .data:514 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:zext(pack(False)) }); // Reading clears bit515 endcase516 end517 5'd28 : begin518 // $display( "***** Reqesting Sample \n");519 let sample = inAudioFifo.first(); // is this going to cause perf. delay?520 if (sample matches tagged Sample .audio) // if it is EOF another rule sets the cp0_audioEOF521 wbQ.enq(tagged WB_ALU {dest:it.rdst, data:zext(pack(audio)) }); // do I need pack?522 else $display ( "Audio File EOF Reached. Invalid sample request.");523 inAudioFifo.deq();524 end525 default :526 $display( " RTL-ERROR : %m : Illegal MFC0 cop0src register!" );527 endcase528 end530 // -- Illegal ---------------------------------------------------532 default :533 $display( " RTL-ERROR : %m : Illegal instruction !" );535 endcase537 //evaluate branch prediction538 Addr ppc = pcQ.first().qnxtpc; //predicted branch539 if (ppc != newPC) //prediction wrong540 begin541 epoch <= pcQ.first().qepoch + 1;542 bp.upd(instrpc, newPC); //update branch predictor543 pcQ.clear();544 pc <= newPC;545 end546 else547 pcQ.deq();548 //rlm: removing549 // if ( cp0_statsEn )550 // num_inst.incr();552 endrule554 rule writeback; // ( stage == Writeback );555 traceTiny("mkProc", "writeback","W");558 // get what to do off the writeback queue559 wbQ.deq();560 case (wbQ.first()) matches561 tagged WB_ALU {data:.res, dest:.rdst} : rf.wr(rdst, res);562 tagged WB_Load .regWr :563 begin564 dataRespQ.deq();565 if (dataRespQ.first() matches tagged LoadResp .ld)566 rf.wr(truncate(ld.tag), ld.data); // no need to use Rindx from queue? Duplicate?567 end568 tagged WB_Store : dataRespQ.deq();569 tagged WB_Host .dat : noAction;570 endcase572 endrule574 //rlm remove575 // rule inc_num_cycles;576 // if ( cp0_statsEn )577 // num_cycles.incr();578 // endrule580 /*581 // for now, we don't do anything.582 rule connectAudioReqResp;583 $display("rlm: PROCESSOR copies a datum\n");584 outAudioFifo.enq(inAudioFifo.first());585 inAudioFifo.deq;586 endrule587 */588 /*589 rule flagAudioEnd (inAudioFifo.first() matches tagged EndOfFile);590 $display (" PROCESSOR End Audio Flag Set ");591 cp0_audioEOF <= True;592 inAudioFifo.deq;593 endrule594 */595 rule sendProcEnd (cp0_progComp);596 $display (" PROCESSOR Says Program Complete ");597 outAudioFifo.enq(tagged EndOfFile);598 cp0_progComp <= False; //only send one. And functions to reset599 endrule602 //-----------------------------------------------------------603 // Methods605 interface Client imem_client;606 interface Get request = fifoToGet(instReqQ);607 interface Put response = fifoToPut(instRespQ);608 endinterface610 interface Client dmem_client;611 interface Get request = fifoToGet(dataReqQ);612 interface Put response = fifoToPut(dataRespQ);613 endinterface615 interface Get statsEn_get = toGet(asReg(cp0_statsEn));617 /*618 interface CPUToHost tohost;619 method Bit#(32) cpuToHost(int req);620 return (case (req)621 0: cp0_tohost;622 1: pc;623 2: zeroExtend(pack(stage));624 endcase);625 endmethod626 endinterface627 */629 interface Get sampleOutput = fifoToGet(outAudioFifo);630 interface Put sampleInput = fifoToPut(inAudioFifo);632 endmodule