Advertisement
NovaYoshi

Sunsoft 5B, Namco 163, VRC6

May 18th, 2016
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VeriLog 22.67 KB | None | 0 0
  1. `default_nettype none
  2. //Sunsoft 5B "Gimmick"
  3.  
  4. module MAP45(       //signal descriptions in powerpak.v
  5.     input m2,
  6.     input m2_n,
  7.     input clk20,
  8.  
  9.     input reset,
  10.     input nesprg_we,
  11.     output nesprg_oe,
  12.     input neschr_rd,
  13.     input neschr_wr,
  14.     input [15:0] prgain,
  15.     input [13:0] chrain,
  16.     input [7:0] nesprgdin,
  17.     input [7:0] ramprgdin,
  18.     output [7:0] nesprgdout,
  19.  
  20.     output [7:0] neschrdout,
  21.     output neschr_oe,
  22.  
  23.     output chrram_we,
  24.     output chrram_oe,
  25.     output wram_oe,
  26.     output wram_we,
  27.     output prgram_we,
  28.     output prgram_oe,
  29.     output [18:10] ramchraout,
  30.     output [18:13] ramprgaout,
  31.     output irq,
  32.     output ciram_ce,
  33.     output exp6,
  34.  
  35.     input cfg_boot,
  36.     input [18:12] cfg_chrmask,
  37.     input [18:13] cfg_prgmask,
  38.     input cfg_vertical,
  39.     input cfg_fourscreen,
  40.     input cfg_chrram
  41. );
  42.     reg [1:0] sramEN;
  43.     reg [3:0] regA;
  44.     reg [7:0] chrbank0, chrbank1, chrbank2, chrbank3, chrbank4, chrbank5, chrbank6, chrbank7;
  45.     reg [5:0] prgbank6, prgbank8, prgbankA, prgbankC;
  46.     reg [1:0] mirror;
  47.     always@(posedge m2) begin
  48.         if(nesprg_we) begin
  49.             if(prgain[15:13]==3'b100)   //8000
  50.                 regA<=nesprgdin;
  51.             if(prgain[15:13]==3'b101)   //A000
  52.                 case(regA)
  53.                     0:chrbank0<=nesprgdin;
  54.                     1:chrbank1<=nesprgdin;
  55.                     2:chrbank2<=nesprgdin;
  56.                     3:chrbank3<=nesprgdin;
  57.                     4:chrbank4<=nesprgdin;
  58.                     5:chrbank5<=nesprgdin;
  59.                     6:chrbank6<=nesprgdin;
  60.                     7:chrbank7<=nesprgdin;
  61.                     8:{sramEN,prgbank6}<=nesprgdin;
  62.                     9:prgbank8<=nesprgdin;
  63.                     10:prgbankA<=nesprgdin;
  64.                     11:prgbankC<=nesprgdin;
  65.                     12:mirror<=nesprgdin;
  66.                     //13:{timerEN,timerIRQEN}<={nesprgdin[7],nesprgdin[0]};
  67.                     //14:timer[7:0]<=nesprgdin;
  68.                     //15:timer[15:8]<=nesprgdin;
  69.                 endcase
  70.         end
  71.     end
  72.  
  73. //bankswitch
  74.     reg [18:13] prgbank;
  75.     reg [18:10] chrbank;
  76.     always@* begin
  77.         chrbank[18]=0;
  78.         case(prgain[14:13])
  79.             0:prgbank=prgbank8;
  80.             1:prgbank=prgbankA;
  81.             2:prgbank=prgbankC;
  82.             3:prgbank={6{prgain[15]}}|prgbank6;
  83.         endcase
  84.         case(chrain[12:10])
  85.             0:chrbank=chrbank0;
  86.             1:chrbank=chrbank1;
  87.             2:chrbank=chrbank2;
  88.             3:chrbank=chrbank3;
  89.             4:chrbank=chrbank4;
  90.             5:chrbank=chrbank5;
  91.             6:chrbank=chrbank6;
  92.             7:chrbank=chrbank7;
  93.         endcase
  94.     end
  95.  
  96. //IRQ
  97.     reg [15:0] timer;
  98.     wire [16:0] timer_dec = timer-1;
  99.     reg tripped;
  100.     reg timerEN,timerIRQEN;
  101.     always@(posedge m2, posedge reset) begin
  102.         if(reset) begin
  103.             timerIRQEN<=0;
  104.             timerEN<=0;
  105.             timer<=0;
  106.             tripped<=0;
  107.         end else begin
  108.             if(nesprg_we & prgain[15:13]==3'b101 & regA==13) //write A000:D
  109.                 {timerEN,timerIRQEN}<={nesprgdin[7],nesprgdin[0]};
  110.  
  111.             if(nesprg_we & prgain[15:13]==3'b101 & regA==14) //write A000:E
  112.                 timer[7:0]<=nesprgdin;
  113.             else if(timerEN)
  114.                 timer[7:0]<=timer_dec[7:0];
  115.  
  116.             if(nesprg_we & prgain[15:13]==3'b101 & regA==15) //write A000:F
  117.                 timer[15:8]<=nesprgdin;
  118.             else if(timerEN)
  119.                 timer[15:8]<=timer_dec[15:8];
  120.  
  121.             if(nesprg_we & prgain[15:13]==3'b101 & regA==13 & ~nesprgdin[0]) // ack IRQ when IRQEN is cleared
  122.                 tripped<=0;
  123.             else if(timerEN && timer_dec[16]) // trigger IRQ when timer wraps
  124.                 tripped<=1;
  125.         end
  126.     end
  127.     assign irq=tripped & timerIRQEN;
  128.  
  129. //mirroring (00=V, 01=H, 10=1scA, 11=1scB)
  130.     wire vertical= mirror==0;
  131.     wire horizontal= mirror==1;
  132.     wire oneB= mirror==3;
  133.     assign ramchraout[10]=!chrain[13] ? chrbank[10] : (oneB | (vertical & chrain[10]) | (horizontal & chrain[11]));
  134.     assign ramchraout[11]=chrbank[11];
  135.     assign ciram_ce=chrain[13];
  136.  
  137. //rom size mask
  138.     assign ramprgaout[18:13]=prgbank[18:13] & cfg_prgmask;
  139.     assign ramchraout[18:12]=chrbank[18:12] & cfg_chrmask;
  140.  
  141. //bus control
  142.     assign chrram_we=neschr_wr & !chrain[13] & cfg_chrram;
  143.     assign chrram_oe=neschr_rd & !chrain[13];
  144.  
  145.     assign neschr_oe=0;
  146.     assign neschrdout=8'bx;
  147.  
  148.     assign wram_oe=m2_n & ~nesprg_we & prgain[15:13]=='b011 & sramEN==3;
  149.     assign wram_we=m2_n &  nesprg_we & prgain[15:13]=='b011 & sramEN==3;
  150.  
  151.     assign prgram_we=0;
  152.     assign prgram_oe=~cfg_boot & m2_n & ~nesprg_we & (prgain[15] | (~sramEN[0] & prgain[15:13]=='b011));
  153.  
  154.     wire config_rd;
  155.     gamegenie gg(m2, reset, nesprg_we, prgain, nesprgdin, ramprgdin, nesprgdout, config_rd);
  156.     assign nesprg_oe=wram_oe | prgram_oe | config_rd;
  157.  
  158. //audio
  159.     wire [6:0] fme7_out;
  160.     FME7_sound snd0(m2, reset, nesprg_we, prgain, nesprgdin, fme7_out);
  161.     pdm #(7) pdm_mod(clk20, fme7_out, exp6);
  162.  
  163. endmodule
  164.  
  165. module FME7_sound(
  166.     input m2,
  167.     input reset,
  168.     input wr,
  169.     input [15:0] ain,
  170.     input [7:0] din,
  171.     output [6:0] out
  172. );
  173.     reg [3:0] regC;
  174.     reg [11:0] freq0,freq1,freq2;
  175.     reg [2:0] en;
  176.     reg [3:0] vol0,vol1,vol2;
  177.     reg [11:0] count0,count1,count2;
  178.     reg [4:0] duty0,duty1,duty2;
  179.     always@(posedge m2, posedge reset) begin
  180.         if(reset) begin
  181.             en<=0;
  182.         end else begin
  183.             if(wr) begin
  184.                 if(ain[15:13]==3'b110)  //C000
  185.                     regC<=din;
  186.                 if(ain[15:13]==3'b111)  //E000
  187.                 case(regC)
  188.                     0:freq0[7:0]<=din;
  189.                     1:freq0[11:8]<=din;
  190.                     2:freq1[7:0]<=din;
  191.                     3:freq1[11:8]<=din;
  192.                     4:freq2[7:0]<=din;
  193.                     5:freq2[11:8]<=din;
  194.                     7:en<=din;
  195.                     8:vol0<=din;
  196.                     9:vol1<=din;
  197.                     10:vol2<=din;
  198.                 endcase
  199.             end
  200.             if(count0==freq0) begin
  201.                 count0<=0;
  202.                 duty0<=duty0+1;
  203.             end else
  204.                 count0<=count0+1;
  205.  
  206.             if(count1==freq1) begin
  207.                 count1<=0;
  208.                 duty1<=duty1+1;
  209.             end else
  210.                 count1<=count1+1;
  211.             if(count2==freq2) begin
  212.                 count2<=0;
  213.                 duty2<=duty2+1;
  214.             end else
  215.                 count2<=count2+1;
  216.         end
  217.     end
  218.    
  219.     wire [3:0] ch0={4{~en[0] & duty0[4]}} & vol0;
  220.     wire [3:0] ch1={4{~en[1] & duty1[4]}} & vol1;
  221.     wire [3:0] ch2={4{~en[2] & duty2[4]}} & vol2;
  222.     assign out=ch0+ch1+ch2;
  223.    
  224. endmodule
  225.  
  226. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  227.  
  228. `default_nettype none
  229.  
  230. //fixme- sound ram is supposed to be readable (does this affect any games?)
  231. module MAPN106(     //signal descriptions in powerpak.v
  232.     input m2,
  233.     input m2_n,
  234.     input clk20,
  235.  
  236.     input reset,
  237.     input nesprg_we,
  238.     output nesprg_oe,
  239.     input neschr_rd,
  240.     input neschr_wr,
  241.     input [15:0] prgain,
  242.     input [13:0] chrain,
  243.     input [7:0] nesprgdin,
  244.     input [7:0] ramprgdin,
  245.     output reg [7:0] nesprgdout,
  246.  
  247.     output [7:0] neschrdout,
  248.     output neschr_oe,
  249.  
  250.     output reg chrram_we,
  251.     output reg chrram_oe,
  252.     output wram_oe,
  253.     output wram_we,
  254.     output prgram_we,
  255.     output prgram_oe,
  256.     output reg [18:10] ramchraout,
  257.     output [18:13] ramprgaout,
  258.     output irq,
  259.     output reg ciram_ce,
  260.     output exp6,
  261.    
  262.     input cfg_boot,
  263.     input [18:12] cfg_chrmask,
  264.     input [18:13] cfg_prgmask,
  265.     input cfg_vertical,
  266.     input cfg_fourscreen,
  267.     input cfg_chrram
  268. );
  269.  
  270.     reg [1:0] chr_en;
  271.     reg [5:0] prg89,prgAB,prgCD;
  272.     reg [7:0] chr0,chr1,chr2,chr3,chr4,chr5,chr6,chr7,chr10,chr11,chr12,chr13;
  273.     reg mirror;
  274.     always@(posedge m2) begin
  275.         if(nesprg_we)
  276.         case(prgain[15:11])
  277.             5'b10000: chr0<=nesprgdin;              //8000
  278.             5'b10001: chr1<=nesprgdin;
  279.             5'b10010: chr2<=nesprgdin;              //9000
  280.             5'b10011: chr3<=nesprgdin;
  281.             5'b10100: chr4<=nesprgdin;              //A000
  282.             5'b10101: chr5<=nesprgdin;
  283.             5'b10110: chr6<=nesprgdin;              //B000
  284.             5'b10111: chr7<=nesprgdin;
  285.             5'b11000: chr10<=nesprgdin;             //C000
  286.             5'b11001: chr11<=nesprgdin;
  287.             5'b11010: chr12<=nesprgdin;             //D000
  288.             5'b11011: chr13<=nesprgdin;
  289.             5'b11100: {mirror,prg89}<=nesprgdin;    //E000
  290.             5'b11101: {chr_en,prgAB}<=nesprgdin;    //E800
  291.             5'b11110: prgCD<=nesprgdin;             //F000
  292.             //5'b11111:                             //F800 (sound)
  293.         endcase
  294.     end
  295.  
  296.     //IRQ
  297.     reg [15:0] count;
  298.     wire [15:0] count_next=count+1;
  299.     wire countup=count[15] & ~&count[14:0];
  300.     reg timeout;
  301.     assign irq=timeout;
  302.     always@(posedge m2) begin
  303.         if(prgain[15:12]==4'b0101)              timeout<=0;
  304.         else if(count==16'hFFFF)                timeout<=1;
  305.         if(nesprg_we & prgain[15:11]==5'b01010) count[7:0]<=nesprgdin;
  306.         else if(countup)                        count[7:0]<=count_next[7:0];
  307.         if(nesprg_we & prgain[15:11]==5'b01011) count[15:8]<=nesprgdin;
  308.         else if(countup)                        count[15:8]<=count_next[15:8];          
  309.     end
  310.  
  311.     //PRG bank
  312.     reg [18:13] prgbankin;
  313.     always@* begin
  314.         case(prgain[14:13])
  315.             0:prgbankin=prg89;
  316.             1:prgbankin=prgAB;
  317.             2:prgbankin=prgCD;
  318.             3:prgbankin=6'b111111;
  319.         endcase
  320.     end
  321.     assign ramprgaout[18:13]=prgbankin[18:13] & cfg_prgmask & {4'b1111,{2{prgain[15]}}};
  322.  
  323.     //CHR control
  324.     reg chrram;
  325.     reg [17:10] chrbank;
  326.     always@* begin
  327.         case(chrain[13:10])
  328.             0:chrbank=chr0;
  329.             1:chrbank=chr1;
  330.             2:chrbank=chr2;
  331.             3:chrbank=chr3;
  332.             4:chrbank=chr4;
  333.             5:chrbank=chr5;
  334.             6:chrbank=chr6;
  335.             7:chrbank=chr7;
  336.             8,12:chrbank=chr10;
  337.             9,13:chrbank=chr11;
  338.             10,14:chrbank=chr12;
  339.             11,15:chrbank=chr13;
  340.         endcase
  341.         chrram=(~(chrain[12]?chr_en[1]:chr_en[0]))&(&chrbank[17:15]);   //ram/rom select
  342.         if(!chrain[13]) begin
  343.             ciram_ce=0;
  344.             chrram_oe=neschr_rd;
  345.             chrram_we=neschr_wr & chrram;
  346.             ramchraout[10]=chrbank[10];
  347.         end else begin
  348.             ciram_ce=&chrbank[17:15] | mirror;
  349.             chrram_oe=~ciram_ce & neschr_rd;
  350.             chrram_we=~ciram_ce & neschr_wr & chrram;
  351.             ramchraout[10]=mirror?chrain[10]:chrbank[10];
  352.         end
  353.         ramchraout[11]=chrbank[11];
  354.         ramchraout[17:12]=chrbank[17:12] & cfg_chrmask[17:12];
  355.         ramchraout[18]=chrram;
  356.     end
  357.  
  358.     assign wram_oe=m2_n & ~nesprg_we & prgain[15:13]==3'b011;
  359.     assign wram_we=m2_n &  nesprg_we & prgain[15:13]==3'b011;
  360.  
  361.     assign prgram_we=0;
  362.     assign prgram_oe= ~cfg_boot & m2_n & ~nesprg_we & prgain[15];
  363.  
  364.     wire config_rd;
  365.     wire [7:0] gg_out;
  366.     gamegenie gg(m2, reset, nesprg_we, prgain, nesprgdin, ramprgdin, gg_out, config_rd);
  367.  
  368.     //PRG data out
  369.     wire counter_oe = m2_n & ~nesprg_we & prgain[15:12]=='b0101;
  370.     always@* case(prgain[15:11])
  371.         5'b01010: nesprgdout=count[7:0];
  372.         5'b01011: nesprgdout=count[15:8];
  373.         default: nesprgdout=gg_out;
  374.     endcase
  375.  
  376.     assign nesprg_oe=wram_oe | prgram_oe | counter_oe | config_rd;
  377.  
  378.     assign neschr_oe=0;
  379.     assign neschrdout=0;
  380.  
  381.     //sound
  382.     wire [10:0] n106_out;
  383.     wire [9:0] saturated=n106_out[9:0] | {10{n106_out[10]}};    //this is still too quiet for the suggested 47k resistor, but more clipping will make some games sound bad
  384.     namco106_sound n106(m2, clk20, reset, nesprg_we, prgain, nesprgdin, n106_out);
  385.     pdm #(10) pdm_mod(clk20, saturated, exp6);
  386.  
  387. endmodule
  388.  
  389. module namco106_sound(
  390.     input m2,
  391.     input clk20,
  392.     input reset,
  393.     input wr,
  394.     input [15:0] ain,
  395.     input [7:0] din,
  396.     output reg [10:0] out       //range is 0..0x708
  397. );
  398.     reg carry;
  399.     reg autoinc;
  400.     reg [6:0] ram_ain;
  401.     reg [6:0] ram_aout;
  402.     wire [7:0] ram_dout;
  403.     reg [2:0] ch;
  404.     reg [7:0] cnt_L[7:0];
  405.     reg [7:0] cnt_M[7:0];
  406.     reg [1:0] cnt_H[7:0];
  407.     wire [2:0] sum_H=cnt_H[ch]+ram_dout[1:0]+carry;
  408.     reg [4:0] sample_pos[7:0];
  409.     reg [2:0] cycle;
  410.     reg [3:0] sample;
  411.     wire [7:0] chan_out=sample*ram_dout[3:0];   //sample*vol
  412.     reg [10:0] out_acc;
  413.     wire [10:0] sum=out_acc+chan_out;
  414.     reg addr_lsb;
  415.     wire [7:0] sample_addr=ram_dout+sample_pos[ch];
  416.  
  417.     //ram in
  418.     always@(posedge m2) begin
  419.         if(wr & ain[15:11]==5'b11111)           //F800..FFFF
  420.             {autoinc,ram_ain}<=din;
  421.         else if(ain[15:11]==5'b01001 & autoinc) //4800..4FFF
  422.             ram_ain<=ram_ain+1;    
  423.     end
  424.  
  425.     //mixer FSM
  426.     always@* case(cycle)
  427.         0: ram_aout={1'b1,ch,3'd0};     //freq[7:0]
  428.         1: ram_aout={1'b1,ch,3'd2};     //freq[15:8]
  429.         2: ram_aout={1'b1,ch,3'd4};     //length, freq[17:16]
  430.         3: ram_aout={1'b1,ch,3'd6};     //address
  431.         4: ram_aout=sample_addr[7:1];   //sample address
  432.         5: ram_aout={1'b1,ch,3'd7};     //volume
  433.         default: ram_aout=7'bXXXXXXX;
  434.     endcase
  435.     reg [3:0] count45,cnt45;
  436.     always@(posedge m2)
  437.         count45<=(count45==14)?0:count45+1;
  438.     always@(posedge clk20) begin
  439.         cnt45<=count45;
  440.         if(cnt45[1:0]==0) cycle<=0;             // this gives 45 21.4M clocks per channel
  441.         else if(cycle!=7) cycle<=cycle+1;
  442.         case(cycle)
  443.             1: {carry, cnt_L[ch]}<=cnt_L[ch][7:0]+ram_dout;
  444.             2: {carry, cnt_M[ch]}<=cnt_M[ch][7:0]+ram_dout+carry;
  445.             3: begin
  446.                 cnt_H[ch]<=sum_H[1:0];
  447.                 if(sum_H[2])
  448.                     sample_pos[ch]<=(sample_pos[ch]=={ram_dout[4:2]^3'b111,2'b11})?0:(sample_pos[ch]+1);
  449.             end
  450.             4: addr_lsb<=sample_addr[0];
  451.             5: sample<=addr_lsb?ram_dout[7:4]:ram_dout[3:0];
  452.             6: begin
  453.                 if(ch==7) begin
  454.                     ch<=ram_dout[6:4]^7;
  455.                     out_acc<=0;
  456.                     out<=sum;
  457.                 end else begin
  458.                     ch<=ch+1;
  459.                     out_acc<=sum;
  460.                 end
  461.             end
  462.         endcase
  463.     end
  464.  
  465.     RAMB4_S8_S8 n106_ram(
  466.         .WEA(wr & ain[15:11]==5'b01001),   //cpu write 4800-4FFF
  467.         .ENA(1'b1),
  468.         .RSTA(1'b0),
  469.         .CLKA(m2),
  470.         .ADDRA({2'd0,ram_ain}),
  471.         .DIA(din),
  472.         .DOA(),
  473.  
  474.         .WEB(1'b0),
  475.         .ENB(1'b1),
  476.         .RSTB(1'b0),
  477.         .CLKB(clk20),
  478.         .ADDRB({2'd0,ram_aout}),
  479.         .DIB(),
  480.         .DOB(ram_dout)
  481.     );
  482.  
  483. endmodule
  484.  
  485. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  486.  
  487. `default_nettype none
  488.  
  489. // change ain below to set VRC6 variant
  490. module MAPVRC6(     //signal descriptions in powerpak.v
  491.     input m2,
  492.     input m2_n,
  493.     input clk20,
  494.  
  495.     input reset,
  496.     input nesprg_we,
  497.     output nesprg_oe,
  498.     input neschr_rd,
  499.     input neschr_wr,
  500.     input [15:0] prgain,
  501.     input [13:0] chrain,
  502.     input [7:0] nesprgdin,
  503.     input [7:0] ramprgdin,
  504.     output [7:0] nesprgdout,
  505.  
  506.     output [7:0] neschrdout,
  507.     output neschr_oe,
  508.  
  509.     output chrram_we,
  510.     output chrram_oe,
  511.     output wram_oe,
  512.     output wram_we,
  513.     output prgram_we,
  514.     output prgram_oe,
  515.     output [18:10] ramchraout,
  516.     output [18:13] ramprgaout,
  517.     output irq,
  518.     output ciram_ce,
  519.  
  520.     output exp6,
  521.    
  522.     input cfg_boot,
  523.     input [18:12] cfg_chrmask,
  524.     input [18:13] cfg_prgmask,
  525.     input cfg_vertical,
  526.     input cfg_fourscreen,
  527.     input cfg_chrram
  528. );
  529.     //wire [15:0] ain=prgain;                             //MAP18
  530.     wire [15:0] ain={prgain[15:2],prgain[0],prgain[1]}; //MAP1A
  531.  
  532.     reg [4:0] prgbank8;
  533.     reg [5:0] prgbankC;
  534.     reg [7:0] chrbank0, chrbank1, chrbank2, chrbank3, chrbank4, chrbank5, chrbank6, chrbank7;
  535.     reg [1:0] mirror;
  536.     reg [7:0] irqlatch;
  537.     reg irqM,irqE,irqA;
  538.     always@(posedge m2) begin
  539.         if(nesprg_we) begin
  540.             casex({ain[15:12],ain[1:0]})
  541.                 6'b1000xx:prgbank8<=nesprgdin;      //800x
  542.                 6'b1100xx:prgbankC<=nesprgdin;      //C00x
  543.                 6'b101111:mirror<=nesprgdin[3:2];   //B003
  544.                 6'b110100:chrbank0<=nesprgdin;      //D000
  545.                 6'b110101:chrbank1<=nesprgdin;      //D001
  546.                 6'b110110:chrbank2<=nesprgdin;      //D002
  547.                 6'b110111:chrbank3<=nesprgdin;      //D003
  548.                 6'b111000:chrbank4<=nesprgdin;      //E000
  549.                 6'b111001:chrbank5<=nesprgdin;      //E001
  550.                 6'b111010:chrbank6<=nesprgdin;      //E002
  551.                 6'b111011:chrbank7<=nesprgdin;      //E003
  552.                 6'b111100:irqlatch<=nesprgdin;      //F000
  553.                 6'b111101:{irqM,irqA}<={nesprgdin[2],nesprgdin[0]}; //F001
  554.             endcase
  555.         end
  556.     end
  557.  
  558.     //bankswitch
  559.     reg [18:13] prgbankin;
  560.     reg [17:10] chrbank;
  561.     always@* begin
  562.         casex(prgain[15:13])
  563.             3'b0xx:prgbankin=0;                         //sram
  564.             3'b10x:prgbankin={prgbank8,prgain[13]};     //89AB
  565.             3'b110:prgbankin=prgbankC;                  //CD
  566.             default:prgbankin=6'b111111;                //EF
  567.         endcase
  568.         case(chrain[12:10])
  569.             0:chrbank=chrbank0;
  570.             1:chrbank=chrbank1;
  571.             2:chrbank=chrbank2;
  572.             3:chrbank=chrbank3;
  573.             4:chrbank=chrbank4;
  574.             5:chrbank=chrbank5;
  575.             6:chrbank=chrbank6;
  576.             7:chrbank=chrbank7;
  577.         endcase
  578.     end
  579.  
  580.     //IRQ
  581.     reg [7:0] irqcnt;
  582.     reg timeout;
  583.     reg [6:0] scalar;
  584.     reg [1:0] line;
  585.     wire irqclk=irqM|(scalar==0);
  586.     wire setE=nesprg_we & {ain[15:12],ain[1:0]}==6'b111101 & nesprgdin[1];
  587.     always@(posedge m2, posedge setE) begin
  588.         if(setE) begin
  589.             scalar<=113;
  590.             line<=0;
  591.             irqcnt<=irqlatch;
  592.         end else if(irqE) begin
  593.             if(scalar!=0)
  594.                 scalar<=scalar-1;
  595.             else begin
  596.                 scalar<=(~line[1])?113:112;
  597.                 line<=line[1]?0:line+1;
  598.             end
  599.             if(irqclk) begin
  600.                 if(irqcnt==255)     irqcnt<=irqlatch;
  601.                 else            irqcnt<=irqcnt+1;
  602.             end
  603.         end
  604.     end
  605.     always@(posedge m2, posedge reset) begin
  606.         if(reset) begin
  607.             irqE<=0;
  608.             timeout<=0;
  609.         end else begin
  610.             if(nesprg_we & ain[15:12]==15 & ^ain[1:0]) //write Fxx1 or Fxx2
  611.                 timeout<=0;
  612.             else if(irqclk & irqcnt==255)
  613.                 timeout<=1;
  614.  
  615.             if(nesprg_we & {ain[15:12],ain[1:0]}==6'b111101) //write Fxx1
  616.                 irqE<=nesprgdin[1];
  617.             else if(nesprg_we & {ain[15:12],ain[1:0]}==6'b111110) //write Fxx2
  618.                 irqE<=irqA;
  619.         end
  620.     end
  621.  
  622.     assign irq=timeout & irqE;
  623.  
  624. //mirroring
  625.     assign ramchraout[10]=!chrain[13] ? chrbank[10] : ((mirror==0 & chrain[10]) | (mirror==1 & chrain[11]) | (mirror==3));
  626.     assign ramchraout[11]=chrbank[11];
  627.     assign ciram_ce=chrain[13];
  628.  
  629. //rom size mask
  630.     assign ramprgaout[18:13]=prgbankin[18:13] & cfg_prgmask;
  631.     assign ramchraout[18:12]={1'b0,chrbank[17:12]} & cfg_chrmask;
  632.  
  633. //ram control
  634.     assign chrram_we=neschr_wr & !chrain[13] & cfg_chrram;
  635.     assign chrram_oe=neschr_rd & !chrain[13];
  636.  
  637.     assign neschr_oe=0;
  638.     assign neschrdout=8'bx;
  639.  
  640.     assign wram_oe=m2_n & ~nesprg_we & prgain[15:13]=='b011;
  641.     assign wram_we=m2_n &  nesprg_we & prgain[15:13]=='b011;
  642.    
  643.     assign prgram_we=0;
  644.     assign prgram_oe=~cfg_boot & m2_n & ~nesprg_we & prgain[15];
  645.  
  646.     wire config_rd;
  647.     gamegenie gg(m2, reset, nesprg_we, prgain, nesprgdin, ramprgdin, nesprgdout, config_rd);
  648.     assign nesprg_oe=wram_oe | prgram_oe | config_rd;
  649.  
  650. //sound
  651.     wire [5:0] vrc6_out;
  652.     vrc6sound snd(m2, reset, nesprg_we, ain, nesprgdin, vrc6_out);
  653.     pdm #(6) pdm_mod(clk20, vrc6_out, exp6);
  654.  
  655. endmodule
  656.  
  657. module vrc6sound(
  658.     input m2,
  659.     input reset,
  660.     input wr,
  661.     input [15:0] ain,
  662.     input [7:0] din,
  663.     output [5:0] out        //range=0..0x3D
  664. );
  665.     reg mode0, mode1;
  666.     reg [3:0] vol0, vol1;
  667.     reg [5:0] vol2;
  668.     reg [2:0] duty0, duty1;
  669.     reg [11:0] freq0, freq1, freq2;
  670.     reg [11:0] div0, div1;
  671.     reg [12:0] div2;
  672.     reg en0, en1, en2;
  673.  
  674.     reg [3:0] duty0cnt, duty1cnt;
  675.     reg [2:0] duty2cnt;
  676.     reg [7:0] acc;
  677.  
  678.     always@(posedge m2, posedge reset) begin
  679.         if(reset) begin
  680.             en0<=0;
  681.             en1<=0;
  682.             en2<=0;
  683.         end else begin
  684.             if(wr) begin
  685.                 case(ain)
  686.                     16'h9000: {mode0, duty0, vol0}<=din;
  687.                     16'h9001: freq0[7:0]<=din;
  688.                     16'h9002: {en0, freq0[11:8]} <= {din[7],din[3:0]};
  689.  
  690.                     16'hA000: {mode1, duty1, vol1}<=din;
  691.                     16'hA001: freq1[7:0]<=din;
  692.                     16'hA002: {en1, freq1[11:8]} <= {din[7],din[3:0]};
  693.  
  694.                     16'hB000: vol2<=din[5:0];
  695.                     16'hB001: freq2[7:0]<=din;
  696.                     16'hB002: {en2, freq2[11:8]}<={din[7],din[3:0]};
  697.                 endcase
  698.             end
  699.             if(en0) begin
  700.                 if(div0!=0)
  701.                     div0<=div0-1;
  702.                 else begin
  703.                     div0<=freq0;
  704.                     duty0cnt<=duty0cnt+1;
  705.                 end
  706.             end
  707.             if(en1) begin
  708.                 if(div1!=0)
  709.                     div1<=div1-1;
  710.                 else begin
  711.                     div1<=freq1;
  712.                     duty1cnt<=duty1cnt+1;
  713.                 end
  714.             end
  715.             if(en2) begin
  716.                 if(div2!=0)
  717.                     div2<=div2-1;
  718.                 else begin
  719.                     div2<={freq2,1'b1};
  720.                     if(duty2cnt==6) begin
  721.                         duty2cnt<=0;
  722.                         acc<=0;
  723.                     end else begin
  724.                         duty2cnt<=duty2cnt+1;
  725.                         acc<=acc+vol2;
  726.                     end
  727.                 end
  728.             end
  729.         end
  730.     end
  731.  
  732.     wire [4:0] duty0pos=duty0cnt+{1'b1,~duty0};
  733.     wire [4:0] duty1pos=duty1cnt+{1'b1,~duty1};
  734.     wire [3:0] ch0=((~duty0pos[4]|mode0)&en0)?vol0:0;
  735.     wire [3:0] ch1=((~duty1pos[4]|mode1)&en1)?vol1:0;
  736.     wire [4:0] ch2=en2?acc[7:3]:0;
  737.     assign out=ch0+ch1+ch2;
  738.  
  739. endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement