diff --git a/cores/SamCoupe/asic.v b/cores/SamCoupe/asic.v index d6f0aeb..6a60669 100644 --- a/cores/SamCoupe/asic.v +++ b/cores/SamCoupe/asic.v @@ -67,12 +67,12 @@ module asic ( HBPORCH = 64, LBORDER = 48; - parameter HTOTAL = HACTIVEREGION + - RBORDER + + parameter HTOTAL = RBORDER + HFPORCH + HSYNC + HBPORCH + - LBORDER; + LBORDER + + HACTIVEREGION; parameter VACTIVEREGION = 192, BBORDER = 48, @@ -89,19 +89,11 @@ module asic ( TBORDER; // Start of vertical sync, horizontal counter (last 4 scanlines) - parameter BEGINVSYNCH = HACTIVEREGION + RBORDER + HFPORCH + HSYNC + HBPORCH; + parameter BEGINVSYNCH = 0; - // Start and end of vertical retrace interrupt, horizontal counter - parameter BEGINVINTH = BEGINVSYNCH; //HACTIVEREGION + RBORDER + HFPORCH; - parameter ENDVINTH = (BEGINVINTH + 256)%HTOTAL; - - // Start and end of vertical retrace interrupt, vertical counter - parameter BEGINVINTV = VACTIVEREGION + BBORDER + VFPORCH - 1; - parameter ENDVINTV = VACTIVEREGION + BBORDER + VFPORCH; - - // Start and end of raster interrupt, horizontal counter - parameter BEGINHINTH = HACTIVEREGION + RBORDER; - parameter ENDHINTH = (BEGINHINTH + 256)%HTOTAL; + // Start and end of vertical sync + parameter BEGINVSYNCV = VACTIVEREGION + BBORDER + VFPORCH; + parameter ENDVSYNCV = BEGINVSYNCV + 4; parameter IOADDR_VMPR = 8'd252, IOADDR_HMPR = 8'd251, @@ -115,12 +107,7 @@ module asic ( ////////////////////////////////////////////////////////////////////////// // IO regs -`ifdef SYNTH reg [7:0] vmpr = 8'h00; // port 252. bit 7 is not used. R/W -`else - reg [7:0] vmpr = 8'b01100000; // port 252. bit 7 is not used. R/W. Mode 4 for simulation - -`endif wire [1:0] screen_mode = vmpr[6:5]; wire [4:0] screen_page = vmpr[4:0]; @@ -130,9 +117,10 @@ module asic ( wire rom_in_section_d = lmpr[6]; wire write_protect_section_a = lmpr[7]; - reg [7:0] hmpr = 8'h00; // port 251. Bit 7 is not used for now. R/W + reg [7:0] hmpr = 8'h00; // port 251. wire [4:0] high_page = hmpr[4:0]; wire [1:0] clut_mode_3_hi = hmpr[6:5]; + wire external_memory = hmpr[7]; reg [7:0] border = 8'h00; // port 254. Bit 6 not implemented. Write only. wire [3:0] clut_border = {border[5],border[2:0]}; @@ -166,15 +154,16 @@ module asic ( end ////////////////////////////////////////////////////////////////////////// - // Pixel counter and scan counter + // Pixel counter (horizontal) and scan counter (vertical) reg [9:0] hc = 10'h000; reg [8:0] vc = 9'h000; always @(posedge clk) begin - if (hc != (HTOTAL-1)) + if (hc != (HTOTAL-1)) begin hc <= hc + 1; + end else begin - hc <= 10'h000; + hc <= 10'h000; if (vc != (VTOTAL-1)) vc <= vc + 1; else @@ -183,24 +172,7 @@ module asic ( end ////////////////////////////////////////////////////////////////////////// - // HPEN and LPEN counters - always @(posedge clk) begin - if (hc[0] == 1'b0) begin - if (hc == HACTIVEREGION) begin - if (vc == VTOTAL-1) - hpen <= 8'h00; - else if (vc < VACTIVEREGION) - hpen <= hpen + 1; - end - if (hc < HACTIVEREGION) - lpen <= lpen + 1; - else - lpen <= 8'h00; - end - end - - ////////////////////////////////////////////////////////////////////////// - // Syncs and vertical retrace/raster line int generation + // Syncs and vertical retrace/raster line interrupt generation reg vint_n; reg rint_n; @@ -208,39 +180,15 @@ module asic ( csync = 1'b1; vint_n = 1'b1; rint_n = 1'b1; - if (hc >= (HACTIVEREGION + RBORDER + HFPORCH) && - hc < (HACTIVEREGION + RBORDER + HFPORCH + HSYNC)) - csync = 1'b0; - if ( (vc > BEGINVINTV && vc < (BEGINVINTV+4)) || - (vc == BEGINVINTV && hc >= BEGINVSYNCH) || - (vc == (BEGINVINTV+4) && hc < BEGINVSYNCH) ) - csync = ~csync; - if ( (vc == BEGINVINTV && hc >= BEGINVINTH) || - (vc == ENDVINTV && hc < ENDVINTH) ) -// if (vc == BEGINVINTV && hc >= BEGINVINTH) - vint_n = 1'b0; - if (lineint >= 8'd0 && lineint <= 8'd191) begin -// if (lineint == 8'd0) begin -// if (vc == VTOTAL-1 && hc >= BEGINHINTH || -// vc == 9'd0 && hc < ENDHINTH) -// rint_n = 1'b0; -// end -// else begin -// if ({1'b0, lineint} == vc-1 && hc >= BEGINHINTH || -// {1'b0, lineint} == vc && hc < ENDHINTH) -// rint_n = 1'b0; -// end -// end - if (lineint == 8'd0) begin - if (vc == VTOTAL-1 && hc >= BEGINHINTH) - rint_n = 1'b0; - end - else begin - if ({1'b0, lineint} == vc-1 && hc >= BEGINHINTH) - rint_n = 1'b0; - end - - end + if (hc >= (RBORDER + HFPORCH) && hc < (RBORDER + HFPORCH + HSYNC)) + csync = 1'b0; + if (vc >= BEGINVSYNCV && vc < ENDVSYNCV) + csync = ~csync; + if (vc == BEGINVSYNCV && hc < 256) + vint_n = 1'b0; + if (lineint >= 8'd0 && lineint <= 8'd191) + if ({1'b0, lineint} == vc && hc < 10'd256) + rint_n = 1'b0; end assign int_n = vint_n & rint_n; @@ -249,7 +197,7 @@ module asic ( reg fetching_pixels; always @* begin - if (vc>=0 && vc=0 && hc=0 && vc=256 && hc= (HACTIVEREGION + RBORDER) && - hc < (HACTIVEREGION + RBORDER + HFPORCH + HSYNC + HBPORCH) ) || - (vc >= (VACTIVEREGION + BBORDER) && - vc < (VACTIVEREGION + BBORDER + VFPORCH + VSYNC + VBPORCH) ) || - (screen_off == 1'b1) ) - blank_time = 1'b1; - else - blank_time = 1'b0; + blank_time = 1'b0; + if (screen_off == 1'b1) + blank_time = 1'b1; + if (hc >= RBORDER && hc < (RBORDER + HFPORCH + HSYNC + HBPORCH)) + blank_time = 1'b1; + if (vc >= (VACTIVEREGION + BBORDER) && vc < (VACTIVEREGION + BBORDER + VFPORCH + VSYNC + VBPORCH)) + blank_time = 1'b1; end ////////////////////////////////////////////////////////////////////////// @@ -277,20 +224,24 @@ module asic ( always @* begin mem_contention = 1'b0; + io_contention = 1'b0; - if (hc[3:0]<4'd10) + if (screen_off == 1'b0 && hc[3:0]<4'd10) io_contention = 1'b1; - else - io_contention = 1'b0; - + if (screen_off == 1'b1 && (hc[3:0]==4'd0 || + hc[3:0]==4'd1 || + hc[3:0]==4'd8 || + hc[3:0]==4'd9) ) + io_contention = 1'b1; + if (fetching_pixels == 1'b1 && hc[3:0]<4'd10) mem_contention = 1'b1; - else if (fetching_pixels == 1'b0 && (hc[3:0]==4'd0 || - hc[3:0]==4'd1 || - hc[3:0]==4'd8 || - hc[3:0]==4'd9) ) + if (fetching_pixels == 1'b0 && (hc[3:0]==4'd0 || + hc[3:0]==4'd1 || + hc[3:0]==4'd8 || + hc[3:0]==4'd9) ) mem_contention = 1'b1; - if (screen_mode == 2'b00 && hc[3:0]<4'd10 && hc[9:4]<6'd40) + if (screen_mode == 2'b00 && hc[3:0]<4'd10 && (hc<10'd128 || hc>=10'd256)) mem_contention = 1'b1; // extra contention for MODE 1 end assign asic_is_using_ram = mem_contention & fetching_pixels; @@ -305,7 +256,7 @@ module asic ( wait_n = 1'b1; else if (mem_contention == 1'b1 && mreq_n == 1'b0) wait_n = 1'b0; - else if (io_contention == 1'b1 && iorq_n == 1'b0) + else if (io_contention == 1'b1 && iorq_n == 1'b0 && (rd_n == 1'b0 || wr_n == 1'b0)) wait_n = 1'b0; end @@ -380,7 +331,7 @@ module asic ( else begin // showing border sregm12 <= 8'h00; attrreg <= {1'b0, clut_border, 3'b000}; - sregm3 <= { {16{clut_border[1:0]}} }; + sregm3 <= { {16{clut_border[0],clut_border[1]}} }; sregm4 <= { {8{clut_border}} }; hibits_clut_m3 <= clut_border[3:2]; end @@ -411,7 +362,7 @@ module asic ( else index = {attrreg[6],attrreg[5:3]}; end - 2'd2: index = {hibits_clut_m3, sregm3[31:30]}; + 2'd2: index = {hibits_clut_m3, sregm3[30], sregm3[31]}; 2'd3: index = sregm4[31:28]; endcase if (blank_time == 1'b1) @@ -424,6 +375,29 @@ module asic ( assign b = {pixel[4], pixel[0]}; assign bright = pixel[3]; + ////////////////////////////////////////////////////////////////////////// + // HPEN and LPEN counters + reg iorq_prev = 1'b1; + reg [7:0] hpen_internal = 8'h00; + + always @(posedge clk) begin + if (hc == 10'd255 && vc == 9'd0) begin + hpen_internal <= 8'h00; + end + else if (hc == (HTOTAL-1)) begin + if (hpen_internal != 8'hC0) + hpen_internal <= hpen_internal + 1; + end + end + + always @(posedge clk) begin + iorq_prev <= iorq_n; + if (iorq_prev == 1'b1 && iorq_n == 1'b0) begin // falling edge IORQ + lpen <= (hc<10'd256 || vc>=9'd192)? {7'b0000000,index[0]} : (hc[8:1] ^ 8'h80); // fast way to add 128 to hc[8:1] + hpen <= (screen_off == 1'b1)? 8'd192 : hpen_internal; + end + end + ////////////////////////////////////////////////////////////////////////// // CPU memory address and control signal generation @@ -437,8 +411,11 @@ module asic ( else if (mreq_n == 1'b0 && cpuaddr>=16'hC000 && rom_in_section_d==1'b1) begin romcs_n = 1'b0; end - else if (mreq_n == 1'b0 /*&& (contention == 1'b0 || fetching_pixels == 1'b0)*/ ) begin - ramcs_n = 1'b0; + else if (mreq_n == 1'b0) begin + if (cpuaddr >= 16'h8000 && external_memory == 1'b1) // disable internal RAM if bit 7 HMPR is set + ramcs_n = 1'b1; + else + ramcs_n = 1'b0; end end @@ -476,11 +453,7 @@ module asic ( // Write to IO ports from CPU always @(posedge clk) begin if (rst_n == 1'b0) begin -`ifdef SYNTH vmpr <= 8'h00; -`else - vmpr <= 8'b01100000; -`endif lmpr <= 8'h00; hmpr <= 8'h00; border <= 8'h00; @@ -512,7 +485,7 @@ module asic ( if (iorq_n == 1'b0 && rd_n == 1'b0) begin data_enable_n = 1'b0; if (cpuaddr[7:0] == IOADDR_BORDER) - data_to_cpu = {1'b0, ear, 1'b0, keyboard[4:0]}; + data_to_cpu = {screen_off, ear, 1'b0, keyboard[4:0]}; else if (cpuaddr[7:0] == IOADDR_ATTRIB) data_to_cpu = vram_byte3; else if (cpuaddr[7:0] == IOADDR_STATUS) diff --git a/cores/SamCoupe/audio_management.v b/cores/SamCoupe/audio_management.v new file mode 100644 index 0000000..c40ec95 --- /dev/null +++ b/cores/SamCoupe/audio_management.v @@ -0,0 +1,101 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 04:04:00 04/01/2012 +// Design Name: +// Module Name: sigma_delta_dac +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + +`define MSBI 8 // Most significant Bit of DAC input + +//This is a Delta-Sigma Digital to Analog Converter +module dac (DACout, DACin, Clk, Reset); + output DACout; // This is the average output that feeds low pass filter + input [`MSBI:0] DACin; // DAC input (excess 2**MSBI) + input Clk; + input Reset; + + reg DACout; // for optimum performance, ensure that this ff is in IOB + reg [`MSBI+2:0] DeltaAdder; // Output of Delta adder + reg [`MSBI+2:0] SigmaAdder; // Output of Sigma adder + reg [`MSBI+2:0] SigmaLatch = 1'b1 << (`MSBI+1); // Latches output of Sigma adder + reg [`MSBI+2:0] DeltaB; // B input of Delta adder + + always @(SigmaLatch) DeltaB = {SigmaLatch[`MSBI+2], SigmaLatch[`MSBI+2]} << (`MSBI+1); + always @(DACin or DeltaB) DeltaAdder = DACin + DeltaB; + always @(DeltaAdder or SigmaLatch) SigmaAdder = DeltaAdder + SigmaLatch; + always @(posedge Clk or posedge Reset) + begin + if(Reset) + begin + SigmaLatch <= #1 1'b1 << (`MSBI+1); + DACout <= #1 1'b0; + end + else + begin + SigmaLatch <= #1 SigmaAdder; + DACout <= #1 SigmaLatch[`MSBI+2]; + end + end +endmodule + +module mixer ( + input wire clk, + input wire rst_n, + input wire ear, + input wire mic, + input wire spk, + input wire [7:0] saa_left, + input wire [7:0] saa_right, + output wire audio_left, + output wire audio_right + ); + + reg [6:0] beeper; + always @* begin + beeper = 7'd0; + if (ear == 1'b1) + beeper = beeper + 7'd38; // 30% of total output + if (mic == 1'b1) + beeper = beeper + 7'd38; // 30% of total output + if (spk == 1'b1) + beeper = beeper + 7'd51; // 40% of total output + end + + wire [8:0] next_sample_l = beeper + saa_left; + wire [8:0] next_sample_r = beeper + saa_right; + + reg [8:0] sample_l, sample_r; + always @(posedge clk) begin + sample_l <= next_sample_l; + sample_r <= next_sample_r; + end + + dac audio_dac_left ( + .DACout(audio_left), + .DACin(sample_l), + .Clk(clk), + .Reset(~rst_n) + ); + + dac audio_dac_right ( + .DACout(audio_right), + .DACin(sample_r), + .Clk(clk), + .Reset(~rst_n) + ); + +endmodule diff --git a/cores/SamCoupe/compressor_lut.hex b/cores/SamCoupe/compressor_lut.hex new file mode 100644 index 0000000..d5f0cd6 --- /dev/null +++ b/cores/SamCoupe/compressor_lut.hex @@ -0,0 +1,256 @@ +00 +05 +08 +0B +0E +10 +13 +15 +18 +1A +1C +1E +20 +22 +24 +26 +28 +2A +2C +2E +2F +31 +33 +35 +36 +38 +3A +3B +3D +3F +40 +42 +44 +45 +47 +48 +4A +4B +4D +4F +50 +52 +53 +55 +56 +57 +59 +5A +5C +5D +5F +60 +62 +63 +64 +66 +67 +69 +6A +6B +6D +6E +6F +71 +72 +73 +75 +76 +77 +79 +7A +7B +7D +7E +7F +81 +82 +83 +84 +86 +87 +88 +89 +8B +8C +8D +8E +90 +91 +92 +93 +95 +96 +97 +98 +9A +9B +9C +9D +9E +A0 +A1 +A2 +A3 +A4 +A6 +A7 +A8 +A9 +AA +AB +AD +AE +AF +B0 +B1 +B2 +B4 +B5 +B6 +B7 +B8 +B9 +BA +BC +BD +BE +BF +C0 +C1 +C2 +C4 +C5 +C6 +C7 +C8 +C9 +CA +CB +CC +CE +CF +D0 +D1 +D2 +D3 +D4 +D5 +D6 +D7 +D9 +DA +DB +DC +DD +DE +DF +E0 +E1 +E2 +E3 +E4 +E5 +E6 +E8 +E9 +EA +EB +EC +ED +EE +EF +F0 +F1 +F2 +F3 +F4 +F5 +F6 +F7 +F8 +F9 +FA +FB +FC +FD +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF +FF diff --git a/cores/SamCoupe/gen_curva_compresor.c b/cores/SamCoupe/gen_curva_compresor.c new file mode 100644 index 0000000..412547c --- /dev/null +++ b/cores/SamCoupe/gen_curva_compresor.c @@ -0,0 +1,27 @@ +#include +#include + +#define GAMMA 0.75 + +int main() +{ + FILE *f; + int i,v; + double x; + + f = fopen ("compressor_lut.hex", "wt"); + for (i=0;i<256;i++) + { + if (i<=186) + { + x = i/186.0; + v = 255*pow(x,GAMMA); + } + else + v = 255; + printf ("%4d -> %4d\n", i, v); + fprintf (f, "%.2X\n", v); + } + fclose (f); + return 0; +} diff --git a/cores/SamCoupe/ps2_keyb.v b/cores/SamCoupe/ps2_keyb.v index 6cfdd4a..537ee88 100644 --- a/cores/SamCoupe/ps2_keyb.v +++ b/cores/SamCoupe/ps2_keyb.v @@ -3,14 +3,14 @@ ////////////////////////////////////////////////////////////////////////////////// // Company: -// Engineer: +// Engineer: Miguel Angel Rodriguez Jodar // -// Create Date: 15:18:53 06/03/2015 -// Design Name: -// Module Name: ps2_keyb -// Project Name: -// Target Devices: -// Tool versions: +// Create Date: 15:18:53 03/06/2015 +// Design Name: SAM Coupé clone +// Module Name: ps2_keyb +// Project Name: SAM Coupé clone +// Target Devices: Spartan 6 +// Tool versions: ISE 12.4 // Description: // // Dependencies: diff --git a/cores/SamCoupe/relojes.v b/cores/SamCoupe/relojes.v index ebfbce8..fbb368e 100644 --- a/cores/SamCoupe/relojes.v +++ b/cores/SamCoupe/relojes.v @@ -74,10 +74,11 @@ module relojes // Clock out ports output wire CLK_OUT1, output wire CLK_OUT2, - output wire CLK_OUT3 + output wire CLK_OUT3, + output wire CLK_OUT4 ); - wire clkin1, clkout0, clkout1, clkout2; + wire clkin1, clkout0, clkout1, clkout2, clkout3; // Input buffering //------------------------------------ @@ -95,7 +96,6 @@ module relojes wire drdy_unused; wire locked_unused; wire clkfbout; - wire clkout3_unused; wire clkout4_unused; wire clkout5_unused; @@ -114,7 +114,10 @@ module relojes .CLKOUT1_DUTY_CYCLE (0.500), .CLKOUT2_DIVIDE (100), .CLKOUT2_PHASE (0.000), - .CLKOUT2_DUTY_CYCLE (0.500), + .CLKOUT3_DUTY_CYCLE (0.500), + .CLKOUT3_DIVIDE (75), + .CLKOUT3_PHASE (0.000), + .CLKOUT3_DUTY_CYCLE (0.500), .CLKIN_PERIOD (20.0), .REF_JITTER (0.010)) pll_base_inst @@ -123,7 +126,7 @@ module relojes .CLKOUT0 (clkout0), .CLKOUT1 (clkout1), .CLKOUT2 (clkout2), - .CLKOUT3 (clkout3_unused), + .CLKOUT3 (clkout3), .CLKOUT4 (clkout4_unused), .CLKOUT5 (clkout5_unused), .LOCKED (locked_unused), @@ -141,7 +144,6 @@ module relojes (.O (CLK_OUT1), .I (clkout0)); - BUFG clkout2_buf (.O (CLK_OUT2), .I (clkout1)); @@ -150,6 +152,8 @@ module relojes (.O (CLK_OUT3), .I (clkout2)); - + BUFG clkout4_buf + (.O (CLK_OUT4), + .I (clkout3)); endmodule diff --git a/cores/SamCoupe/saa1099.v b/cores/SamCoupe/saa1099.v new file mode 100644 index 0000000..649de1f --- /dev/null +++ b/cores/SamCoupe/saa1099.v @@ -0,0 +1,645 @@ +`timescale 1ns / 1ps +`default_nettype none + +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: Miguel Angel Rodriguez Jodar +// +// Create Date: 17:20:11 08/09/2015 +// Design Name: SAM Coupé clone +// Module Name: saa1099 +// Project Name: SAM Coupé clone +// Target Devices: Spartan 6 +// Tool versions: ISE 12.4 +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module saa1099 ( + input wire clk, // 8 MHz + input wire rst_n, + input wire cs_n, + input wire a0, // 0=data, 1=address + input wire wr_n, + input wire [7:0] din, + output wire [7:0] out_l, + output wire [7:0] out_r + ); + // DTACK is not implemented. Sorry about that + + reg [7:0] amplit0, amplit1, amplit2, amplit3, amplit4, amplit5; + reg [8:0] freq0, freq1, freq2, freq3, freq4, freq5; + reg [7:0] oct10, oct32, oct54; + reg [7:0] freqenable; + reg [7:0] noiseenable; + reg [7:0] noisegen; + reg [7:0] envelope0, envelope1; + reg [7:0] ctrl; // frequency reset and sound enable for all channels + + reg [4:0] addr; // holds the address of the register to write to + + // Write values into internal registers + always @(posedge clk) begin + if (rst_n == 1'b0) begin + ctrl <= 8'h00; + end + else begin + if (cs_n == 1'b0 && wr_n == 1'b0) begin + if (a0 == 1'b1) + addr <= din[4:0]; + else begin + case (addr) + 5'h00: amplit0 <= din; + 5'h01: amplit1 <= din; + 5'h02: amplit2 <= din; + 5'h03: amplit3 <= din; + 5'h04: amplit4 <= din; + 5'h05: amplit5 <= din; + + 5'h08: freq0 <= 9'd510 - {1'b0, din}; + 5'h09: freq1 <= 9'd510 - {1'b0, din}; + 5'h0A: freq2 <= 9'd510 - {1'b0, din}; + 5'h0B: freq3 <= 9'd510 - {1'b0, din}; + 5'h0C: freq4 <= 9'd510 - {1'b0, din}; + 5'h0D: freq5 <= 9'd510 - {1'b0, din}; + + 5'h10: oct10 <= din; + 5'h11: oct32 <= din; + 5'h12: oct54 <= din; + + 5'h14: freqenable <= din; + 5'h15: noiseenable <= din; + 5'h16: noisegen <= din; + + 5'h18: envelope0 <= din; + 5'h19: envelope1 <= din; + + 5'h1C: ctrl <= din; + endcase + end + end + end + end + + wire gen0_tone; + wire gen1_tone; + wire gen2_tone; + wire gen3_tone; + wire gen4_tone; + wire gen5_tone; + + wire pulse_to_noise0, pulse_to_envelope0; + wire pulse_to_noise1, pulse_to_envelope1; + + wire noise0, noise1; + + wire [4:0] mixout0_l, mixout0_r; + wire [4:0] mixout1_l, mixout1_r; + wire [4:0] mixout2_l, mixout2_r; + wire [4:0] mixout2_l_with_env, mixout2_r_with_env; + wire [4:0] mixout3_l, mixout3_r; + wire [4:0] mixout4_l, mixout4_r; + wire [4:0] mixout5_l, mixout5_r; + wire [4:0] mixout5_l_with_env, mixout5_r_with_env; + + // Frequency and noise generators, top half + + saa1099_tone_gen freq_gen0 ( + .clk(clk), + .octave(oct10[2:0]), + .freq(freq0), + .out(gen0_tone), + .pulseout(pulse_to_noise0) + ); + + saa1099_tone_gen freq_gen1 ( + .clk(clk), + .octave(oct10[6:4]), + .freq(freq1), + .out(gen1_tone), + .pulseout(pulse_to_envelope0) + ); + + saa1099_tone_gen freq_gen2 ( + .clk(clk), + .octave(oct32[2:0]), + .freq(freq2), + .out(gen2_tone), + .pulseout() + ); + + saa1099_noise_gen noise_gen0 ( + .clk(clk), + .rst_n(rst_n), + .pulse_from_gen(pulse_to_noise0), + .noise_freq(noisegen[1:0]), + .out(noise0) + ); + + + // Frequency and noise generators, bottom half + + saa1099_tone_gen freq_gen3 ( + .clk(clk), + .octave(oct32[6:4]), + .freq(freq3), + .out(gen3_tone), + .pulseout(pulse_to_noise1) + ); + + saa1099_tone_gen freq_gen4 ( + .clk(clk), + .octave(oct54[2:0]), + .freq(freq4), + .out(gen4_tone), + .pulseout(pulse_to_envelope1) + ); + + saa1099_tone_gen freq_gen5 ( + .clk(clk), + .octave(oct54[6:4]), + .freq(freq5), + .out(gen5_tone), + .pulseout() + ); + + saa1099_noise_gen noise_gen1 ( + .clk(clk), + .rst_n(rst_n), + .pulse_from_gen(pulse_to_noise1), + .noise_freq(noisegen[5:4]), + .out(noise1) + ); + + + // Mixers + + sa1099_mixer_and_amplitude mixer0 ( + .clk(clk), + .en_tone(freqenable[0] == 1'b1 && noisegen[1:0] != 2'd3), // if gen0 is being used to generate noise, don't use this channel for tone output + .en_noise(noiseenable[0]), + .tone(gen0_tone), + .noise(noise0), + .amplitude_l(amplit0[3:0]), + .amplitude_r(amplit0[7:4]), + .out_l(mixout0_l), + .out_r(mixout0_r) + ); + + sa1099_mixer_and_amplitude mixer1 ( + .clk(clk), + .en_tone(freqenable[1] == 1'b1 && envelope0[7] == 1'b0), + .en_noise(noiseenable[1]), + .tone(gen1_tone), + .noise(noise0), + .amplitude_l(amplit1[3:0]), + .amplitude_r(amplit1[7:4]), + .out_l(mixout1_l), + .out_r(mixout1_r) + ); + + sa1099_mixer_and_amplitude mixer2 ( + .clk(clk), + .en_tone(freqenable[2]), + .en_noise(noiseenable[2]), + .tone(gen2_tone), + .noise(noise0), + .amplitude_l(amplit2[3:0]), + .amplitude_r(amplit2[7:4]), + .out_l(mixout2_l), + .out_r(mixout2_r) + ); + + sa1099_mixer_and_amplitude mixer3 ( + .clk(clk), + .en_tone(freqenable[3] == 1'b1 && noisegen[5:4] != 2'd3), // if gen3 is being used to generate noise, don't use this channel for tone output + .en_noise(noiseenable[3]), + .tone(gen3_tone), + .noise(noise1), + .amplitude_l(amplit3[3:0]), + .amplitude_r(amplit3[7:4]), + .out_l(mixout3_l), + .out_r(mixout3_r) + ); + + sa1099_mixer_and_amplitude mixer4 ( + .clk(clk), + .en_tone(freqenable[4] == 1'b1 && envelope1[7] == 1'b0), + .en_noise(noiseenable[4]), + .tone(gen4_tone), + .noise(noise1), + .amplitude_l(amplit4[3:0]), + .amplitude_r(amplit4[7:4]), + .out_l(mixout4_l), + .out_r(mixout4_r) + ); + + sa1099_mixer_and_amplitude mixer5 ( + .clk(clk), + .en_tone(freqenable[5]), + .en_noise(noiseenable[5]), + .tone(gen5_tone), + .noise(noise1), + .amplitude_l(amplit5[3:0]), + .amplitude_r(amplit5[7:4]), + .out_l(mixout5_l), + .out_r(mixout5_r) + ); + + + // Envelope generators + + saa1099_envelope_gen envelope_gen0 ( + .clk(clk), + .rst_n(rst_n), + .envreg(envelope0), + .write_to_envreg_addr(cs_n == 1'b0 && wr_n == 1'b0 && a0 == 1'b1 && din[4:0] == 5'h18), + .write_to_envreg_data(cs_n == 1'b0 && wr_n == 1'b0 && a0 == 1'b0 && addr == 5'h18), + .pulse_from_tonegen(pulse_to_envelope0), + .tone_en(freqenable[2]), + .noise_en(noiseenable[2]), + .sound_in_left(mixout2_l), + .sound_in_right(mixout2_r), + .sound_out_left(mixout2_l_with_env), + .sound_out_right(mixout2_r_with_env) + ); + + saa1099_envelope_gen envelope_gen1 ( + .clk(clk), + .rst_n(rst_n), + .envreg(envelope1), + .write_to_envreg_addr(cs_n == 1'b0 && wr_n == 1'b0 && a0 == 1'b1 && din[4:0] == 5'h19), + .write_to_envreg_data(cs_n == 1'b0 && wr_n == 1'b0 && a0 == 1'b0 && addr == 5'h19), + .pulse_from_tonegen(pulse_to_envelope1), + .tone_en(freqenable[5]), + .noise_en(noiseenable[5]), + .sound_in_left(mixout5_l), + .sound_in_right(mixout5_r), + .sound_out_left(mixout5_l_with_env), + .sound_out_right(mixout5_r_with_env) + ); + + // Final mix + + saa1099_output_mixer outmix_left ( + .clk(clk), + .sound_enable(ctrl[0]), + .i0(mixout0_l), + .i1(mixout1_l), + .i2(mixout2_l_with_env), + .i3(mixout3_l), + .i4(mixout4_l), + .i5(mixout5_l_with_env), + .o(out_l) + ); + + saa1099_output_mixer outmix_right ( + .clk(clk), + .sound_enable(ctrl[0]), + .i0(mixout0_r), + .i1(mixout1_r), + .i2(mixout2_r_with_env), + .i3(mixout3_r), + .i4(mixout4_r), + .i5(mixout5_r_with_env), + .o(out_r) + ); + + +endmodule + +module saa1099_tone_gen ( + input wire clk, + input wire [2:0] octave, + input wire [8:0] freq, + output reg out, + output reg pulseout +); + + reg [7:0] fcounter; + always @* begin + case (octave) + 3'd0: fcounter = 8'd255; + 3'd1: fcounter = 8'd127; + 3'd2: fcounter = 8'd63; + 3'd3: fcounter = 8'd31; + 3'd4: fcounter = 8'd15; + 3'd5: fcounter = 8'd7; + 3'd6: fcounter = 8'd3; + 3'd7: fcounter = 8'd1; + endcase + end + + reg [7:0] count = 8'd0; + always @(posedge clk) begin + if (count == fcounter) + count <= 8'd0; + else + count <= count + 1; + end + + reg pulse; + always @* begin + if (count == fcounter) + pulse = 1'b1; + else + pulse = 1'b0; + end + + initial out = 1'b0; + reg [8:0] cfinal = 9'd0; + always @(posedge clk) begin + if (pulse == 1'b1) begin + if (cfinal == freq) begin + cfinal <= 9'd0; + out <= ~out; + end + else + cfinal <= cfinal + 1; + end + end + + always @* begin + if (pulse == 1'b1 && cfinal == freq) + pulseout = 1'b1; + else + pulseout = 1'b0; + end +endmodule + +module saa1099_noise_gen ( + input wire clk, + input wire rst_n, + input wire pulse_from_gen, + input wire [1:0] noise_freq, + output wire out + ); + + reg [10:0] fcounter; + always @* begin + case (noise_freq) + 2'd0: fcounter = 11'd255; + 2'd1: fcounter = 11'd511; + 2'd2: fcounter = 11'd1023; + default: fcounter = 11'd2047; // actually not used + endcase + end + + reg [10:0] count = 11'd0; + always @(posedge clk) begin + if (count == fcounter) + count <= 11'd0; + else + count <= count + 1; + end + + reg [30:0] lfsr = 31'h11111111; + always @(posedge clk) begin + if (rst_n == 1'b0) + lfsr <= 31'h11111111; // just a seed + if ((noise_freq == 2'd3 && pulse_from_gen == 1'b1) || + (noise_freq != 2'd3 && count == fcounter)) begin + if ((lfsr[2] ^ lfsr[30]) == 1'b1) + lfsr <= {lfsr[29:0], 1'b1}; + else + lfsr <= {lfsr[29:0], 1'b0}; + end + end + + assign out = lfsr[0]; + +endmodule + +module sa1099_mixer_and_amplitude ( + input wire clk, + input wire en_tone, + input wire en_noise, + input wire tone, + input wire noise, + input wire [3:0] amplitude_l, + input wire [3:0] amplitude_r, + output reg [4:0] out_l, + output reg [4:0] out_r + ); + + reg [4:0] next_out_l, next_out_r; + always @* begin + next_out_l = 5'b0000; + next_out_r = 5'b0000; + if (en_tone == 1'b1) + if (tone == 1'b1) begin + next_out_l = next_out_l + {1'b0, amplitude_l}; + next_out_r = next_out_r + {1'b0, amplitude_r}; + end + if (en_noise == 1'b1) + if (noise == 1'b1) begin + next_out_l = next_out_l + {1'b0, amplitude_l}; + next_out_r = next_out_r + {1'b0, amplitude_r}; + end + end + + always @(posedge clk) begin + out_l <= next_out_l; + out_r <= next_out_r; + end +endmodule + +module saa1099_envelope_gen ( + input wire clk, + input wire rst_n, + input wire [7:0] envreg, + input wire write_to_envreg_addr, + input wire write_to_envreg_data, + input wire pulse_from_tonegen, + input wire tone_en, + input wire noise_en, + input wire [4:0] sound_in_left, + input wire [4:0] sound_in_right, + output wire [4:0] sound_out_left, + output wire [4:0] sound_out_right + ); + + reg [3:0] envelopes[0:511]; + integer i; + initial begin + // Generating envelopes + // 0 0 0 : ______________ + for (i=0;i<64;i=i+1) + envelopes[{3'b000,i[5:0]}] = 4'd0; + + // 0 0 1 : -------------- + for (i=0;i<64;i=i+1) + envelopes[{3'b001,i[5:0]}] = 4'd15; + + // 0 1 0 : \_____________ + for (i=0;i<16;i=i+1) + envelopes[{3'b010,i[5:0]}] = ~i[3:0]; + for (i=16;i<64;i=i+1) + envelopes[{3'b010,i[5:0]}] = 4'd0; + + // 0 1 1 : \|\|\|\|\|\|\|\ + for (i=0;i<64;i=i+1) + envelopes[{3'b011,i[5:0]}] = ~i[3:0]; + + // 1 0 0 : /\______________ + for (i=0;i<16;i=i+1) + envelopes[{3'b100,i[5:0]}] = i[3:0]; + for (i=16;i<32;i=i+1) + envelopes[{3'b100,i[5:0]}] = ~i[3:0]; + for (i=32;i<64;i=i+1) + envelopes[{3'b100,i[5:0]}] = 4'd0; + + // 1 0 1 : /\/\/\/\/\/\/\/\ + for (i=0;i<16;i=i+1) + envelopes[{3'b101,i[5:0]}] = i[3:0]; + for (i=16;i<32;i=i+1) + envelopes[{3'b101,i[5:0]}] = ~i[3:0]; + for (i=32;i<48;i=i+1) + envelopes[{3'b101,i[5:0]}] = i[3:0]; + for (i=48;i<64;i=i+1) + envelopes[{3'b101,i[5:0]}] = ~i[3:0]; + + // 1 1 0 : /|________________ + for (i=0;i<16;i=i+1) + envelopes[{3'b110,i[5:0]}] = i[3:0]; + for (i=16;i<64;i=i+1) + envelopes[{3'b110,i[5:0]}] = 4'd0; + + // 1 1 1 : /|/|/|/|/|/|/|/|/| + for (i=0;i<64;i=i+1) + envelopes[{3'b111,i[5:0]}] = i[3:0]; + end + + reg write_to_address_prev = 1'b0; + wire write_to_address_edge = (~write_to_address_prev & write_to_envreg_addr); + + reg write_to_data_prev = 1'b0; + wire write_to_data_edge = (~write_to_data_prev & write_to_envreg_data); + + reg [2:0] envshape = 3'b000; + reg stereoshape = 1'b0; + reg envclock = 1'b0; + wire env_enable = envreg[7]; + wire env_resolution = envreg[4]; + + reg pending_data = 1'b0; + + reg [5:0] envcounter = 6'd0; + always @(posedge clk) begin + if (rst_n == 1'b0) begin + envcounter <= 6'd0; + stereoshape <= 1'b0; + envshape <= 3'b000; + envclock <= 1'b0; + write_to_address_prev = 1'b0; + write_to_data_prev = 1'b0; + pending_data <= 1'b0; + end + else begin + write_to_address_prev <= write_to_envreg_addr; + write_to_data_prev <= write_to_envreg_data; + if (write_to_data_edge == 1'b1) + pending_data <= 1'b1; + if (env_enable == 1'b1) begin + if (envclock == 1'b0 && pulse_from_tonegen == 1'b1 || envclock == 1'b1 && write_to_address_edge == 1'b1) begin // pulse from internal or external clock? + if (envcounter == 6'd63) + envcounter <= 6'd32; + else begin + if (env_resolution == 1'b0) + envcounter <= envcounter + 1; + else + envcounter <= envcounter + 2; + end + if (envcounter == 6'd0 || + envcounter >= 6'd15 && (envshape == 3'b000 || envshape == 3'b010 || envshape == 3'b110) || + envcounter[3:0] == 4'd15 && (envshape == 3'b001 || envshape == 3'b011 || envshape == 3'b111) || + envcounter >= 6'd31 && envshape == 3'b100 || + envcounter[4:0] == 5'd31 && envshape ==3'b101) begin // find out when to updated buffered values + if (pending_data == 1'b1) begin // if we reached one of the designated points (3) or (4) and there is pending data, load it + envshape <= envreg[3:1]; + stereoshape <= envreg[0]; + envclock <= envreg[5]; + envcounter <= 6'd0; + pending_data <= 1'b0; + end + end + end + end + end + end + + reg [3:0] envleft = 4'b0000; + wire [3:0] envright = (stereoshape == 1'b0)? envleft : ~envleft; // bit 0 of envreg inverts envelope shape + always @(posedge clk) + envleft <= envelopes[{envshape,envcounter}]; // take current envelope from envelopes ROM + + wire [4:0] temp_out_left, temp_out_right; + + saa1099_amp_env_mixer modulate_left ( + .a(sound_in_left), + .b(envleft), + .o(temp_out_left) + ); + + saa1099_amp_env_mixer modulate_right ( + .a(sound_in_right), + .b(envright), + .o(temp_out_right) + ); + + assign sound_out_left = (env_enable == 1'b0)? sound_in_left : // if envelopes are not enabled, just bypass them + (env_enable == 1'b1 && tone_en == 1'b0 && noise_en == 1'b0)? {envleft, envleft[3]} : // if tone and noise are off, output is envelope signal itself + temp_out_left; // else it is original signal modulated by envelope + + assign sound_out_right = (env_enable == 1'b0)? sound_in_right : + (env_enable == 1'b1 && tone_en == 1'b0 && noise_en == 1'b0)? {envright, envright[3]} : + temp_out_right; +endmodule + +module saa1099_amp_env_mixer ( + input wire [4:0] a, // amplitude + input wire [3:0] b, // envelope + output wire [4:0] o // output + ); + + wire [6:0] res1 = ((b[0] == 1'b1)? a : 5'h00) + ((b[1] == 1'b1)? {a,1'b0} : 6'h00); + wire [8:0] res2 = ((b[2] == 1'b1)? {a,2'b00} : 7'h00) + ((b[3] == 1'b1)? {a,3'b000} : 8'h00); + wire [8:0] res3 = res1 + res2; + assign o = res3[8:4]; +endmodule + +module saa1099_output_mixer ( + input wire clk, + input wire sound_enable, + input wire [4:0] i0, + input wire [4:0] i1, + input wire [4:0] i2, + input wire [4:0] i3, + input wire [4:0] i4, + input wire [4:0] i5, + output reg [7:0] o + ); + + reg [7:0] compressor_table[0:255]; + initial begin + $readmemh ("compressor_lut.hex", compressor_table); + end + + reg [7:0] mix; + always @* begin + if (sound_enable == 1'b1) + mix = i0 + i1 + i2 + i3 + i4 + i5; + else + mix = 8'd0; + end + + always @(posedge clk) begin + o <= compressor_table[mix]; + end +endmodule + \ No newline at end of file diff --git a/cores/SamCoupe/samcoupe.v b/cores/SamCoupe/samcoupe.v index 14c1aff..e100bc1 100644 --- a/cores/SamCoupe/samcoupe.v +++ b/cores/SamCoupe/samcoupe.v @@ -3,14 +3,14 @@ ////////////////////////////////////////////////////////////////////////////////// // Company: -// Engineer: +// Engineer: Miguel Angel Rodriguez Jodar // -// Create Date: 03:54:40 07/25/2015 -// Design Name: -// Module Name: samcoupe -// Project Name: -// Target Devices: -// Tool versions: +// Create Date: 03:54:40 13/25/2015 +// Design Name: SAM Coupé clone +// Module Name: samcoupe +// Project Name: SAM Coupé clone +// Target Devices: Spartan 6 +// Tool versions: ISE 12.4 // Description: // // Dependencies: @@ -24,6 +24,7 @@ module samcoupe ( input wire clk24, input wire clk12, input wire clk6, + input wire clk8, input wire master_reset_n, // Video output output wire [1:0] r, @@ -82,8 +83,7 @@ module samcoupe ( // Audio signals wire mic, beep; - assign audio_out_left = ear; - assign audio_out_right = beep; + wire [7:0] saa_out_l, saa_out_r; // MUX from memory/devices to Z80 data bus assign data_to_cpu = (rom_oe_n == 1'b0)? data_from_rom : @@ -158,30 +158,12 @@ module samcoupe ( .dout(data_from_rom) ); -// ram_dual_port_turnos ram_512k ( -// .clk(clk24), -// .whichturn(asic_is_using_ram), -// .vramaddr(vramaddr), -// .cpuramaddr(cpuramaddr), -// .cpu_we_n(ram_we_n), -// .data_from_cpu(data_from_cpu), -// .data_to_asic(data_to_asic), -// .data_to_cpu(data_from_ram), -// // Actual interface with SRAM -// .sram_a(sram_addr), -// .sram_we_n(sram_we_n), -// .sram_d(sram_data) -// ); - - ram_dual_port ram_512k ( + ram_dual_port_turnos ram_512k ( .clk(clk24), .whichturn(asic_is_using_ram), .vramaddr(vramaddr), .cpuramaddr(cpuramaddr), - .mreq_n(ram_oe_n), - .rd_n(rd_n), - .wr_n(ram_we_n), - .rfsh_n(rfsh_n), + .cpu_we_n(ram_we_n), .data_from_cpu(data_from_cpu), .data_to_asic(data_to_asic), .data_to_cpu(data_from_ram), @@ -190,20 +172,25 @@ module samcoupe ( .sram_we_n(sram_we_n), .sram_d(sram_data) ); - -// ps2k el_teclado ( -// .clk(clk6), -// .ps2clk(clkps2), -// .ps2data(dataps2), -// .rows(kbrows[7:0]), -// .cols(kbcolumns[4:0]), -// .joy(), // Implementación joystick kempston en teclado numerico -// .scancode(), // El scancode original desde el teclado -// .rst(kb_rst_n), // esto son salidas, no entradas -// .nmi(kb_nmi_n), // Señales de reset y NMI -// .mrst() // generadas por pulsaciones especiales del teclado -// ); +// ram_dual_port ram_512k ( +// .clk(clk24), +// .whichturn(asic_is_using_ram), +// .vramaddr(vramaddr), +// .cpuramaddr(cpuramaddr), +// .mreq_n(ram_oe_n), +// .rd_n(rd_n), +// .wr_n(ram_we_n), +// .rfsh_n(rfsh_n), +// .data_from_cpu(data_from_cpu), +// .data_to_asic(data_to_asic), +// .data_to_cpu(data_from_ram), +// // Actual interface with SRAM +// .sram_a(sram_addr), +// .sram_we_n(sram_we_n), +// .sram_d(sram_data) +// ); + ps2_keyb el_teclado ( .clk(clk6), .clkps2(clkps2), @@ -228,4 +215,28 @@ module samcoupe ( .kbstatus_dout(), .oe_n_kbstatus() ); + + saa1099 el_saa ( + .clk(clk8), // 8 MHz + .rst_n(kb_rst_n), + .cs_n(~(cpuaddr[7:0] == 8'hFF && iorq_n == 1'b0)), + .a0(cpuaddr[8]), // 0=data, 1=address + .wr_n(wr_n), + .din(data_from_cpu), + .out_l(saa_out_l), + .out_r(saa_out_r) + ); + + mixer sam_audio_mixer ( + .clk(clk8), + .rst_n(kb_rst_n), + .ear(ear), + .mic(mic), + .spk(beep), + .saa_left(saa_out_l), + .saa_right(saa_out_r), + .audio_left(audio_out_left), + .audio_right(audio_out_right) + ); + endmodule diff --git a/cores/SamCoupe/samcoupe.xise b/cores/SamCoupe/samcoupe.xise index d01185e..1044dca 100644 --- a/cores/SamCoupe/samcoupe.xise +++ b/cores/SamCoupe/samcoupe.xise @@ -85,6 +85,14 @@ + + + + + + + + @@ -107,11 +115,11 @@ - + - + @@ -129,7 +137,7 @@ - + @@ -322,8 +330,8 @@ - - + + @@ -341,7 +349,7 @@ - + @@ -387,11 +395,11 @@ - + - + diff --git a/cores/SamCoupe/tb_asic.v b/cores/SamCoupe/tb_asic.v index 620e838..3f0e31d 100644 --- a/cores/SamCoupe/tb_asic.v +++ b/cores/SamCoupe/tb_asic.v @@ -51,10 +51,13 @@ module tb_asic; .data_enable_n(), .wait_n(), // RAM/ROM interface - .ramaddr(), + .vramaddr(), + .cpuramaddr(), .data_from_ram(8'hAA), .ramwr_n(), .romcs_n(), + .ramcs_n(), + .asic_is_using_ram(), // audio I/O .ear(1'b0), .mic(), diff --git a/cores/SamCoupe/tld_sam.v b/cores/SamCoupe/tld_sam.v index 6b88e80..37d5ae2 100644 --- a/cores/SamCoupe/tld_sam.v +++ b/cores/SamCoupe/tld_sam.v @@ -59,20 +59,22 @@ module tld_sam ( assign stdn = 1'b0; // fijar norma PAL assign stdnb = 1'b1; // y conectamos reloj PAL - wire clk24, clk12, clk6; + wire clk24, clk12, clk6, clk8; relojes los_relojes ( .CLK_IN1 (clk50mhz), // IN // Clock out ports - .CLK_OUT1 (clk24), // OUT - .CLK_OUT2 (clk12), // OUT - .CLK_OUT3 (clk6) // OUT + .CLK_OUT1 (clk24), // modulo multiplexor de SRAM + .CLK_OUT2 (clk12), // ASIC + .CLK_OUT3 (clk6), // CPU y teclado PS/2 + .CLK_OUT4 (clk8) // SAA1099 y DAC ); samcoupe maquina ( .clk24(clk24), .clk12(clk12), .clk6(clk6), + .clk8(clk8), .master_reset_n(1'b1), // esta señal es sólo para simulación // Video output .r(sam_r), diff --git a/cores/SamCoupe/tv80_core.v b/cores/SamCoupe/tv80_core.v index 13a2ad6..6a9d3aa 100644 --- a/cores/SamCoupe/tv80_core.v +++ b/cores/SamCoupe/tv80_core.v @@ -34,7 +34,7 @@ module tv80_core (/*AUTOARG*/ // Beginning of automatic inputs (from unused autoinst inputs) // End of automatics - parameter Mode = 1; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + parameter Mode = 0; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB parameter IOWait = 1; // 0 => Single cycle I/O, 1 => Std I/O cycle parameter Flag_C = 0; parameter Flag_N = 1; diff --git a/cores/SamCoupe/tv80n.v b/cores/SamCoupe/tv80n.v index d672608..70454a1 100644 --- a/cores/SamCoupe/tv80n.v +++ b/cores/SamCoupe/tv80n.v @@ -102,80 +102,65 @@ module tv80n (/*AUTOARG*/ .intcycle_n (intcycle_n) ); - always @* - begin - nxt_mreq_n = 1; - nxt_rd_n = 1; - nxt_iorq_n = 1; - nxt_wr_n = 1; - - if (mcycle[0]) - begin - if (tstate[1] || tstate[2]) - begin - nxt_rd_n = ~ intcycle_n; - nxt_mreq_n = ~ intcycle_n; - nxt_iorq_n = intcycle_n; - end + always @* begin + nxt_mreq_n = 1; + nxt_rd_n = 1; + nxt_iorq_n = 1; + nxt_wr_n = 1; + + if (mcycle[0]) begin + if (tstate[1] || tstate[2]) begin + nxt_rd_n = ~ intcycle_n; + nxt_mreq_n = ~ intcycle_n; + nxt_iorq_n = intcycle_n; + end end // if (mcycle[0]) - else - begin - if ((tstate[1] || tstate[2]) && !no_read && !write) - begin - nxt_rd_n = 1'b0; - nxt_iorq_n = ~ iorq; - nxt_mreq_n = iorq; - end - if (T2Write == 0) - begin - if (tstate[2] && write) - begin - nxt_wr_n = 1'b0; - nxt_iorq_n = ~ iorq; - nxt_mreq_n = iorq; + else begin + if ((tstate[1] || tstate[2]) && !no_read && !write) begin + nxt_rd_n = 1'b0; + nxt_iorq_n = ~ iorq; + nxt_mreq_n = iorq; + end + if (T2Write == 0) begin + if (tstate[2] && write) begin + nxt_wr_n = 1'b0; + nxt_iorq_n = ~ iorq; + nxt_mreq_n = iorq; end end - else - begin - if ((tstate[1] || (tstate[2] && !wait_n)) && write) - begin - nxt_wr_n = 1'b0; - nxt_iorq_n = ~ iorq; - nxt_mreq_n = iorq; - end - end // else: !if(T2write == 0) - end // else: !if(mcycle[0]) + else begin + if ((tstate[1] || (tstate[2] && !wait_n)) && write) begin + nxt_wr_n = 1'b0; + nxt_iorq_n = ~ iorq; + nxt_mreq_n = iorq; + end + end // else: !if(T2write == 0) + end // else: !if(mcycle[0]) end // always @ * - always @(negedge clk) - begin - if (!reset_n) - begin - rd_n <= #1 1'b1; - wr_n <= #1 1'b1; - iorq_n <= #1 1'b1; - mreq_n <= #1 1'b1; + always @(negedge clk) begin + if (!reset_n) begin + rd_n <= #1 1'b1; + wr_n <= #1 1'b1; + iorq_n <= #1 1'b1; + mreq_n <= #1 1'b1; end - else - begin - rd_n <= #1 nxt_rd_n; - wr_n <= #1 nxt_wr_n; - iorq_n <= #1 nxt_iorq_n; - mreq_n <= #1 nxt_mreq_n; - end // else: !if(!reset_n) + else begin + rd_n <= #1 nxt_rd_n; + wr_n <= #1 nxt_wr_n; + iorq_n <= #1 nxt_iorq_n; + mreq_n <= #1 nxt_mreq_n; + end // else: !if(!reset_n) end // always @ (posedge clk or negedge reset_n) - always @(posedge clk) - begin - if (!reset_n) - begin - di_reg <= #1 0; + always @(posedge clk) begin + if (!reset_n) begin + di_reg <= #1 0; end - else - begin - if (tstate[2] && wait_n == 1'b1) - di_reg <= #1 di; - end // else: !if(!reset_n) + else begin + if (tstate[2] && wait_n == 1'b1) + di_reg <= #1 di; + end // else: !if(!reset_n) end // always @ (posedge clk) endmodule // t80n