module DE1_TOP ( //////////////////// Clock Input //////////////////// CLOCK_24, // 24 MHz CLOCK_27, // 27 MHz CLOCK_50, // 50 MHz EXT_CLOCK, // External Clock //////////////////// Push Button //////////////////// KEY, // Pushbutton[3:0] //////////////////// DPDT Switch //////////////////// SW, // Toggle Switch[9:0] //////////////////// 7-SEG Dispaly //////////////////// HEX0, // Seven Segment Digit 0 HEX1, // Seven Segment Digit 1 HEX2, // Seven Segment Digit 2 HEX3, // Seven Segment Digit 3 //////////////////////// LED //////////////////////// LEDG, // LED Green[7:0] LEDR, // LED Red[9:0] //////////////////////// UART //////////////////////// UART_TXD, // UART Transmitter UART_RXD, // UART Receiver ///////////////////// SDRAM Interface //////////////// DRAM_DQ, // SDRAM Data bus 16 Bits DRAM_ADDR, // SDRAM Address bus 12 Bits DRAM_LDQM, // SDRAM Low-byte Data Mask DRAM_UDQM, // SDRAM High-byte Data Mask DRAM_WE_N, // SDRAM Write Enable DRAM_CAS_N, // SDRAM Column Address Strobe DRAM_RAS_N, // SDRAM Row Address Strobe DRAM_CS_N, // SDRAM Chip Select DRAM_BA_0, // SDRAM Bank Address 0 DRAM_BA_1, // SDRAM Bank Address 0 DRAM_CLK, // SDRAM Clock DRAM_CKE, // SDRAM Clock Enable //////////////////// Flash Interface //////////////// FL_DQ, // FLASH Data bus 8 Bits FL_ADDR, // FLASH Address bus 22 Bits FL_WE_N, // FLASH Write Enable FL_RST_N, // FLASH Reset FL_OE_N, // FLASH Output Enable FL_CE_N, // FLASH Chip Enable //////////////////// SRAM Interface //////////////// SRAM_DQ, // SRAM Data bus 16 Bits SRAM_ADDR, // SRAM Address bus 18 Bits SRAM_UB_N, // SRAM High-byte Data Mask SRAM_LB_N, // SRAM Low-byte Data Mask SRAM_WE_N, // SRAM Write Enable SRAM_CE_N, // SRAM Chip Enable SRAM_OE_N, // SRAM Output Enable //////////////////// SD_Card Interface //////////////// SD_DAT, // SD Card Data SD_DAT3, // SD Card Data 3 SD_CMD, // SD Card Command Signal SD_CLK, // SD Card Clock //////////////////// USB JTAG link //////////////////// TDI, // CPLD -> FPGA (data in) TCK, // CPLD -> FPGA (clk) TCS, // CPLD -> FPGA (CS) TDO, // FPGA -> CPLD (data out) //////////////////// I2C //////////////////////////// I2C_SDAT, // I2C Data I2C_SCLK, // I2C Clock //////////////////// PS2 //////////////////////////// PS2_DAT, // PS2 Data PS2_CLK, // PS2 Clock //////////////////// VGA //////////////////////////// VGA_HS, // VGA H_SYNC VGA_VS, // VGA V_SYNC VGA_R, // VGA Red[3:0] VGA_G, // VGA Green[3:0] VGA_B, // VGA Blue[3:0] //////////////// Audio CODEC //////////////////////// AUD_ADCLRCK, // Audio CODEC ADC LR Clock AUD_ADCDAT, // Audio CODEC ADC Data AUD_DACLRCK, // Audio CODEC DAC LR Clock AUD_DACDAT, // Audio CODEC DAC Data AUD_BCLK, // Audio CODEC Bit-Stream Clock AUD_XCK, // Audio CODEC Chip Clock //////////////////// GPIO //////////////////////////// GPIO_0, // GPIO Connection 0 GPIO_1 // GPIO Connection 1 ); //////////////////////// Clock Input //////////////////////// input [1:0] CLOCK_24; // 24 MHz input [1:0] CLOCK_27; // 27 MHz input CLOCK_50; // 50 MHz input EXT_CLOCK; // External Clock //////////////////////// Push Button //////////////////////// input [3:0] KEY; // Pushbutton[3:0] //////////////////////// DPDT Switch //////////////////////// input [9:0] SW; // Toggle Switch[9:0] //////////////////////// 7-SEG Dispaly //////////////////////// output [6:0] HEX0; // Seven Segment Digit 0 output [6:0] HEX1; // Seven Segment Digit 1 output [6:0] HEX2; // Seven Segment Digit 2 output [6:0] HEX3; // Seven Segment Digit 3 //////////////////////////// LED //////////////////////////// output [7:0] LEDG; // LED Green[7:0] output [9:0] LEDR; // LED Red[9:0] //////////////////////////// UART //////////////////////////// output UART_TXD; // UART Transmitter input UART_RXD; // UART Receiver /////////////////////// SDRAM Interface //////////////////////// inout [15:0] DRAM_DQ; // SDRAM Data bus 16 Bits output [11:0] DRAM_ADDR; // SDRAM Address bus 12 Bits output DRAM_LDQM; // SDRAM Low-byte Data Mask output DRAM_UDQM; // SDRAM High-byte Data Mask output DRAM_WE_N; // SDRAM Write Enable output DRAM_CAS_N; // SDRAM Column Address Strobe output DRAM_RAS_N; // SDRAM Row Address Strobe output DRAM_CS_N; // SDRAM Chip Select output DRAM_BA_0; // SDRAM Bank Address 0 output DRAM_BA_1; // SDRAM Bank Address 0 output DRAM_CLK; // SDRAM Clock output DRAM_CKE; // SDRAM Clock Enable //////////////////////// Flash Interface //////////////////////// inout [7:0] FL_DQ; // FLASH Data bus 8 Bits output [21:0] FL_ADDR; // FLASH Address bus 22 Bits output FL_WE_N; // FLASH Write Enable output FL_RST_N; // FLASH Reset output FL_OE_N; // FLASH Output Enable output FL_CE_N; // FLASH Chip Enable //////////////////////// SRAM Interface //////////////////////// inout [15:0] SRAM_DQ; // SRAM Data bus 16 Bits output [17:0] SRAM_ADDR; // SRAM Address bus 18 Bits output SRAM_UB_N; // SRAM High-byte Data Mask output SRAM_LB_N; // SRAM Low-byte Data Mask output SRAM_WE_N; // SRAM Write Enable output SRAM_CE_N; // SRAM Chip Enable output SRAM_OE_N; // SRAM Output Enable //////////////////// SD Card Interface //////////////////////// inout SD_DAT; // SD Card Data inout SD_DAT3; // SD Card Data 3 inout SD_CMD; // SD Card Command Signal output SD_CLK; // SD Card Clock //////////////////////// I2C //////////////////////////////// inout I2C_SDAT; // I2C Data output I2C_SCLK; // I2C Clock //////////////////////// PS2 //////////////////////////////// input PS2_DAT; // PS2 Data input PS2_CLK; // PS2 Clock //////////////////// USB JTAG link //////////////////////////// input TDI; // CPLD -> FPGA (data in) input TCK; // CPLD -> FPGA (clk) input TCS; // CPLD -> FPGA (CS) output TDO; // FPGA -> CPLD (data out) //////////////////////// VGA //////////////////////////// output VGA_HS; // VGA H_SYNC output VGA_VS; // VGA V_SYNC output [3:0] VGA_R; // VGA Red[3:0] output [3:0] VGA_G; // VGA Green[3:0] output [3:0] VGA_B; // VGA Blue[3:0] //////////////////// Audio CODEC //////////////////////////// inout AUD_ADCLRCK; // Audio CODEC ADC LR Clock input AUD_ADCDAT; // Audio CODEC ADC Data inout AUD_DACLRCK; // Audio CODEC DAC LR Clock output AUD_DACDAT; // Audio CODEC DAC Data inout AUD_BCLK; // Audio CODEC Bit-Stream Clock output AUD_XCK; // Audio CODEC Chip Clock //////////////////////// GPIO //////////////////////////////// inout [35:0] GPIO_0; // GPIO Connection 0 inout [35:0] GPIO_1; // GPIO Connection 1 assign LEDR = {1'h0, Scan_DAV, MMC_data}; // All inout port turn to tri-state assign DRAM_DQ = 16'hzzzz; assign FL_DQ = 8'hzz; assign SRAM_DQ = 16'hzzzz; assign SD_DAT = 1'bz; assign I2C_SDAT = 1'bz; assign AUD_ADCLRCK = 1'bz; assign AUD_DACLRCK = 1'bz; assign AUD_BCLK = 1'bz; assign GPIO_0 = 36'hzzzzzzzzz; //{28'hzzzzzzz, sample_high8}; assign GPIO_1 = {8'hzz, ram_addr, // 18 bits 1'bz, // first 10 cen, cpu_oe, cpu_we_n, mmc_ram_we, MMC_is_idle, SD_DAT, SD_DAT3, SD_CMD, SD_CLK, }; // Audio assign AUD_ADCLRCK = AUD_DACLRCK; assign AUD_XCK = AUD_CTRL_CLK; assign FL_WE_N = 1; assign FL_RST_N = 1; // end of generic setup wire tape_in; assign tape_in = 1'b1; //GPIO_0[0]; assign LEDG = {1'b0, A16ram, DL}; wire mclk28; wire [7:0] mem_data; wire [7:0] io_data; wire [7:0] data_for_cpu; wire m1_n; wire [15:0] mSEG7_DIG; wire reset_in; wire mreq_n, iorq_n; wire cpu_wt; wire [12:0] video_addr; wire [3:0] high_cpu_addr; wire ROM_address_space; wire [15:0] cpu_addr; wire [7:0] cpu_di; wire [7:0] cpu_do; wire cpu_rom_access; wire cpu_ram_access; wire video_has_bus; wire io_access, cen; wire [17:0] ram_addr; wire turbo; assign turbo = 0; wire [5:0] DL; wire vga_oe, cpu_oe; wire cpu_clock_en; wire [7:0] romdata; wire [7:0] disk_buff_do; wire [7:0] low16k_data; wire top_16k = cpu_addr[15] & cpu_addr[14]; wire low_8k_access = (cpu_addr[15:13] == 3'b0); wire A15VID ; wire [4:0] scan_res; //from keyboard reg text_mode; reg mmc_load_mode; assign A15VID = DL[3]; assign ROM_address_space = ~(cpu_addr[15] | cpu_addr[14]); assign cpu_oe = mreq_n | cpu_rd | ~rfsh_n | ~cen; // all low -> low assign vga_oe = ~video_has_bus; `define HAS_CPU `define HAS_SOUND reg [3:0] clk_div = 0; reg A14ram; reg A15ram; reg A16ram; assign SRAM_UB_N = 1'b1; assign SRAM_LB_N = 1'b0; assign SRAM_OE_N = vga_oe & cpu_oe ; assign SRAM_CE_N = 0; //always on always @(*) begin if(top_16k) begin // top 1/4 0xCxxx A14ram <= DL[0]; A15ram <= DL[1]; A16ram <= DL[2]; end else begin A14ram <= cpu_addr[14]; A15ram <= cpu_addr[15]; A16ram <= cpu_addr[14]; end end //always wire SPI_active; assign SRAM_DQ[7:0] = mmc_writes_to_SRAM ? MMC_data : (((mreq_n | cpu_wt) == 0) && cen) ? cpu_do: 8'bz; //may be redundant assign SRAM_DQ[15:8] = 8'bz; assign cen = turbo ? 1 : (clk_div[2:0] == 7) & cpu_clock_en; assign CPU_reset_n = locked_sig && KEY[0]; assign reset_in = ~CPU_reset_n; pll pll_50_to_28 (.inclk0(CLOCK_50), .c0(mclk28),.locked(locked_sig)); SEG7_LUT_4 u0 ( HEX0,HEX1,HEX2,HEX3,mSEG7_DIG ); assign io_data = cpu_addr[7:0] == 8'haa ? MMC_data : cpu_addr[7:0] == 8'hab ? {7'h0, SPI_active} : cpu_addr[7:0] == 8'h00 ? {1'b0, ASCII_Code} : cs_8910 == 0 ? do_8910 : {1'b1, tape_in, 1'b1, scan_res}; reg [7:0] di_r1; assign data_for_cpu = (mreq_n == 0) ? mem_data : io_data; reg force_flash_mode; wire use_flash_for_ROM = SW[0] || force_flash_mode; // SW 0 up means use Flash for ROM (from 1 MB up) assign mem_data = (cpu_addr[15] | cpu_addr[14]) ? SRAM_DQ[7:0] : use_flash_for_ROM ? FL_DQ : low16k_data; assign FL_CE_N = ~(use_flash_for_ROM && ROM_address_space); assign FL_OE_N = cpu_oe || ~use_flash_for_ROM; assign cpu_clock_en = SW[9]; assign ram_addr = mmc_writes_to_SRAM ? {1'b0, DMA_addr_high[5], DMA_addr_high[6:0], MMC_addr} : video_has_bus ? {2'b01, A15VID, 2'b10, video_addr} : {high_cpu_addr, cpu_addr[13:0]}; assign SRAM_ADDR = ram_addr; always @(posedge mclk28) begin if(cen) begin if(mreq_n == 0) di_r1 <= mem_data; if(iorq_n == 0) di_r1 <= io_data; end end // assign di = mreq_n ? io_data : mem_data ; // assign di = mem_data ; assign cpu_di = turbo ? mem_data : di_r1 ; wire cpu_we_n; assign cpu_we_n = mreq_n | cpu_wt | ~cen ; // all low -> low assign SRAM_WE_N = mmc_writes_to_SRAM ? ~mmc_ram_we : cpu_we_n | ROM_address_space; always @(posedge mclk28) begin clk_div <= clk_div +1; end // VIDEO section wire bright; wire R,G,B; assign VGA_R = ~R ? 4'b0 : bright ? 4'b1111 : 4'b1000; assign VGA_G = ~G ? 4'b0 : bright ? 4'b1111 : 4'b1000; assign VGA_B = ~B ? 4'b0 : bright ? 4'b1111 : 4'b1000; zx2_sram zx_video ( .clk28(mclk28), .reset(reset_in), .R(R), .G(G), .B(B), .bright(bright), .HSync(VGA_HS), .VSync(VGA_VS), .ioreq(iorq_n), .memreq(mreq_n), .refr(rfsh_n), .wr_n(cpu_wt), .rd_n(cpu_rd), .M1(m1_n), .ram_addr(video_addr), .ram_data(SRAM_DQ[7:0]), .cpu_data(cpu_do), .cpu_addr(cpu_addr), .A14_rom(A14_rom), .clk_div(clk_div), .video_access(video_has_bus), .interrupt(interrupt), .turbo(turbo), .DL(DL), .speaker(speaker), .text_mode(text_mode) ); // flash contains rom data starting at 1 MB, 0x100000 assign FL_ADDR = { 7'b0100000, A14_rom, cpu_addr[13:0]}; wire wait_n; assign wait_n = 1; wire int_n, nmi_n, busrq_n; assign int_n = ~interrupt; assign nmi_n = 1; assign busrq_n = 1; `ifdef HAS_CPU tv80s cpu ( .m1_n(m1_n), .mreq_n(mreq_n), .iorq_n(iorq_n), .rd_n(cpu_rd), .wr_n(cpu_wt), .rfsh_n(rfsh_n), .halt_n(halt_n), .busak_n(busak_n), .A(cpu_addr), .do(cpu_do), .reset_n(CPU_reset_n), .clk(mclk28), .wait_n(wait_n), .int_n(int_n), .nmi_n(nmi_n), .busrq_n(busrq_n), .di(cpu_di), .cen(cen) ); wire [6:0] ASCII_Code; kbd_intf kbd_intf ( .mclk25(mclk28), .reset_in(reset_in), .PS2_Clk(PS2_CLK), .PS2_Data(PS2_DAT), // .shift(shift), .scan_addr(cpu_addr[15:8]), .scan_res(scan_res), .debug_res0(debug_res0), .ASCII_Code(ASCII_Code), .Scan_DAV(Scan_DAV) ); assign mSEG7_DIG[6:0] = ASCII_Code; assign high_cpu_addr[3] = 0; assign high_cpu_addr[2] = A16ram; assign high_cpu_addr[1] = ROM_address_space ? 0 : A15ram; assign high_cpu_addr[0] = ROM_address_space ? A14_rom : A14ram; `endif wire [7:0] MMC_data; wire [7:0] disk_buff_di; wire [8:0] MMC_addr; wire [8:0] disk_buff_addr; //assign SD_DAT3 = ~SPI_control; wire disk_buff_space; assign disk_buff_space = (cpu_addr[15:9] == 7'b0010000) && mmc_access_mode; wire mmc_access_mode; wire mmc_writes_to_SRAM; assign mmc_access_mode = SW[1]; assign mmc_writes_to_SRAM = DMA_enable && ~MMC_is_idle && mmc_access_mode; assign disk_buff_di = MMC_is_idle ? cpu_do : MMC_data; assign disk_buff_addr = MMC_is_idle ? cpu_addr : MMC_addr; assign membuff_ram_we = MMC_is_idle ? cpu_write_to_buff : mmc_ram_we; assign cpu_write_to_buff = (((mreq_n | cpu_wt) == 0) && cen && disk_buff_space ); // mapped at 0x2000 assign low16k_data = disk_buff_space ? disk_buff_do : romdata; reg [7:0] SPI_write_data; reg SPI_control; reg SPI_start; reg SPI_block; reg DMA_enable; // the block address for the MMC controller reg [7:0] block_addr_lo; // i/o at 0xf0 reg [7:0] block_addr_mid; // i/o at 0xf1 reg [7:0] block_addr_high; // i/o at 0xf2 reg [7:0] DMA_addr_lo; // i/o at 0xf3 reg [7:0] DMA_addr_high; // i/o at 0xf4 always @ (posedge mclk28) if(reset_in) begin SPI_control <= 0; SPI_start <= 0; block_addr_lo <= 0; block_addr_mid <= 0; block_addr_high <= 0; text_mode <= SW[1]; force_flash_mode <= 0; mmc_load_mode <= 1; end else begin if(~m1_n && ~mreq_n && (cpu_addr == 16'h0052) && cen ) begin // fetch instruction "ret" from RAM mmc_load_mode <= 0; end if(cen && ~mmc_load_mode) //delay by one clock so that we fetch "ret" from special RAM force_flash_mode <= 1; if(~iorq_n) begin if((cpu_addr[7:0] == 8'haa) && ~cpu_wt) SPI_write_data <= cpu_do; if((cpu_addr[7:0] == 8'hab) && ~cpu_wt) begin SPI_start <= cpu_do[0]; SPI_block <= cpu_do[1]; DMA_enable <= cpu_do[3]; text_mode <= cpu_do[7]; end if((cpu_addr[7:0] == 8'hac) && ~cpu_wt) SPI_control <= cpu_do[0]; if((cpu_addr[7:0] == 8'hf0) && ~cpu_wt) block_addr_lo <= cpu_do; if((cpu_addr[7:0] == 8'hf1) && ~cpu_wt) block_addr_mid <= cpu_do; if((cpu_addr[7:0] == 8'hf2) && ~cpu_wt) block_addr_high <= cpu_do; if((cpu_addr[7:0] == 8'hf3) && ~cpu_wt) DMA_addr_lo <= cpu_do; if((cpu_addr[7:0] == 8'hf4) && ~cpu_wt) DMA_addr_high <= cpu_do; end end `ifdef SIMPLE_SPI spi_mmc spi_mmc (.clock(mclk28),.reset(reset_in), .SDO(SD_DAT), .SDI(SD_CMD), .SCL(SD_CLK), .write_data(SPI_write_data), .start(SPI_start), .block(SPI_block), .SPI_active(SPI_active), .read_data(MMC_data), .write_strobe(mmc_write_strobe), .ram_addr(MMC_addr) ); `else spi_controller spi_controller1( .CS_N (SD_DAT3), //: out std_logic; -- MMC chip select .MOSI(SD_CMD), //: out std_logic; -- Data to card (master out slave in) .MISO(SD_DAT), //: in std_logic; -- Data from card (master in slave out) .SCLK(SD_CLK), //: out std_logic; -- Card clock .ram_write_addr(MMC_addr), //: out unsigned(13 downto 0); .ram_di(MMC_data), //: out unsigned(7 downto 0); .ram_we(mmc_ram_we), //: out std_logic; .track(5'h0), //: in unsigned(5 downto 0); -- 0 - 34 .block_to_read({block_addr_high,block_addr_mid,block_addr_lo}), .block_read_cmd(SPI_start), .CLK_14M(mclk28), //: in std_logic; -- System clock .reset(reset_in), //: in std_logic); .is_idle(MMC_is_idle) ); assign SPI_active = ~MMC_is_idle; `endif // SIMPLE_SPI buff_ram buff_ram ( .address(disk_buff_addr), .clock(mclk28), .data(disk_buff_di), .wren(membuff_ram_we), .q(disk_buff_do) ); wire protected_low_4k = (cpu_addr[12:10] == 3'b0); mmc_ram mmc_prog_ram ( .address(cpu_addr[12:0]), .clock(mclk28), .data(cpu_do), .wren(~cpu_we_n && low_8k_access && ~protected_low_4k), .q(romdata)); VGA_Audio_PLL u3 ( .inclk0(CLOCK_27[0]),.c0(VGA_CTRL_CLK),.c1(AUD_CTRL_CLK) ); `ifdef HAS_SOUND wire [7:0] sample_high8; wire [9:0] iLeft; wire [9:0] iRight; I2C_AV_Config u7 ( // Host Side .iCLK(CLOCK_50), .iRST_N(KEY[0]), // I2C Side .I2C_SCLK(I2C_SCLK), .I2C_SDAT(I2C_SDAT) ); AUDIO_DAC u8 ( // Audio Side .oAUD_BCK(AUD_BCLK), .oAUD_DATA(AUD_DACDAT), .oAUD_LRCK(AUD_DACLRCK), .iLeft(iLeft), // 10 bits each .iRight(iRight), // Control Signals .iSrc_Select(SW[8]), .iCLK_18_4(AUD_CTRL_CLK), .iRST_N(KEY[0]), .sample_high8(sample_high8) ); wire clk_en_ay8910 = (clk_div == 0); // 28/16=1.75 MHz wire asel_ay8910 = cpu_addr[14]; wire cs_8910 = ~(cen && ~iorq_n && ~cpu_addr[1] && cpu_addr[15] && m1_n); //A1=0, A14=A15=1 wire [7:0] do_8910; wire [7:0] A_8910; wire [7:0] B_8910; wire [7:0] C_8910; wire [7:0] beeper = {speaker, 7'b0}; ay8910 ay8910 ( .rst_n(~reset_in), .clk(mclk28), .clk_en(clk_en_ay8910), .asel(asel_ay8910), .wr_n(cpu_wt), .cs_n(cs_8910), .di(cpu_do), .do(do_8910), .A(A_8910), .B(B_8910), .C(C_8910) ); assign iLeft = beeper + A_8910 + {1'b0, B_8910[7:1]}; assign iRight= beeper + C_8910 + {1'b0, B_8910[7:1]}; `endif //rom16k rom48(.address(cpu_addr[13:0]), .clock(mclk28), .q(romdata)); /* rambuff1 rambuff1 ( .address(MMC_addr), // .clken(1'b1), .clock(mclk28), .data(MMC_data), .wren(mmc_write_strobe), .q()); */ endmodule