`timescale 1ns / 100ps /* * Note about interrupt wiring: * * Level IPL 0 <- VIA * IPL 1 <- SCC * IPL 2 <- xxx * * With debug switch clamping all 3 down */ module minimigmac ( /* m68k CPU pins */ inout [15:0] cpu_data, // m68k data bus input [23:1] cpu_address, // m68k address bus output [2:0] _cpu_ipl, // m68k interrupt request input _cpu_as, // m68k address strobe input _cpu_uds, // m68k upper data strobe input _cpu_lds, // m68k lower data strobe input cpu_r_w, // m68k read / write output _cpu_dtack, // m68k data acknowledge inout _cpu_reset, // m68k reset output cpu_clk, // m68k clock /* SRAM pins */ inout [15:0] ram_data, // sram data bus output [19:1] ram_address, // sram address bus output [3:0] _ram_ce, // sram chip enable output _ram_bhe, // sram upper byte select output _ram_ble, // sram lower byte select output _ram_we, // sram write enable output _ram_oe, // sram output enable /* RS232 pins */ input rxd, // rs232 receive output txd, // rs232 send input cts, // rs232 clear to send output rts, // rs232 request to send /* Joystick ports */ input [5:0]_joy1, // joystick 1 [fire2,fire,up,down,left,right] input [5:0]_joy2, // joystick 2 [fire2,fire,up,down,left,right] /* PS2 ports */ inout msdat, // PS2 mouse data inout msclk, // PS2 mouse clk inout kbddat, // PS2 keyboard data inout kbdclk, // PS2 keyboard clk /* Video pins */ output _hsync, // horizontal sync output _vsync, // vertical sync output [3:0] red, // red output [3:0] green, // green output [3:0] blue, // blue /* Audio pins */ output left, // audio bitstream left output right, // audio bitstream right /* System pins */ input mclk, // master system clock (4.433619 Mhz) output pwrled, // power led output init_b, input _15khz, // scandoubler disable (jumper, unused) output gpio, output scsi_hshake, // handshake for scsi fifo input nmi, // macsbug ! /* SPI pins */ input _spi_cs, // SPI chip select input sdi, // SPI data input inout sdo, // SPI data output input sck // SPI clock ); /* Internal clocks */ wire sysclk16; wire sysclk33; wire pixclk; /* Backbus SPI interface */ wire [5:0] bb_addr; wire [7:0] bb_wdata; wire [7:0] bb_rdata; wire bb_strobe; wire bb_wr; /* Chip-selects & rdata for backbus clients */ wire bb_cs_scope; wire [7:0] bb_rdata_scope; wire bb_cs_ctrl; wire [7:0] bb_rdata_ctrl; wire bb_cs_cpu; wire [7:0] bb_rdata_cpu; wire bb_cs_iwm; wire [7:0] bb_rdata_iwm; wire bb_cs_scsi; wire [7:0] bb_rdata_scsi; wire bb_cs_mem; wire [7:0] bb_rdata_mem; /* Signals for the scope module */ wire [63:0] scoped_sigs; /* Main bus between CPU and devices */ wire [23:1] bus_addr; wire [15:0] bus_wdata; wire bus_ube; wire bus_lbe; wire bus_we; wire bus_phase; wire bus_cs_ram; wire bus_cs_rom; wire bus_ack_mem; wire [15:0] bus_rdata_mem; wire bus_cs_scsi; wire bus_ack_scsi; wire [7:0] bus_rdata_scsi; wire bus_cs_scc; wire bus_ack_scc; wire [7:0] bus_rdata_scc; wire bus_cs_via; wire bus_ack_via; wire [7:0] bus_rdata_via; wire bus_cs_iwm; wire bus_ack_iwm; wire [7:0] bus_rdata_iwm; /* VIA wires */ wire [2:0] via_pa_sndvol; wire via_pa_sndbuf_sel; /* 1=main, 0=alt */ wire via_pa_rom_ovl; /* 1=overlay */ wire via_pa_disksel; wire via_pa_vidbuf_sel; /* 1=main, 0=alt */ wire via_pa_scc_wreq; wire via_pb_mouse_switch; wire via_pb_mouse_x2; wire via_pb_mouse_y2; wire via_pb_snddis; /* 1=disabled */ wire [7:0] via_kbd_out; wire via_kbd_out_strobe; wire [7:0] via_kbd_in; wire via_kbd_in_strobe; /* Video wires */ wire vid_req; wire vid_ack; wire [15:0] vid_pixels; wire vid_hblank; /* SCC additional wires */ wire scc_mouse_x1; wire scc_mouse_y1; /* RTC wires */ wire rtc_onesec; wire rtc_data_in; wire rtc_data_out; wire rtc_data_clock; wire _rtc_data_enable; /* IRQs */ wire _via_irq; wire _scc_irq; reg _prg_irq; reg nmi_sync; /* Control lines */ reg led; /* Reset hack */ reg [3:0] reset_ctl = 4'b0000;/* Xilinx tool should cope */ wire reset; wire ctrl_cpu_reset; /* Led test hack */ reg [31:0] led_cnt; /* Scope test hack */ reg [7:0] scope_test; /* PS2 mouse & kbd port debug */ wire [15:0] ps2m_dbg; wire [15:0] ps2k_dbg; /* Not real synchronizers but will do */ reg _vblank_sync; reg hblank_sync; /* Instanciate clock generator */ clockgen clocks(.mclk(mclk), .sysclk16(sysclk16), .sysclk33(sysclk33), .pixclk(pixclk)); /* Low skew clock out trick from Matt */ OFDDRCPE OFDDRCPE_inst ( .Q(cpu_clk), // Data output (connect directly to // top-level port) .C0(sysclk16), // 0 degree clock input .C1(~sysclk16), // 180 degree clock input .CE(1'b1), // Clock enable input .CLR(1'b0), // Asynchronous reset input .D0(1'b1), // Posedge data input .D1(1'b0), // Negedge data input .PRE(1'b0) // Asynchronous preset input ); /* Instanciate backbus/SPI interface. Use 16Mhz clock for now */ spi_backbus spi_bb(.sysclk(sysclk16), .reset(reset), ._scs(_spi_cs), .sdi(sdi), .sdo(sdo), .sck(sck), .bb_addr(bb_addr), .bb_wdata(bb_wdata), .bb_rdata(bb_rdata), .bb_strobe(bb_strobe), .bb_wr(bb_wr)); /* Our reset currently comes reset_ctl, this will deassert it * after 4clk of config (gives time to slower components like * video to reset) */ assign reset = ~reset_ctl[0]; always@(posedge sysclk16) if (!ctrl_cpu_reset && !_cpu_reset) reset_ctl <= 0; else reset_ctl[3:0] <= { 1'b1, reset_ctl[3:1] }; assign _cpu_reset = ctrl_cpu_reset ? 1'b0 : 1'bz; /* Instanciate scope module */ scope scop0(.sysclk(sysclk16), .capclk(sysclk16), .reset(reset), .sigs(scoped_sigs), .bb_addr(bb_addr), .bb_wdata(bb_wdata), .bb_rdata(bb_rdata_scope), .bb_strobe(bb_strobe && bb_cs_scope), .bb_wr(bb_wr)); `ifdef __disabled__ assign scoped_sigs = { msclk, /* 63 */ msdat, /* 62 */ cpu_data, /* 61..46 */ cpu_address, /* 45..23 */ _cpu_ipl, /* 22..20 */ _cpu_as, /* 19 */ _cpu_uds, /* 18 */ _cpu_lds, /* 17 */ cpu_r_w, /* 16 */ _cpu_dtack, /* 15 */ _cpu_reset, /* 14 */ 6'b111111, scope_test}; `else assign scoped_sigs = 0; `endif always@(posedge reset or posedge sysclk16) begin if (reset) begin scope_test <= 0; end else begin scope_test <= scope_test + 1; end end /* Instanciate the CPU interface */ cpu_intf cpu0(.sysclk(sysclk16), .reset(reset), .cpu_data(cpu_data), .cpu_addr(cpu_address), ._cpu_as(_cpu_as), ._cpu_uds(_cpu_uds), ._cpu_lds(_cpu_lds), .cpu_r_w(cpu_r_w), ._cpu_dtack(_cpu_dtack), .bb_addr(bb_addr), .bb_wdata(bb_wdata), .bb_rdata(bb_rdata_cpu), .bb_strobe(bb_strobe && bb_cs_cpu), .bb_wr(bb_wr), .bus_addr(bus_addr), .bus_wdata(bus_wdata), .bus_ube(bus_ube), .bus_lbe(bus_lbe), .bus_we(bus_we), .bus_phase(bus_phase), .bus_cs_ram(bus_cs_ram), .bus_cs_rom(bus_cs_rom), .bus_ack_mem(bus_ack_mem), .bus_rdata_mem(bus_rdata_mem), .bus_cs_scsi(bus_cs_scsi), .bus_ack_scsi(bus_ack_scsi), .bus_rdata_scsi(bus_rdata_scsi), .bus_cs_scc(bus_cs_scc), .bus_ack_scc(bus_ack_scc), .bus_rdata_scc(bus_rdata_scc), .bus_cs_via(bus_cs_via), .bus_ack_via(bus_ack_via), .bus_rdata_via(bus_rdata_via), .bus_cs_iwm(bus_cs_iwm), .bus_ack_iwm(bus_ack_iwm), .bus_rdata_iwm(bus_rdata_iwm), .rom_ovl(via_pa_rom_ovl)); /* CPU interrupt inputs */ /* * Don't assert _via_irq if _scc_irq is asserted * a temporary spurrious is fine but the ROM will not * handle otherwise a level 3 (it just RTEs). */ assign _cpu_ipl = _prg_irq ? {1'b1, _scc_irq, _via_irq | ~_scc_irq } : 3'b000; /* Instanciate memory interface */ mem_intf mem0(.sysclk(sysclk16), .reset(reset), .ram_data(ram_data), .ram_address(ram_address), ._ram_ce(_ram_ce), ._ram_bhe(_ram_bhe), ._ram_ble(_ram_ble), ._ram_we(_ram_we), ._ram_oe(_ram_oe), .bus_cs_ram(bus_cs_ram), .bus_cs_rom(bus_cs_rom), .bus_we(bus_we), .bus_ack(bus_ack_mem), .bus_addr(bus_addr[22:1]), .bus_ube(bus_ube), .bus_lbe(bus_lbe), .bus_phase(bus_phase), .bus_wdata(bus_wdata), .bus_rdata(bus_rdata_mem), .bb_addr(bb_addr), .bb_wdata(bb_wdata), .bb_rdata(bb_rdata_mem), .bb_strobe(bb_strobe & bb_cs_mem), .bb_wr(bb_wr), .vid_bufsel(via_pa_vidbuf_sel), .vid_req(vid_req), .vid_ack(vid_ack), .vid_pixels(vid_pixels)); /* Instanciate VIA */ via6522 via0(.sysclk(sysclk16), .reset(reset), .cs(bus_cs_via & bus_phase), .we(bus_we), .rs(bus_addr[12:9]), .wdata(bus_wdata[15:8]), .rdata(bus_rdata_via), ._irq(_via_irq), .pa_in7(via_pa_scc_wreq), .pa_out({via_pa_vidbuf_sel, via_pa_disksel, via_pa_rom_ovl, via_pa_sndbuf_sel, via_pa_sndvol}), .pb_out2_0({_rtc_data_enable, rtc_data_clock, rtc_data_out}), .pb_out7(via_pb_snddis), .pb_in6_3({hblank_sync, via_pb_mouse_y2, via_pb_mouse_x2, via_pb_mouse_switch}), .pb_in0(rtc_data_in), .sr_in(via_kbd_in), .sr_in_strobe(via_kbd_in_strobe), .sr_out(via_kbd_out), .sr_out_strobe(via_kbd_out_strobe), .ca1(_vblank_sync), .ca2(rtc_onesec)); /* Simplified one-phase interface */ assign bus_ack_via = bus_cs_via; /* Instanciate the RTC */ rtc rtc0(.sysclk(sysclk16), .reset(reset), .onesec(rtc_onesec), .data_in(rtc_data_in), .data_out(rtc_data_out), .data_clock(rtc_data_clock), ._data_enable(_rtc_data_enable)); /* Instanciate scc */ scc scc0(.sysclk(sysclk16), .reset_hw(reset), .cs(bus_cs_scc & bus_phase), .we(bus_we), .rs(bus_addr[2:1]), .wdata(bus_wdata[15:8]), .rdata(bus_rdata_scc), ._irq(_scc_irq), .rxd(rxd), .txd(txd), .cts(cts), .rts(rts), .dcd_a(scc_mouse_x1), .dcd_b(scc_mouse_y1), .wreq(via_pa_scc_wreq)); /* Simplified one-phase interface */ assign bus_ack_scc = bus_cs_scc; /* Instanciate iwm */ iwm iwm0(.sysclk(sysclk16), .reset(reset), .cs(bus_cs_iwm), .we(bus_we), .ack(bus_ack_iwm), .phase(bus_phase), .rs(bus_addr[12:9]), .wdata(bus_wdata[7:0]), .rdata(bus_rdata_iwm), .bb_addr(bb_addr), .bb_wdata(bb_wdata), .bb_rdata(bb_rdata_iwm), .bb_strobe(bb_strobe && bb_cs_iwm), .bb_wr(bb_wr), .via_sel(via_pa_disksel)); /* Instanciate scsi */ ncr5380 scsi0(.sysclk(sysclk16), .reset(reset), .bus_cs(bus_cs_scsi), .bus_we(bus_we), .bus_ack(bus_ack_scsi), .bus_phase(bus_phase), .bus_rs(bus_addr[6:4]), .dack(bus_addr[9]), .wdata(bus_wdata[15:8]), .rdata(bus_rdata_scsi), .scsi_hshake(scsi_hshake), .bb_addr(bb_addr), .bb_wdata(bb_wdata), .bb_rdata(bb_rdata_scsi), .bb_strobe(bb_strobe && bb_cs_scsi), .bb_wr(bb_wr)); /* Instanciate video output module */ video video0(.pixclk(pixclk), .reset(reset), .pixels(vid_pixels), .req_pix(vid_req), .ack_pix(vid_ack), ._hsync(_hsync), ._vsync(_vsync), .red(red), .green(green), .blue(blue), .hblank(vid_hblank)); /* Instanciate the PS/2 mouse interface */ ps2_mouse mouse0(.sysclk(sysclk16), .reset(reset), .ps2dat(msdat), .ps2clk(msclk), .x1(scc_mouse_x1), .y1(scc_mouse_y1), .x2(via_pb_mouse_x2), .y2(via_pb_mouse_y2), .button(via_pb_mouse_switch), .debug(ps2m_dbg)); /* Instanciate the PS/2 keyboard interface */ ps2_kbd kbd0(.sysclk(sysclk16), .reset(reset), .ps2dat(kbddat), .ps2clk(kbdclk), .data_out(via_kbd_out), .strobe_out(via_kbd_out_strobe), .data_in(via_kbd_in), .strobe_in(via_kbd_in_strobe), .debug(ps2k_dbg)); /* Instanciate global backbus control registers */ ctrl ctrl0(.sysclk(sysclk16), .reset(reset), .bb_addr(bb_addr), .bb_wdata(bb_wdata), .bb_rdata(bb_rdata_ctrl), .bb_strobe(bb_strobe && bb_cs_ctrl), .bb_wr(bb_wr), .ps2m_dbg(ps2m_dbg), .ps2k_dbg(ps2k_dbg), .cpu_reset(ctrl_cpu_reset)); /* Generate backbus chip selects and mux the backbus read data */ assign bb_cs_ctrl = bb_addr[5:3] == 3'b000; assign bb_cs_cpu = bb_addr[5:4] == 3'b001; assign bb_cs_mem = bb_addr[5:3] == 3'b100; assign bb_cs_iwm = bb_addr[5:3] == 3'b101; assign bb_cs_scsi = bb_addr[5:3] == 3'b110; assign bb_cs_scope = bb_addr[5:3] == 3'b111; assign bb_rdata = bb_cs_ctrl ? bb_rdata_ctrl : bb_cs_cpu ? bb_rdata_cpu : bb_cs_iwm ? bb_rdata_iwm : bb_cs_scsi ? bb_rdata_scsi : bb_cs_mem ? bb_rdata_mem : bb_cs_scope ? bb_rdata_scope : 8'hff; /* Test LED */ always@(posedge sysclk16) begin if (reset) begin led <= 0; led_cnt <= 0; end else begin led_cnt <= led_cnt + 1; if (led_cnt == 1000000) begin led_cnt <= 0; led <= ~led; end end end /* Programmer switch, latch the button */ always@(posedge sysclk16) begin if (reset) begin nmi_sync <= 0; _prg_irq <= 1; end else begin nmi_sync <= nmi; _prg_irq <= ~nmi_sync; end end /* Not real synchronizers but will do */ always@(posedge sysclk16 or posedge reset) begin if (reset) begin _vblank_sync <= 1; hblank_sync <= 0; end else begin _vblank_sync <= _vsync; hblank_sync <= vid_hblank; end end /* LED output powered by a weak pullup */ assign pwrled = led ? 1'b1 : 1'bz; /* Unused output signals */ assign kbddat = 1'bz; assign kbdclk = 1'bz; assign left = 0; assign right = 0; assign init_b = 0; assign gpio = 1'bz; endmodule // mimigmac