diff --git a/cores/nes/nes.qsf b/cores/nes/nes.qsf index 4a807e3..5a9aa80 100644 --- a/cores/nes/nes.qsf +++ b/cores/nes/nes.qsf @@ -281,6 +281,7 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_n set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCS set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CKE set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CLK +set_global_assignment -name SYSTEMVERILOG_FILE src/apu.sv set_global_assignment -name VHDL_FILE t65/T65_Pack.vhd set_global_assignment -name VHDL_FILE t65/T65_MCode.vhd set_global_assignment -name VHDL_FILE t65/T65_ALU.vhd @@ -304,6 +305,5 @@ set_global_assignment -name VERILOG_FILE src/nes.v set_global_assignment -name VERILOG_FILE src/MicroCode.v set_global_assignment -name VERILOG_FILE src/hq2x.v set_global_assignment -name VERILOG_FILE src/dsp.v -set_global_assignment -name VERILOG_FILE src/apu.v set_global_assignment -name VERILOG_FILE mist/NES_mist.v set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/cores/nes/src/apu.v b/cores/nes/src/apu.sv similarity index 74% rename from cores/nes/src/apu.v rename to cores/nes/src/apu.sv index fa3dfa8..26e3025 100644 --- a/cores/nes/src/apu.v +++ b/cores/nes/src/apu.sv @@ -71,7 +71,7 @@ reg [2:0] SeqPos; wire [10:0] ShiftedPeriod = (Period >> SweepShift); wire [10:0] PeriodRhs = (SweepNegate ? (~ShiftedPeriod + {10'b0, sq2}) : ShiftedPeriod); wire [11:0] NewSweepPeriod = Period + PeriodRhs; -wire ValidFreq = Period[10:3] >= 8 && (SweepNegate || !NewSweepPeriod[11]); +wire ValidFreq = (|Period[10:3]) && (SweepNegate || !NewSweepPeriod[11]); always @(posedge clk) if (reset) begin LenCtr <= 0; @@ -131,14 +131,14 @@ always @(posedge clk) if (reset) begin if (TimerCtr == 0) begin // Timer was clocked TimerCtr <= {Period, 1'b0}; - SeqPos <= SeqPos - 1; + SeqPos <= SeqPos - 1'd1; end else begin - TimerCtr <= TimerCtr - 1; + TimerCtr <= TimerCtr - 1'd1; end // Clock the length counter? if (LenCtr_Clock && LenCtr != 0 && !LenCtrHalt) begin - LenCtr <= LenCtr - 1; + LenCtr <= LenCtr - 1'd1; end // Clock the sweep unit? @@ -148,7 +148,7 @@ always @(posedge clk) if (reset) begin if (SweepEnable && SweepShift != 0 && ValidFreq) Period <= NewSweepPeriod[10:0]; end else begin - SweepDivider <= SweepDivider - 1; + SweepDivider <= SweepDivider - 1'd1; end if (SweepReset) SweepDivider <= SweepPeriod; @@ -164,9 +164,9 @@ always @(posedge clk) if (reset) begin end else if (EnvDivider == 0) begin EnvDivider <= Volume; if (Envelope != 0 || EnvLoop) - Envelope <= Envelope - 1; + Envelope <= Envelope - 1'd1; end else begin - EnvDivider <= EnvDivider - 1; + EnvDivider <= EnvDivider - 1'd1; end end @@ -252,12 +252,12 @@ module TriangleChan(input clk, input ce, input reset, if (TimerCtr == 0) begin TimerCtr <= Period; end else begin - TimerCtr <= TimerCtr - 1; + TimerCtr <= TimerCtr - 1'd1; end // // Clock the length counter? if (LenCtr_Clock && !LenCtrZero && !LenCtrHalt) begin - LenCtr <= LenCtr - 1; + LenCtr <= LenCtr - 1'd1; end // // Clock the linear counter? @@ -265,7 +265,7 @@ module TriangleChan(input clk, input ce, input reset, if (LinHalt) LinCtr <= LinCtrPeriod; else if (!LinCtrZero) - LinCtr <= LinCtr - 1; + LinCtr <= LinCtr - 1'd1; if (!LinCtrl) LinHalt <= 0; end @@ -276,7 +276,7 @@ module TriangleChan(input clk, input ce, input reset, // // Clock the sequencer position if (TimerCtr == 0 && !LenCtrZero && !LinCtrZero) - SeqPos <= SeqPos + 1; + SeqPos <= SeqPos + 1'd1; end // Generate the output assign Sample = SeqPos[3:0] ^ {4{~SeqPos[4]}}; @@ -371,11 +371,11 @@ module NoiseChan(input clk, input ce, input reset, Shift[0] ^ (ShortMode ? Shift[6] : Shift[1]), Shift[14:1]}; end else begin - TimerCtr <= TimerCtr - 1; + TimerCtr <= TimerCtr - 1'd1; end // Clock the length counter? if (LenCtr_Clock && LenCtr != 0 && !LenCtrHalt) begin - LenCtr <= LenCtr - 1; + LenCtr <= LenCtr - 1'd1; end // Clock the envelope generator? if (Env_Clock) begin @@ -386,11 +386,11 @@ module NoiseChan(input clk, input ce, input reset, end else if (EnvDivider == 0) begin EnvDivider <= Volume; if (Envelope != 0) - Envelope <= Envelope - 1; + Envelope <= Envelope - 1'd1; else if (EnvLoop) Envelope <= 15; end else - EnvDivider <= EnvDivider - 1; + EnvDivider <= EnvDivider - 1'd1; end if (!Enabled) LenCtr <= 0; @@ -398,7 +398,7 @@ module NoiseChan(input clk, input ce, input reset, // Produce the output signal assign Sample = (LenCtr == 0 || Shift[0]) ? - 0 : + 4'd0 : (EnvDisable ? Volume : Envelope); endmodule @@ -429,7 +429,6 @@ module DmcChan(input clk, input ce, input reset, reg [7:0] SampleBuffer; // Next value to be loaded into shift reg reg HasSampleBuffer; // Sample buffer is nonempty reg HasShiftReg; // Shift reg is non empty - reg [8:0] NewPeriod[0:15]; reg DmcEnabled; reg [1:0] ActivationDelay; assign DmaAddr = {1'b1, Address}; @@ -439,24 +438,13 @@ module DmcChan(input clk, input ce, input reset, assign DmaReq = !HasSampleBuffer && DmcEnabled && !ActivationDelay[0]; - initial begin - NewPeriod[0] = 428; - NewPeriod[1] = 380; - NewPeriod[2] = 340; - NewPeriod[3] = 320; - NewPeriod[4] = 286; - NewPeriod[5] = 254; - NewPeriod[6] = 226; - NewPeriod[7] = 214; - NewPeriod[8] = 190; - NewPeriod[9] = 160; - NewPeriod[10] = 142; - NewPeriod[11] = 128; - NewPeriod[12] = 106; - NewPeriod[13] = 84; - NewPeriod[14] = 72; - NewPeriod[15] = 54; - end + wire [8:0] NewPeriod[16] = '{ + 428, 380, 340, 320, + 286, 254, 226, 214, + 190, 160, 142, 128, + 106, 84, 72, 54 + }; + // Shift register initially loaded with 07 always @(posedge clk) begin if (reset) begin @@ -512,7 +500,7 @@ module DmcChan(input clk, input ce, input reset, endcase end - Cycles <= Cycles - 1; + Cycles <= Cycles - 1'd1; if (Cycles == 1) begin Cycles <= NewPeriod[Freq]; if (HasShiftReg) begin @@ -523,7 +511,7 @@ module DmcChan(input clk, input ce, input reset, end end ShiftReg <= {1'b0, ShiftReg[7:1]}; - BitsUsed <= BitsUsed + 1; + BitsUsed <= BitsUsed + 1'd1; if (BitsUsed == 7) begin HasShiftReg <= HasSampleBuffer; ShiftReg <= SampleBuffer; @@ -533,8 +521,8 @@ module DmcChan(input clk, input ce, input reset, // Acknowledge DMA? if (DmaAck) begin - Address <= Address + 1; - BytesLeft <= BytesLeft - 1; + Address <= Address + 1'd1; + BytesLeft <= BytesLeft - 1'd1; HasSampleBuffer <= 1; SampleBuffer <= DmaData; if (BytesLeft == 0) begin @@ -549,75 +537,56 @@ module DmcChan(input clk, input ce, input reset, end endmodule -module ApuLookupTable(input clk, input [7:0] in_a, input [7:0] in_b, output [15:0] out); - reg [15:0] lookup[0:511]; - reg [15:0] tmp_a, tmp_b; - initial begin - lookup[ 0] = 0; lookup[ 1] = 760; lookup[ 2] = 1503; lookup[ 3] = 2228; - lookup[ 4] = 2936; lookup[ 5] = 3627; lookup[ 6] = 4303; lookup[ 7] = 4963; - lookup[ 8] = 5609; lookup[ 9] = 6240; lookup[ 10] = 6858; lookup[ 11] = 7462; - lookup[ 12] = 8053; lookup[ 13] = 8631; lookup[ 14] = 9198; lookup[ 15] = 9752; - lookup[ 16] = 10296; lookup[ 17] = 10828; lookup[ 18] = 11349; lookup[ 19] = 11860; - lookup[ 20] = 12361; lookup[ 21] = 12852; lookup[ 22] = 13334; lookup[ 23] = 13807; - lookup[ 24] = 14270; lookup[ 25] = 14725; lookup[ 26] = 15171; lookup[ 27] = 15609; - lookup[ 28] = 16039; lookup[ 29] = 16461; lookup[ 30] = 16876; lookup[256] = 0; - lookup[257] = 439; lookup[258] = 874; lookup[259] = 1306; lookup[260] = 1735; - lookup[261] = 2160; lookup[262] = 2581; lookup[263] = 2999; lookup[264] = 3414; - lookup[265] = 3826; lookup[266] = 4234; lookup[267] = 4639; lookup[268] = 5041; - lookup[269] = 5440; lookup[270] = 5836; lookup[271] = 6229; lookup[272] = 6618; - lookup[273] = 7005; lookup[274] = 7389; lookup[275] = 7769; lookup[276] = 8147; - lookup[277] = 8522; lookup[278] = 8895; lookup[279] = 9264; lookup[280] = 9631; - lookup[281] = 9995; lookup[282] = 10356; lookup[283] = 10714; lookup[284] = 11070; - lookup[285] = 11423; lookup[286] = 11774; lookup[287] = 12122; lookup[288] = 12468; - lookup[289] = 12811; lookup[290] = 13152; lookup[291] = 13490; lookup[292] = 13825; - lookup[293] = 14159; lookup[294] = 14490; lookup[295] = 14818; lookup[296] = 15145; - lookup[297] = 15469; lookup[298] = 15791; lookup[299] = 16110; lookup[300] = 16427; - lookup[301] = 16742; lookup[302] = 17055; lookup[303] = 17366; lookup[304] = 17675; - lookup[305] = 17981; lookup[306] = 18286; lookup[307] = 18588; lookup[308] = 18888; - lookup[309] = 19187; lookup[310] = 19483; lookup[311] = 19777; lookup[312] = 20069; - lookup[313] = 20360; lookup[314] = 20648; lookup[315] = 20935; lookup[316] = 21219; - lookup[317] = 21502; lookup[318] = 21783; lookup[319] = 22062; lookup[320] = 22339; - lookup[321] = 22615; lookup[322] = 22889; lookup[323] = 23160; lookup[324] = 23431; - lookup[325] = 23699; lookup[326] = 23966; lookup[327] = 24231; lookup[328] = 24494; - lookup[329] = 24756; lookup[330] = 25016; lookup[331] = 25274; lookup[332] = 25531; - lookup[333] = 25786; lookup[334] = 26040; lookup[335] = 26292; lookup[336] = 26542; - lookup[337] = 26791; lookup[338] = 27039; lookup[339] = 27284; lookup[340] = 27529; - lookup[341] = 27772; lookup[342] = 28013; lookup[343] = 28253; lookup[344] = 28492; - lookup[345] = 28729; lookup[346] = 28964; lookup[347] = 29198; lookup[348] = 29431; - lookup[349] = 29663; lookup[350] = 29893; lookup[351] = 30121; lookup[352] = 30349; - lookup[353] = 30575; lookup[354] = 30800; lookup[355] = 31023; lookup[356] = 31245; - lookup[357] = 31466; lookup[358] = 31685; lookup[359] = 31904; lookup[360] = 32121; - lookup[361] = 32336; lookup[362] = 32551; lookup[363] = 32764; lookup[364] = 32976; - lookup[365] = 33187; lookup[366] = 33397; lookup[367] = 33605; lookup[368] = 33813; - lookup[369] = 34019; lookup[370] = 34224; lookup[371] = 34428; lookup[372] = 34630; - lookup[373] = 34832; lookup[374] = 35032; lookup[375] = 35232; lookup[376] = 35430; - lookup[377] = 35627; lookup[378] = 35823; lookup[379] = 36018; lookup[380] = 36212; - lookup[381] = 36405; lookup[382] = 36597; lookup[383] = 36788; lookup[384] = 36978; - lookup[385] = 37166; lookup[386] = 37354; lookup[387] = 37541; lookup[388] = 37727; - lookup[389] = 37912; lookup[390] = 38095; lookup[391] = 38278; lookup[392] = 38460; - lookup[393] = 38641; lookup[394] = 38821; lookup[395] = 39000; lookup[396] = 39178; - lookup[397] = 39355; lookup[398] = 39532; lookup[399] = 39707; lookup[400] = 39881; - lookup[401] = 40055; lookup[402] = 40228; lookup[403] = 40399; lookup[404] = 40570; - lookup[405] = 40740; lookup[406] = 40909; lookup[407] = 41078; lookup[408] = 41245; - lookup[409] = 41412; lookup[410] = 41577; lookup[411] = 41742; lookup[412] = 41906; - lookup[413] = 42070; lookup[414] = 42232; lookup[415] = 42394; lookup[416] = 42555; - lookup[417] = 42715; lookup[418] = 42874; lookup[419] = 43032; lookup[420] = 43190; - lookup[421] = 43347; lookup[422] = 43503; lookup[423] = 43659; lookup[424] = 43813; - lookup[425] = 43967; lookup[426] = 44120; lookup[427] = 44273; lookup[428] = 44424; - lookup[429] = 44575; lookup[430] = 44726; lookup[431] = 44875; lookup[432] = 45024; - lookup[433] = 45172; lookup[434] = 45319; lookup[435] = 45466; lookup[436] = 45612; - lookup[437] = 45757; lookup[438] = 45902; lookup[439] = 46046; lookup[440] = 46189; - lookup[441] = 46332; lookup[442] = 46474; lookup[443] = 46615; lookup[444] = 46756; - lookup[445] = 46895; lookup[446] = 47035; lookup[447] = 47173; lookup[448] = 47312; - lookup[449] = 47449; lookup[450] = 47586; lookup[451] = 47722; lookup[452] = 47857; - lookup[453] = 47992; lookup[454] = 48127; lookup[455] = 48260; lookup[456] = 48393; - lookup[457] = 48526; lookup[458] = 48658; - end - always @(posedge clk) begin - tmp_a <= lookup[{1'b0, in_a}]; - tmp_b <= lookup[{1'b1, in_b}]; - end - assign out = tmp_a + tmp_b; +module ApuLookupTable +( + input clk, + input [7:0] in_a, + input [7:0] in_b, + output reg [15:0] out +); + +wire [15:0] lookup_a[256] = '{ + 0, 760, 1503, 2228, 2936, 3627, 4303, 4963, 5609, 6240, 6858, 7462, 8053, 8631, 9198, 9752, + 10296, 10828, 11349, 11860, 12361, 12852, 13334, 13807, 14270, 14725, 15171, 15609, 16039, 16461, 16876, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +wire [15:0] lookup_b[256] = '{ + 0, 439, 874, 1306, 1735, 2160, 2581, 2999, 3414, 3826, 4234, 4639, 5041, 5440, 5836, 6229, + 6618, 7005, 7389, 7769, 8147, 8522, 8895, 9264, 9631, 9995, 10356, 10714, 11070, 11423, 11774, 12122, + 12468, 12811, 13152, 13490, 13825, 14159, 14490, 14818, 15145, 15469, 15791, 16110, 16427, 16742, 17055, 17366, + 17675, 17981, 18286, 18588, 18888, 19187, 19483, 19777, 20069, 20360, 20648, 20935, 21219, 21502, 21783, 22062, + 22339, 22615, 22889, 23160, 23431, 23699, 23966, 24231, 24494, 24756, 25016, 25274, 25531, 25786, 26040, 26292, + 26542, 26791, 27039, 27284, 27529, 27772, 28013, 28253, 28492, 28729, 28964, 29198, 29431, 29663, 29893, 30121, + 30349, 30575, 30800, 31023, 31245, 31466, 31685, 31904, 32121, 32336, 32551, 32764, 32976, 33187, 33397, 33605, + 33813, 34019, 34224, 34428, 34630, 34832, 35032, 35232, 35430, 35627, 35823, 36018, 36212, 36405, 36597, 36788, + 36978, 37166, 37354, 37541, 37727, 37912, 38095, 38278, 38460, 38641, 38821, 39000, 39178, 39355, 39532, 39707, + 39881, 40055, 40228, 40399, 40570, 40740, 40909, 41078, 41245, 41412, 41577, 41742, 41906, 42070, 42232, 42394, + 42555, 42715, 42874, 43032, 43190, 43347, 43503, 43659, 43813, 43967, 44120, 44273, 44424, 44575, 44726, 44875, + 45024, 45172, 45319, 45466, 45612, 45757, 45902, 46046, 46189, 46332, 46474, 46615, 46756, 46895, 47035, 47173, + 47312, 47449, 47586, 47722, 47857, 47992, 48127, 48260, 48393, 48526, 48658, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +always @(posedge clk) begin + out <= lookup_a[in_a] + lookup_b[in_b]; +end + endmodule @@ -712,7 +681,7 @@ always @(posedge clk) if (reset) begin Cycles <= 4; // This needs to be 5 for proper power up behavior IrqCtr <= 0; end else if (ce) begin - FrameInterrupt <= IrqCtr[1] ? 1 : (ADDR == 5'h15 && MR || ApuMW5 && ADDR[1:0] == 3 && DIN[6]) ? 0 : FrameInterrupt; + FrameInterrupt <= IrqCtr[1] ? 1'd1 : (ADDR == 5'h15 && MR || ApuMW5 && ADDR[1:0] == 3 && DIN[6]) ? 1'd0 : FrameInterrupt; InternalClock <= !InternalClock; IrqCtr <= {IrqCtr[0], 1'b0}; Cycles <= Cycles + 1; @@ -723,8 +692,6 @@ end else if (ce) begin end else if (Cycles == 14913) begin ClkE <= 1; ClkL <= 1; - ClkE <= 1; - ClkL <= 1; end else if (Cycles == 22371) begin ClkE <= 1; end else if (Cycles == 29829) begin diff --git a/cores/nes/src/cpu.v b/cores/nes/src/cpu.v deleted file mode 100644 index e328ffb..0000000 --- a/cores/nes/src/cpu.v +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright (c) 2012-2013 Ludvig Strigeus -// This program is GPL Licensed. See COPYING for the full license. - -//`include "MicroCode.v" - -module MyAddSub(input [7:0] A,B, - input CI,ADD, - output [7:0] S, - output CO,OFL); - wire C0,C1,C2,C3,C4,C5,C6; - wire C6O; - wire [7:0] I = A ^ B ^ {8{~ADD}}; - MUXCY_L MUXCY_L0 (.LO(C0),.CI(CI),.DI(A[0]),.S(I[0]) ); - MUXCY_L MUXCY_L1 (.LO(C1),.CI(C0),.DI(A[1]),.S(I[1]) ); - MUXCY_L MUXCY_L2 (.LO(C2),.CI(C1),.DI(A[2]),.S(I[2]) ); - MUXCY_L MUXCY_L3 (.LO(C3),.CI(C2),.DI(A[3]),.S(I[3]) ); - MUXCY_L MUXCY_L4 (.LO(C4),.CI(C3),.DI(A[4]),.S(I[4]) ); - MUXCY_L MUXCY_L5 (.LO(C5),.CI(C4),.DI(A[5]),.S(I[5]) ); - MUXCY_D MUXCY_D6 (.LO(C6),.O(C6O),.CI(C5),.DI(A[6]),.S(I[6]) ); - MUXCY MUXCY_7 (.O(CO),.CI(C6),.DI(A[7]),.S(I[7]) ); - XORCY XORCY0 (.O(S[0]),.CI(CI),.LI(I[0])); - XORCY XORCY1 (.O(S[1]),.CI(C0),.LI(I[1])); - XORCY XORCY2 (.O(S[2]),.CI(C1),.LI(I[2])); - XORCY XORCY3 (.O(S[3]),.CI(C2),.LI(I[3])); - XORCY XORCY4 (.O(S[4]),.CI(C3),.LI(I[4])); - XORCY XORCY5 (.O(S[5]),.CI(C4),.LI(I[5])); - XORCY XORCY6 (.O(S[6]),.CI(C5),.LI(I[6])); - XORCY XORCY7 (.O(S[7]),.CI(C6),.LI(I[7])); - XOR2 X1(.O(OFL),.I0(C6O),.I1(CO)); -endmodule - -module NewAlu(input [10:0] OP, // ALU Operation - input [7:0] A, // Registers input - input [7:0] X, // "" - input [7:0] Y, // "" - input [7:0] S, // "" - input [7:0] M, // Secondary input to ALU - input [7:0] T, // Secondary input to ALU - // -- Flags Input - input CI, // Carry In - input VI, // Overflow In - // -- Flags output - output reg CO, // Carry out - output reg VO, // Overflow out - output reg SO, // Sign out - output reg ZO, // zero out - // -- Result output - output reg [7:0] Result,// Result out - output reg [7:0] IntR); // Intermediate result out - // Crack the ALU Operation - wire [1:0] o_left_input, o_right_input; - wire [2:0] o_first_op, o_second_op; - wire o_fc; - assign {o_left_input, o_right_input, o_first_op, o_second_op, o_fc} = OP; - - // Determine left, right inputs to Add/Sub ALU. - reg [7:0] L, R; - reg CR; - always begin - casez(o_left_input) - 0: L = A; - 1: L = Y; - 2: L = X; - 3: L = A & X; - endcase - casez(o_right_input) - 0: R = M; - 1: R = T; - 2: R = L; - 3: R = S; - endcase - CR = CI; - casez(o_first_op[2:1]) - 0: {CR, IntR} = {R, CI & o_first_op[0]}; // SHL, ROL - 1: {IntR, CR} = {CI & o_first_op[0], R}; // SHR, ROR - 2: IntR = R; // Passthrough - 3: IntR = R + (o_first_op[0] ? 8'b1 : 8'b11111111); // INC/DEC - endcase - end - wire [7:0] AddR; - wire AddCO, AddVO; - MyAddSub addsub(.A(L),.B(IntR),.CI(o_second_op[0] ? CR : 1'b1),.ADD(!o_second_op[2]), .S(AddR), .CO(AddCO), .OFL(AddVO)); - // Produce the output of the second stage. - always begin - casez(o_second_op) - 0: {CO, Result} = {CR, L | IntR}; - 1: {CO, Result} = {CR, L & IntR}; - 2: {CO, Result} = {CR, L ^ IntR}; - 3, 6, 7: {CO, Result} = {AddCO, AddR}; - 4, 5: {CO, Result} = {CR, IntR}; - endcase - // Final result - ZO = (Result == 0); - // Compute overflow flag - VO = VI; - casez(o_second_op) - 1: if (!o_fc) VO = IntR[6]; // Set V to 6th bit for BIT - 3: VO = AddVO; // ADC always sets V - 7: if (o_fc) VO = AddVO; // Only SBC sets V. - endcase - // Compute sign flag. It's always the uppermost bit of the result, - // except for BIT that sets it to the 7th input bit - SO = (o_second_op == 1 && !o_fc) ? IntR[7] : Result[7]; - end -endmodule - -module AddressGenerator(input clk, input ce, - input [4:0] Operation, - input [1:0] MuxCtrl, - input [7:0] DataBus, T, X, Y, - output [15:0] AX, - output Carry); - // Actual contents of registers - reg [7:0] AL, AH; - // Last operation generated a carry? - reg SavedCarry; - assign AX = {AH, AL}; - - wire [2:0] ALCtrl = Operation[4:2]; - wire [1:0] AHCtrl = Operation[1:0]; - - // Possible new value for AL. - wire [7:0] NewAL; - assign {Carry,NewAL} = {1'b0, (MuxCtrl[1] ? T : AL)} + {1'b0, (MuxCtrl[0] ? Y : X)}; - - // The other one - wire TmpVal = (!AHCtrl[1] | SavedCarry); - wire [7:0] TmpAdd = (AHCtrl[1] ? AH : AL) + {7'b0, TmpVal}; - - always @(posedge clk) if (ce) begin - SavedCarry <= Carry; - if (ALCtrl[2]) - case(ALCtrl[1:0]) - 0: AL <= NewAL; - 1: AL <= DataBus; - 2: AL <= TmpAdd; - 3: AL <= T; - endcase - - case(AHCtrl[1:0]) - 0: AH <= AH; - 1: AH <= 0; - 2: AH <= TmpAdd; - 3: AH <= DataBus; - endcase - end -endmodule - -module ProgramCounter(input clk, input ce, - input [1:0] LoadPC, - input GotInterrupt, - input [7:0] DIN, - input [7:0] T, - output reg [15:0] PC, output JumpNoOverflow); - reg [15:0] NewPC; - assign JumpNoOverflow = ((PC[8] ^ NewPC[8]) == 0) & LoadPC[0] & LoadPC[1]; - - always begin - // Load PC Control - case (LoadPC) - 0,1: NewPC = PC + {15'b0, (LoadPC[0] & ~GotInterrupt)}; - 2: NewPC = {DIN,T}; - 3: NewPC = PC + {{8{T[7]}},T}; - endcase - end - - always @(posedge clk) - if (ce) - PC <= NewPC; -endmodule - - -module CPU(input clk, input ce, input reset, - input [7:0] DIN, - input irq, - input nmi, - output reg [7:0] dout, output reg [15:0] aout, - output reg mr, - output reg mw); - reg [7:0] A, X, Y; - reg [7:0] SP, T, P; - reg [7:0] IR; - reg [2:0] State; - reg GotInterrupt; - - reg IsResetInterrupt; - wire [15:0] PC; - reg JumpTaken; - wire JumpNoOverflow; - - // De-multiplex microcode - wire [37:0] MicroCode; - wire [1:0] LoadSP = MicroCode[1:0]; // 7 LUT - wire [1:0] LoadPC = MicroCode[3:2]; // 12 LUT - wire [1:0] AddrBus = MicroCode[5:4]; // 18 LUT - wire [2:0] MemWrite = MicroCode[8:6]; // 10 LUT - wire [4:0] AddrCtrl = MicroCode[13:9]; - wire FlagCtrl = MicroCode[14]; // RegWrite + FlagCtrl = 22 LUT - wire [1:0] LoadT = MicroCode[16:15]; // 13 LUT - wire [1:0] StateCtrl = MicroCode[18:17]; - wire [2:0] FlagsCtrl = MicroCode[21:19]; - wire [15:0] IrFlags = MicroCode[37:22]; - - // Load Instruction Register? Force BRK on Interrupt. - wire [7:0] NextIR = (State == 0) ? (GotInterrupt ? 8'd0 : DIN) : IR; - wire IsBranchCycle1 = (IR[4:0] == 5'b10000) && State[0]; - - // Compute next state. - reg [2:0] NextState; - always begin - case (StateCtrl) - 0: NextState = State + 3'd1; - 1: NextState = (AXCarry ? 3'd4 : 3'd5); - 2: NextState = (IsBranchCycle1 && JumpTaken) ? 2 : 0; // Override next state if the branch is taken. - 3: NextState = (JumpNoOverflow ? 3'd0 : 3'd4); - endcase - end - - wire [15:0] AX; - wire AXCarry; -AddressGenerator addgen(clk, ce, AddrCtrl, {IrFlags[0], IrFlags[1]}, DIN, T, X, Y, AX, AXCarry); - -// Microcode table has a 1 clock latency (block ram). -MicroCodeTable micro2(clk, ce, reset, NextIR, NextState, MicroCode); - - wire [7:0] AluR; - wire [7:0] AluIntR; - wire CO, VO, SO,ZO; -NewAlu new_alu(IrFlags[15:5], A,X,Y,SP,DIN,T, P[0], P[6], CO, VO, SO, ZO, AluR, AluIntR); - -// Registers -always @(posedge clk) if (reset) begin - A <= 0; - X <= 0; - Y <= 0; -end else if (ce) begin - if (FlagCtrl & IrFlags[2]) X <= AluR; - if (FlagCtrl & IrFlags[3]) A <= AluR; - if (FlagCtrl & IrFlags[4]) Y <= AluR; -end - -// Program counter -ProgramCounter pc(clk, ce, LoadPC, GotInterrupt, DIN, T, PC, JumpNoOverflow); - -reg IsNMIInterrupt; -reg LastNMI; -// NMI is triggered at any time, except during reset, or when we're in the middle of -// reading the vector address -wire turn_nmi_on = (AddrBus != 3) && !IsResetInterrupt && nmi && !LastNMI; -// Controls whether we'll remember the state in LastNMI -wire nmi_remembered = (AddrBus != 3) && !IsResetInterrupt ? nmi : LastNMI; -// NMI flag is cleared right after we read the vector address -wire turn_nmi_off = (AddrBus == 3) && (State[0] == 0); -// Controls whether IsNmiInterrupt will get set -wire nmi_active = turn_nmi_on ? 1 : turn_nmi_off ? 0 : IsNMIInterrupt; -always @(posedge clk) begin - if (reset) begin - IsNMIInterrupt <= 0; - LastNMI <= 0; - end else if (ce) begin - IsNMIInterrupt <= nmi_active; - LastNMI <= nmi_remembered; - end -end - -// Generate outputs from module... -always begin - dout = 8'bX; - case (MemWrite[1:0]) - 'b00: dout = T; - 'b01: dout = AluR; - 'b10: dout = {P[7:6], 1'b1, !GotInterrupt, P[3:0]}; - 'b11: dout = State[0] ? PC[7:0] : PC[15:8]; - endcase - mw = MemWrite[2] && !IsResetInterrupt; // Prevent writing while handling a reset - mr = !mw; -end - -always begin - case (AddrBus) - 0: aout = PC; - 1: aout = AX; - 2: aout = {8'h01, SP}; - // irq/BRK vector FFFE - // nmi vector FFFA - // Reset vector FFFC - 3: aout = {13'b1111_1111_1111_1, !IsNMIInterrupt, !IsResetInterrupt, ~State[0]}; - endcase -end - - -always @(posedge clk) begin - if (reset) begin - // Reset runs the BRK instruction as usual. - State <= 0; - IR <= 0; - GotInterrupt <= 1; - IsResetInterrupt <= 1; - P <= 'h24; - SP <= 0; - T <= 0; - JumpTaken <= 0; - end else if (ce) begin - // Stack pointer control. - // The operand is an optimization that either - // returns -1,0,1 depending on LoadSP - case (LoadSP) - 0,2,3: SP <= SP + { {7{LoadSP[0]}}, LoadSP[1] }; - 1: SP <= X; - endcase - - // LoadT control - case (LoadT) - 2: T <= DIN; - 3: T <= AluIntR; - endcase - - if (FlagCtrl) begin - case(FlagsCtrl) - 0: P <= P; // No Op - 1: {P[0], P[1], P[6], P[7]} <= {CO, ZO, VO, SO}; // ALU - 2: P[2] <= 1; // BRK - 3: P[6] <= 0; // CLV - 4: {P[7:6],P[3:0]} <= {DIN[7:6], DIN[3:0]}; // RTI/PLP - 5: P[0] <= IR[5]; // CLC/SEC - 6: P[2] <= IR[5]; // CLI/SEI - 7: P[3] <= IR[5]; // CLD/SED - endcase - end - - // Compute if the jump is to be taken. Result is stored in a flipflop, so - // it won't be available until next cycle. - // NOTE: Using DIN here. DIN is IR at cycle 0. This means JumpTaken will - // contain the Jump status at cycle 1. - case (DIN[7:5]) - 0: JumpTaken <= ~P[7]; // BPL - 1: JumpTaken <= P[7]; // BMI - 2: JumpTaken <= ~P[6]; // BVC - 3: JumpTaken <= P[6]; // BVS - 4: JumpTaken <= ~P[0]; // BCC - 5: JumpTaken <= P[0]; // BCS - 6: JumpTaken <= ~P[1]; // BNE - 7: JumpTaken <= P[1]; // BEQ - endcase - - // Check the interrupt status on the last cycle of the current instruction, - // (or on cycle #1 of any branch instruction) - if (StateCtrl == 2'b10) begin - GotInterrupt <= (irq & ~P[2]) | nmi_active; - IsResetInterrupt <= 0; - end - - IR <= NextIR; - State <= NextState; - end -end -endmodule diff --git a/cores/nes/src/nes.v b/cores/nes/src/nes.v index afe195c..6740193 100644 --- a/cores/nes/src/nes.v +++ b/cores/nes/src/nes.v @@ -160,7 +160,7 @@ module NES(input clk, input reset, input ce, if (reset) cpu_cycle_counter <= 0; else if (ce) - cpu_cycle_counter <= (cpu_cycle_counter == 2) ? 0 : cpu_cycle_counter + 1; + cpu_cycle_counter <= (cpu_cycle_counter == 2) ? 2'd0 : cpu_cycle_counter + 1'd1; end // Sample the NMI flag on cycle #0, otherwise if NMI happens on cycle #0 or #1, @@ -174,7 +174,7 @@ module NES(input clk, input reset, input ce, nmi_active <= nmi; end - wire apu_ce = ce && (cpu_cycle_counter == 2); + wire apu_ce = ce && (cpu_cycle_counter == 2); // -- CPU wire [15:0] cpu_addr; @@ -182,7 +182,8 @@ module NES(input clk, input reset, input ce, wire pause_cpu; reg apu_irq_delayed; reg mapper_irq_delayed; - T65 cpu + + T65 cpu ( .mode(0), .BCD_en(0), @@ -199,6 +200,8 @@ module NES(input clk, input reset, input ce, .DI(cpu_rnw ? from_data_bus : cpu_dout), .DO(cpu_dout) ); + + // -- DMA wire [15:0] dma_aout; wire dma_aout_enable; @@ -217,7 +220,7 @@ module NES(input clk, input reset, input ce, odd_or_even, // Even or odd cycle (addr == 'h4014 && mw_int), // Sprite trigger apu_dma_request, // DMC Trigger - cpu_rnw, // CPU in a read cycle? + cpu_rnw, // CPU in a read cycle? cpu_dout, // Data from cpu from_data_bus, // Data from RAM etc. apu_dma_addr, // DMC addr diff --git a/cores/nes/src/ppu.v b/cores/nes/src/ppu.v index c4f2f12..40ee2d2 100644 --- a/cores/nes/src/ppu.v +++ b/cores/nes/src/ppu.v @@ -1,6 +1,8 @@ // Copyright (c) 2012-2013 Ludvig Strigeus // This program is GPL Licensed. See COPYING for the full license. +// altera message_off 10935 + // Module handles updating the loopy scroll register module LoopyGen ( input clk, input ce, @@ -35,19 +37,19 @@ module LoopyGen ( if (is_rendering) begin // Increment course X scroll right after attribute table byte was fetched. if (cycle[2:0] == 3 && (cycle < 256 || cycle >= 320 && cycle < 336)) begin - loopy_v[4:0] <= loopy_v[4:0] + 1; + loopy_v[4:0] <= loopy_v[4:0] + 1'd1; loopy_v[10] <= loopy_v[10] ^ (loopy_v[4:0] == 31); end // Vertical Increment if (cycle == 251) begin - loopy_v[14:12] <= loopy_v[14:12] + 1; + loopy_v[14:12] <= loopy_v[14:12] + 1'd1; if (loopy_v[14:12] == 7) begin if (loopy_v[9:5] == 29) begin loopy_v[9:5] <= 0; loopy_v[11] <= !loopy_v[11]; end else begin - loopy_v[9:5] <= loopy_v[9:5] + 1; + loopy_v[9:5] <= loopy_v[9:5] + 1'd1; end end end @@ -88,7 +90,7 @@ module LoopyGen ( ppu_address_latch <= 0; //Reset PPU address latch end else if ((read || write) && ain == 7 && !is_rendering) begin // Increment address every time we accessed a reg - loopy_v <= loopy_v + (ppu_incr ? 32 : 1); + loopy_v <= loopy_v + (ppu_incr ? 15'd32 : 15'd1); end end assign loopy = loopy_v; @@ -127,7 +129,7 @@ module ClockGen(input clk, input ce, input reset, cycle <= 0; is_in_vblank <= 1; end else if (ce) begin - cycle <= end_of_line ? 0 : cycle + 1; + cycle <= end_of_line ? 1'd0 : cycle + 1'd1; is_in_vblank <= new_is_in_vblank; end // always @(posedge clk) if (ce) begin @@ -140,12 +142,11 @@ module ClockGen(input clk, input ce, input reset, second_frame <= 0; end else if (ce && end_of_line) begin // Once the scanline counter reaches end of 260, it gets reset to -1. - scanline <= exiting_vblank ? 9'b111111111 : scanline + 1; + scanline <= exiting_vblank ? 9'b111111111 : scanline + 1'd1; // The pre render flag is set while we're on scanline -1. is_pre_render <= exiting_vblank; - if (exiting_vblank) - second_frame <= !second_frame; + //if (exiting_vblank) second_frame <= !second_frame; end endmodule // ClockGen @@ -228,11 +229,12 @@ module SpriteRAM(input clk, input ce, output reg spr_overflow, // Set to true if we had more than 8 objects on a scan line. Reset when exiting vblank. output reg sprite0); // True if sprite#0 is included on the scan line currently being painted. reg [7:0] sprtemp[0:31]; // Sprite Temporary Memory. 32 bytes. - reg [7:0] oam[0:255]; // Sprite OAM. 256 bytes. reg [7:0] oam_ptr; // Pointer into oam_ptr. reg [2:0] p; // Upper 3 bits of pointer into temp, the lower bits are oam_ptr[1:0]. reg [1:0] state; // Current state machine state - wire [7:0] oam_data = oam[oam_ptr]; + reg [7:0] oam[256]; // Sprite OAM. 256 bytes. + reg [7:0] oam_data; + // Compute the current address we read/write in sprtemp. reg [4:0] sprtemp_ptr; // Check if the current Y coordinate is inside. @@ -282,13 +284,18 @@ module SpriteRAM(input clk, input ce, new_oam_ptr[1:0] = oam_ptr[1:0] + {1'b0, oam_inc[0]}; {oam_wrapped, new_oam_ptr[7:2]} = {1'b0, oam_ptr[7:2]} + {6'b0, oam_inc[1]}; end + + wire [7:0] oam_ptr_tmp = oam_ptr_load ? data_in : new_oam_ptr; always @(posedge clk) if (ce) begin // Some bits of the OAM are hardwired to zero. - if (oam_load) - oam[oam_ptr] <= (oam_ptr & 3) == 2 ? data_in & 8'hE3: data_in; - if (cycle[0] && sprites_enabled || oam_load || oam_ptr_load) begin - oam_ptr <= oam_ptr_load ? data_in : new_oam_ptr; + if (oam_load) begin + oam[oam_ptr] <= (oam_ptr & 3) == 2 ? data_in & 8'hE3: data_in; + oam_data <= (oam_ptr & 3) == 2 ? data_in & 8'hE3: data_in; + end + if((cycle[0] && sprites_enabled) || oam_load || oam_ptr_load) begin + oam_ptr <= oam_ptr_tmp; + oam_data <= oam[oam_ptr_tmp]; end // Set overflow flag? if (sprites_enabled && state == 2'b11 && spr_is_inside) @@ -305,7 +312,7 @@ module SpriteRAM(input clk, input ce, // Update state machine on every second cycle. if (cycle[0]) begin // Increment p whenever oam_ptr carries in state 0 or 1. - if (!state[1] && oam_ptr[1:0] == 2'b11) p <= p + 1; + if (!state[1] && oam_ptr[1:0] == 2'b11) p <= p + 1'd1; // Set sprite0 if sprite1 was included on the scan line casez({state, (p == 7) && (oam_ptr[1:0] == 2'b11), oam_wrapped}) 4'b00_0_?: state <= 2'b00; // State #0: Keep filling @@ -322,6 +329,7 @@ module SpriteRAM(input clk, input ce, state <= 0; p <= 0; oam_ptr <= 0; + oam_data <= oam[0]; sprite0_curr <= 0; sprite0 <= sprite0_curr; end @@ -355,7 +363,7 @@ module SpriteAddressGen(input clk, input ce, wire load_pix2 = (cycle == 7) && enabled; reg dummy_sprite; // Set if attrib indicates the sprite is invalid. // Flip incoming vram data based on flipx. Zero out the sprite if it's invalid. The bits are already flipped once. - wire [7:0] vram_f = dummy_sprite ? 0 : + wire [7:0] vram_f = dummy_sprite ? 8'd0 : !flip_x ? {vram_data[0], vram_data[1], vram_data[2], vram_data[3], vram_data[4], vram_data[5], vram_data[6], vram_data[7]} : vram_data; wire [3:0] y_f = temp_y ^ {flip_y, flip_y, flip_y, flip_y}; @@ -679,7 +687,7 @@ module PPU(input clk, input ce, input reset, // input clock 21.48 MHz / 4. 1 always @(posedge clk) if (ce) begin if (vram_read_delayed) vram_latch <= vram_din; - vram_read_delayed = vram_r; + vram_read_delayed <= vram_r; end // Value currently being written to video ram