`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
// Company: Dept. Architecture and Computing Technology. University of Seville
|
// Company: Dept. Architecture and Computing Technology. University of Seville
|
// Engineer: Miguel Angel Rodriguez Jodar. rodriguj@atc.us.es
|
// Engineer: Miguel Angel Rodriguez Jodar. rodriguj@atc.us.es
|
//
|
//
|
// Create Date: 19:13:39 4-Apr-2012
|
// Create Date: 19:13:39 4-Apr-2012
|
// Design Name: ZX Spectrum
|
// Design Name: ZX Spectrum
|
// Module Name: tld_spartan3_sp48k
|
// Module Name: tld_spartan3_sp48k
|
// Project Name:
|
// Project Name:
|
// Target Devices:
|
// Target Devices:
|
// Tool versions:
|
// Tool versions:
|
// Description:
|
// Description:
|
//
|
//
|
// Dependencies:
|
// Dependencies:
|
//
|
//
|
// Revision:
|
// Revision:
|
// Revision 1.00 - File Created
|
// Revision 1.00 - File Created
|
// Additional Comments: GPL License policies apply to the contents of this file.
|
// Additional Comments: GPL License policies apply to the contents of this file.
|
//
|
//
|
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
module tld_spartan3_sp48k (
|
module tld_spartan3_sp48k (
|
input clk50,
|
input clk50,
|
input reset,
|
input reset,
|
output r,
|
output r,
|
output g,
|
output g,
|
output b,
|
output b,
|
output i,
|
output i,
|
output csync,
|
output csync,
|
// ULA I/O
|
// ULA I/O
|
input ear,
|
input ear,
|
output audio_out,
|
output audio_out,
|
// PS/2 keyboard
|
// PS/2 keyboard
|
input clkps2,
|
input clkps2,
|
input dataps2,
|
input dataps2,
|
// diagnostics
|
// diagnostics
|
output [6:0] dispcathodes,
|
output [6:0] dispcathodes,
|
output [3:0] dispanodes,
|
output [3:0] dispanodes,
|
output ledreleased,
|
output ledreleased,
|
output ledextended,
|
output ledextended,
|
output ledshift,
|
output ledshift,
|
output ledclk,
|
output ledclk,
|
output [3:0] ledaux,
|
output [3:0] ledaux,
|
// SRAM memory
|
// SRAM memory
|
output [17:0] sa,
|
output [17:0] sa,
|
inout [7:0] sd1,
|
inout [7:0] sd1,
|
output sramce1,
|
output sramce1,
|
output sramub1,
|
output sramub1,
|
output sramlb1,
|
output sramlb1,
|
output sramoe,
|
output sramoe,
|
output sramwe
|
output sramwe
|
);
|
);
|
|
|
// CPU signals
|
// CPU signals
|
wire [15:0] a;
|
wire [15:0] a;
|
wire [7:0] cpudout;
|
wire [7:0] cpudout;
|
wire [7:0] cpudin;
|
wire [7:0] cpudin;
|
wire clkcpu;
|
wire clkcpu;
|
wire mreq_n;
|
wire mreq_n;
|
wire iorq_n;
|
wire iorq_n;
|
wire wr_n;
|
wire wr_n;
|
wire rd_n;
|
wire rd_n;
|
wire rfsh_n;
|
wire rfsh_n;
|
wire int_n;
|
wire int_n;
|
|
wire m1_n;
|
|
|
// VRAM signals
|
// VRAM signals
|
wire [13:0] va;
|
wire [13:0] va;
|
wire [7:0] vramdin;
|
wire [7:0] vramdin;
|
wire [7:0] vramdout;
|
wire [7:0] vramdout;
|
wire vramoe;
|
wire vramoe;
|
wire vramcs;
|
wire vramcs;
|
wire vramwe;
|
wire vramwe;
|
|
|
// I/O
|
// I/O
|
wire mic;
|
wire mic;
|
wire spk;
|
wire spk;
|
wire [4:0] kbd_columns;
|
wire [4:0] kbd_columns;
|
|
|
// ULA data bus
|
// ULA data bus
|
wire [7:0] uladout;
|
wire [7:0] uladout;
|
wire [7:0] uladin;
|
wire [7:0] uladin;
|
|
|
// SRAM data bus
|
// SRAM data bus
|
wire [7:0] sramdout;
|
wire [7:0] sramdout;
|
wire [7:0] sramdin;
|
wire [7:0] sramdin;
|
|
|
// ROM data bus
|
// ROM data bus
|
wire [7:0] romdout;
|
wire [7:0] romdout;
|
|
|
wire sram_cs = a[15] & !mreq_n;
|
wire sram_cs = a[15] & !mreq_n;
|
wire ula_cs = !a[0] & !iorq_n;
|
wire ula_cs = !a[0] & !iorq_n & m1_n;
|
wire vram_cs = !a[15] & a[14] & !mreq_n;
|
wire vram_cs = !a[15] & a[14] & !mreq_n;
|
wire port255_cs = !iorq_n && a[7:0]==8'hFF && !rd_n;
|
wire port255_cs = !iorq_n && m1_n && a[7:0]==8'hFF && !rd_n;
|
wire ulaplusaddr_cs = !iorq_n & a[0] & !a[2] & a[7:6]==2'b00 & (a[15:14]==2'b10); // port BF3Bh
|
wire ulaplusaddr_cs = !iorq_n & m1_n & a[0] & !a[2] & a[7:6]==2'b00 & (a[15:14]==2'b10); // port BF3Bh
|
wire ulaplusdata_cs = !iorq_n & a[0] & !a[2] & a[7:6]==2'b00 & (a[15:14]==2'b11); // port FF3Bh
|
wire ulaplusdata_cs = !iorq_n & m1_n & a[0] & !a[2] & a[7:6]==2'b00 & (a[15:14]==2'b11); // port FF3Bh
|
wire rom_cs = !a[15] & !a[14] & !mreq_n & !rd_n;
|
wire rom_cs = !a[15] & !a[14] & !mreq_n & !rd_n;
|
|
|
/////////////////////////////////////
|
/////////////////////////////////////
|
// Clock generation
|
// Clock generation
|
/////////////////////////////////////
|
/////////////////////////////////////
|
wire clk56mhz;
|
wire clk56mhz;
|
master_clock clock56mhz (
|
master_clock clock56mhz (
|
.CLKIN_IN(clk50),
|
.CLKIN_IN(clk50),
|
.CLKFX_OUT(clk56mhz),
|
.CLKFX_OUT(clk56mhz),
|
.CLKIN_IBUFG_OUT(),
|
.CLKIN_IBUFG_OUT(),
|
.CLK0_OUT()
|
.CLK0_OUT()
|
);
|
);
|
reg [1:0] cnt56;
|
reg [1:0] cnt56;
|
always @(posedge clk56mhz) begin
|
always @(posedge clk56mhz) begin
|
cnt56 = cnt56 + 1;
|
cnt56 = cnt56 + 1;
|
end
|
end
|
wire clk28 = cnt56[0];
|
wire clk28 = cnt56[0];
|
wire clk14 = cnt56[1];
|
wire clk14 = cnt56[1];
|
wire clkula = clk14;
|
wire clkula = clk14;
|
wire clkdacvideo = clk56mhz;
|
wire clkdacvideo = clk56mhz;
|
wire clkmem = clk28;
|
wire clkmem = clk28;
|
wire clkdacaudio = clk14;
|
wire clkdacaudio = clk14;
|
wire clkkbd = clk14;
|
wire clkkbd = clk14;
|
|
|
/////////////////////////////////////
|
/////////////////////////////////////
|
// ROM
|
// ROM
|
/////////////////////////////////////
|
/////////////////////////////////////
|
rom the_rom (
|
rom the_rom (
|
.clka(clkmem),
|
.clka(clkmem),
|
.ena(rom_cs),
|
.ena(rom_cs),
|
.addra(a[13:0]),
|
.addra(a[13:0]),
|
.douta(romdout)
|
.douta(romdout)
|
);
|
);
|
|
|
/////////////////////////////////////
|
/////////////////////////////////////
|
// VRAM and upper RAM banks
|
// VRAM and upper RAM banks
|
/////////////////////////////////////
|
/////////////////////////////////////
|
ram_controller vram_and_upper_ram (
|
ram_controller vram_and_upper_ram (
|
.clk(clkmem),
|
.clk(clkmem),
|
// Bank 1 (VRAM)
|
// Bank 1 (VRAM)
|
.a1({2'b00,va}),
|
.a1({2'b00,va}),
|
.cs1_n(!vramcs),
|
.cs1_n(!vramcs),
|
.oe1_n(!vramoe),
|
.oe1_n(!vramoe),
|
.we1_n(!vramwe),
|
.we1_n(!vramwe),
|
.din1(vramdin),
|
.din1(vramdin),
|
.dout1(vramdout),
|
.dout1(vramdout),
|
// Bank 2 (upper RAM)
|
// Bank 2 (upper RAM)
|
.a2({1'b0,a[14:0]}),
|
.a2({1'b0,a[14:0]}),
|
.cs2_n(!sram_cs),
|
.cs2_n(!sram_cs),
|
.oe2_n(rd_n),
|
.oe2_n(rd_n),
|
.we2_n(wr_n),
|
.we2_n(wr_n),
|
.din2(sramdin),
|
.din2(sramdin),
|
.dout2(sramdout),
|
.dout2(sramdout),
|
// Outputs to actual SRAM on board
|
// Outputs to actual SRAM on board
|
.sa(sa),
|
.sa(sa),
|
.sd(sd1),
|
.sd(sd1),
|
.sramce(sramce1),
|
.sramce(sramce1),
|
.sramub(sramub1),
|
.sramub(sramub1),
|
.sramlb(sramlb1),
|
.sramlb(sramlb1),
|
.sramoe(sramoe),
|
.sramoe(sramoe),
|
.sramwe(sramwe)
|
.sramwe(sramwe)
|
);
|
);
|
|
|
/////////////////////////////////////
|
/////////////////////////////////////
|
// The ULA
|
// The ULA
|
/////////////////////////////////////
|
/////////////////////////////////////
|
wire ula_r,ula_g,ula_b,ula_i,ulaplus_enabled;
|
wire ula_r,ula_g,ula_b,ula_i,ulaplus_enabled;
|
wire [7:0] rgbulaplus;
|
wire [7:0] rgbulaplus;
|
ula the_ula (
|
ula the_ula (
|
.clk14(clkula),
|
.clk14(clkula),
|
.reset(reset),
|
.reset(reset),
|
.a(a),
|
.a(a),
|
.din(uladin),
|
.din(uladin),
|
.dout(uladout),
|
.dout(uladout),
|
.mreq_n(mreq_n),
|
.mreq_n(mreq_n),
|
.iorq_n(iorq_n),
|
.iorq_n(iorq_n),
|
.rd_n(rd_n),
|
.rd_n(rd_n),
|
.wr_n(wr_n),
|
.wr_n(wr_n),
|
.rfsh_n(rfsh_n),
|
.rfsh_n(rfsh_n),
|
.clkcpu(clkcpu),
|
.clkcpu(clkcpu),
|
.msk_int_n(int_n),
|
.msk_int_n(int_n),
|
.va(va),
|
.va(va),
|
.vramdout(vramdout),
|
.vramdout(vramdout),
|
.vramdin(vramdin),
|
.vramdin(vramdin),
|
.vramoe(vramoe),
|
.vramoe(vramoe),
|
.vramcs(vramcs),
|
.vramcs(vramcs),
|
.vramwe(vramwe),
|
.vramwe(vramwe),
|
.ear(ear),
|
.ear(ear),
|
.mic(mic),
|
.mic(mic),
|
.spk(spk),
|
.spk(spk),
|
.kbrows(),
|
.kbrows(),
|
.kbcolumns(kbd_columns),
|
.kbcolumns(kbd_columns),
|
.r(ula_r),
|
.r(ula_r),
|
.g(ula_g),
|
.g(ula_g),
|
.b(ula_b),
|
.b(ula_b),
|
.i(ula_i),
|
.i(ula_i),
|
.rgbulaplus(rgbulaplus),
|
.rgbulaplus(rgbulaplus),
|
.ulaplus_enabled(ulaplus_enabled),
|
.ulaplus_enabled(ulaplus_enabled),
|
.csync(csync)
|
.csync(csync)
|
);
|
);
|
|
|
/////////////////////////////////////
|
/////////////////////////////////////
|
// ULA/ULA+ video selector and enconding
|
// ULA/ULA+ video selector and enconding
|
/////////////////////////////////////
|
/////////////////////////////////////
|
assign i = 1;
|
assign i = 1;
|
rgbdtoa video_final_stage (
|
rgbdtoa video_final_stage (
|
.clk(clkdacvideo),
|
.clk(clkdacvideo),
|
.reset(reset),
|
.reset(reset),
|
.select(ulaplus_enabled),
|
.select(ulaplus_enabled),
|
.ri(ula_r),
|
.ri(ula_r),
|
.gi(ula_g),
|
.gi(ula_g),
|
.bi(ula_b),
|
.bi(ula_b),
|
.hi(ula_i),
|
.hi(ula_i),
|
.rgbulap(rgbulaplus),
|
.rgbulap(rgbulaplus),
|
.r(r),
|
.r(r),
|
.g(g),
|
.g(g),
|
.b(b)
|
.b(b)
|
);
|
);
|
|
|
/////////////////////////////////////
|
/////////////////////////////////////
|
// The CPU Z80A
|
// The CPU Z80A
|
/////////////////////////////////////
|
/////////////////////////////////////
|
tv80n cpu (
|
tv80n cpu (
|
// Outputs
|
// Outputs
|
.m1_n(),
|
.m1_n(m1_n),
|
.mreq_n(mreq_n),
|
.mreq_n(mreq_n),
|
.iorq_n(iorq_n),
|
.iorq_n(iorq_n),
|
.rd_n(rd_n),
|
.rd_n(rd_n),
|
.wr_n(wr_n),
|
.wr_n(wr_n),
|
.rfsh_n(rfsh_n),
|
.rfsh_n(rfsh_n),
|
.halt_n(),
|
.halt_n(),
|
.busak_n(),
|
.busak_n(),
|
.A(a),
|
.A(a),
|
.dout(cpudout),
|
.dout(cpudout),
|
// Inputs
|
// Inputs
|
.reset_n(!reset),
|
.reset_n(!reset),
|
.clk(clkcpu),
|
.clk(clkcpu),
|
.wait_n(1'b1),
|
.wait_n(1'b1),
|
.int_n(int_n),
|
.int_n(int_n),
|
.nmi_n(1'b1),
|
.nmi_n(1'b1),
|
.busrq_n(1'b1),
|
.busrq_n(1'b1),
|
.di(cpudin)
|
.di(cpudin)
|
);
|
);
|
|
|
/////////////////////////////////////
|
/////////////////////////////////////
|
// CPU data bus
|
// CPU data bus
|
/////////////////////////////////////
|
/////////////////////////////////////
|
assign sramdin = cpudout;
|
assign sramdin = cpudout;
|
assign uladin = cpudout;
|
assign uladin = cpudout;
|
assign cpudin = (rom_cs)? romdout :
|
assign cpudin = (rom_cs)? romdout :
|
(ula_cs | vram_cs | port255_cs | ulaplusaddr_cs | ulaplusdata_cs)? uladout :
|
(ula_cs | vram_cs | port255_cs | ulaplusaddr_cs | ulaplusdata_cs)? uladout :
|
(sram_cs)? sramdout :
|
(sram_cs)? sramdout :
|
8'hFF;
|
8'hFF;
|
|
|
/////////////////////////////////////
|
/////////////////////////////////////
|
// Audio mixer
|
// Audio mixer
|
/////////////////////////////////////
|
/////////////////////////////////////
|
mixer audio_mix (
|
mixer audio_mix (
|
.clkdac(clkdacaudio),
|
.clkdac(clkdacaudio),
|
.reset(reset),
|
.reset(reset),
|
.ear(ear),
|
.ear(ear),
|
.mic(mic),
|
.mic(mic),
|
.spk(spk),
|
.spk(spk),
|
.audio(audio_out)
|
.audio(audio_out)
|
);
|
);
|
|
|
/////////////////////////////////////
|
/////////////////////////////////////
|
// PS2 Keyboard
|
// PS2 Keyboard
|
/////////////////////////////////////
|
/////////////////////////////////////
|
wire [7:0] kbdscancode;
|
wire [7:0] kbdscancode;
|
|
|
ps2kbd keyboard (
|
ps2kbd keyboard (
|
.clk(clkkbd),
|
.clk(clkkbd),
|
.reset(reset),
|
.reset(reset),
|
.clkps2(clkps2),
|
.clkps2(clkps2),
|
.dataps2(dataps2),
|
.dataps2(dataps2),
|
.ledextended(ledextended),
|
.ledextended(ledextended),
|
.ledreleased(ledreleased),
|
.ledreleased(ledreleased),
|
.ledmayus(ledshift),
|
.ledmayus(ledshift),
|
.scancode(kbdscancode),
|
.scancode(kbdscancode),
|
.semifila(a[15:8]),
|
.semifila(a[15:8]),
|
.columna(kbd_columns)
|
.columna(kbd_columns)
|
);
|
);
|
|
|
/////////////////////////////////////
|
/////////////////////////////////////
|
// Diagnostics
|
// Diagnostics
|
/////////////////////////////////////
|
/////////////////////////////////////
|
display numeric_display (
|
display numeric_display (
|
.clk(clkkbd),
|
.clk(clkkbd),
|
.load(int_n),
|
.load(int_n),
|
.valor({8'h00,kbdscancode}),
|
.valor({8'h00,kbdscancode}),
|
.an(dispanodes),
|
.an(dispanodes),
|
.seg(dispcathodes)
|
.seg(dispcathodes)
|
);
|
);
|
|
|
reg [19:0] divclkcpu = 0;
|
reg [19:0] divclkcpu = 0;
|
assign ledclk = divclkcpu[19]; // a simple "hearbeat" blink to let us know that the CPU is running.
|
assign ledclk = divclkcpu[19]; // a simple "hearbeat" blink to let us know that the CPU is running.
|
always @(posedge clkcpu)
|
always @(posedge clkcpu)
|
divclkcpu <= divclkcpu + 1;
|
divclkcpu <= divclkcpu + 1;
|
assign ledaux = 4'b0000;
|
assign ledaux = 4'b0000;
|
|
|
endmodule
|
endmodule
|
|
|