// ----------------------------------------------------------------------- // // Copyright 2003-2016 H. Peter Anvin - All Rights Reserved // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, Inc., 53 Temple Place Ste 330, // Bostom MA 02111-1307, USA; either version 2 of the License, or // (at your option) any later version; incorporated herein by reference. // // ----------------------------------------------------------------------- // // abc80.v // // Top-level module for ABC80 FPGA implementation // // Designed for Altera Nios development kit, Cyclone Edition with // the Lancelot add-on board from www.fpga.nl // module abc80 ( input clock_50, // 50 MHz clock input [1:0] clock_24, // 24 MHz clock (on two pins) input [1:0] clock_27, // 27 MHz clock (on two pins) input ext_clock, // External clock input inout ps2_clk, // PS/2 keyboard clock inout ps2_dat, // PS/2 keyboard data output [9:0] ledr, // Red LEDs output [7:0] ledg, // Green LEDs output [6:0] s7_0, // 7-segment LEDs output [6:0] s7_1, // 7-segment LEDs output [6:0] s7_2, // 7-segment LEDs output [6:0] s7_3, // 7-segment LEDs input [3:0] key_n, // Pushbutton switches input [9:0] sw, // Slide switches output fl_rst_n, // Flash ROM RST# output fl_ce_n, // Flash ROM CE# output fl_oe_n, // Flash ROM OE# output fl_we_n, // Flash ROM WE# output [21:0] fl_a, // Flash ROM address bus inout [7:0] fl_dq, // Flash ROM data bus output [1:0] dram_ba, // SDRAM bank selects output dram_ras_n, // SDRAM RAS# output dram_cas_n, // SDRAM CAS# output dram_cke, // SDRAM clock enable output dram_clk, // SDRAM clock output dram_cs_n, // SDRAM CS# output dram_we_n, // SDRAM WE# output [1:0] dram_dqm, // SDRAM DQM (per byte) output [11:0] dram_a, // SDRAM address bus inout [15:0] dram_dq, // SDRAM data bus output sram_ce_n, // SRAM CE# output sram_oe_n, // SRAM OE# output sram_we_n, // SRAM WE# output [1:0] sram_be_n, // SRAM LB#, UB# output [17:0] sram_a, // SRAM address bus (* altera_attribute="-name FAST_OUTPUT_REGISTER ON; -name FAST_OUTPUT_ENABLE_REGISTER ON; -name FAST_INPUT_REGISTER ON" *) inout [15:0] sram_dq, // SRAM data bus output sd_clk, // SD card clock inout sd_cmd, // SD card DI/MOSI/CMD inout sd_dat0, // SD card SO/MISO/DAT0 inout sd_dat3, // SD card CS#/CD/DAT3 output uart_txd, // RS232 port TxD input uart_rxd, // RS232 port RxD output [3:0] vga_r, // VGA red output [3:0] vga_g, // VGA green output [3:0] vga_b, // VGA blue output vga_hs, // VGA horz sync output vga_vs, // VGA vert sync output aud_xck, // Audio master clock output aud_bclk, // Audio bitclock output aud_dacdat, // Audio DAC data output aud_daclrck, // Audio DAC framing input aud_adcdat, // Audio ADC data output aud_adclrck, // Audio ADC framing inout i2c_scl, // I2C SCK line inout i2c_sda, // I2C SDA line inout [35:0] gpio_0, // GPIO headers inout [35:0] gpio_1 // GPIO headers ); // ------------------------------------------------------------------------ // PLLs and clock distribution // ------------------------------------------------------------------------ wire cpu_clk; // 25 MHz wire video_clk; // 18.78 MHz = compatible screen pixel rate wire sram_clk; // 200 MHz wire fast_clk; // 100 MHz wire audio_clk; // 16 MHz = I2S master clock wire pll1_locked; wire pll2_locked; pll1 pll1 ( .inclk0 ( clock_50 ), // 50 MHz input clock .c0 ( sram_clk ), // x4/1 = 200 MHz .c1 ( fast_clk ), // x2/1 = 100 MHz .c2 ( cpu_clk ), // x1/2 = 25 MHz .locked ( pll1_locked ) ); pll2 pll2 ( .inclk0 ( clock_24[0] ), // 24 MHz input clock .c0 ( audio_clk ), // x2/3 = 16 MHz .c1 ( video_clk ), // x18/23 = 18.78 MHz .locked ( pll2_locked ) ); // ------------------------------------------------------------------------ // Reset - synchronization and pulse stretch // ------------------------------------------------------------------------ parameter reset_width = 6; // 2^6 = 64 cycles minimum width reg [reset_width:0] rst_ctr = 0; reg rst_n; reg power_rst_n = 1'b0; always @(posedge cpu_clk) if (~key_n[2] | ~pll1_locked | ~pll2_locked) // KEY2 = CPU reset rst_ctr <= 0; else if (~rst_ctr[reset_width]) rst_ctr <= rst_ctr + 1; always @(posedge cpu_clk) rst_n <= rst_ctr[reset_width]; always @(posedge cpu_clk) power_rst_n <= 1'b1; // ------------------------------------------------------------------------ // Standard LEDs (here so that we can switch around the LEDs more easily // for quick debugging.) // ------------------------------------------------------------------------ wire [7:0] std_led; reg [6:0] std_s7_1; reg [6:0] std_s7_0; reg [9:0] prog_ledr; reg [7:0] prog_led; reg [6:0] prog_s7[0:3]; reg [3:0] prog_led_ctl; wire [7:0] sd_errled; // Show the switch status assign ledr = prog_led_ctl[1] ? prog_ledr : sw; assign ledg = prog_led_ctl[0] ? prog_led : std_led; assign s7_3 = ~prog_s7[3]; assign s7_2 = ~prog_s7[2]; assign s7_1 = prog_led_ctl[3] ? ~prog_s7[1] : sd_errled[7] ? ~7'b1111001 : ~std_s7_1[6:0]; assign s7_0 = prog_led_ctl[2] ? ~prog_s7[0] : sd_errled[7] ? ~sd_errled[6:0] : ~std_s7_0[6:0]; // ------------------------------------------------------------------------ // Timers // ------------------------------------------------------------------------ // ABC80 has two interrupt-capable timers: one at 128 us (7812.5 Hz) and // one at 20 ms (50 Hz). The 128 us clock was slightly off, since // the real ABC80 had 11.9808 MHz and not 12 MHz for its crystal // (the 50 Hz clock was exact), but everyone treated it as 128 us // (0.16% error). We have a 50 MHz crystal; cpu_clk is already // divided by 2 to obtain 25 MHz (40 ns); we then divide it by 400 to // obtain a 16 us clock, which then is divided by 8 for 128 us and by // 625*2 for the 50 Hz clock. Note the last stage is always divide by 2, // so we get 50% duty cycle. I'm so anal-retentive. reg [8:0] clk_div0; // 16 us counter reg [2:0] clk_div1; // 128 us counter reg [9:0] clk_div2; // 10 ms counter reg clk_div3; // 20 ms counter wire ctr_128us; // 128 us counter out wire ctr_20ms; // 20 ms counter out always @(posedge cpu_clk) begin if ( clk_div0 == 0 ) clk_div0 <= 9'd399; else clk_div0 <= clk_div0-1; if ( clk_div0 == 0 ) begin clk_div1 <= clk_div1 + 1; // No special wrapping needed if ( clk_div2 == 0 ) clk_div2 <= 10'd624; else clk_div2 <= clk_div2-1; if ( clk_div2 == 0 ) clk_div3 <= ~clk_div3; end // if ( clk_div0 == 0 ) end // always @ (posedge cpu_clk) assign ctr_128us = clk_div1[2]; assign ctr_20ms = clk_div3; // ------------------------------------------------------------------------ // Common bus wires declaration // ------------------------------------------------------------------------ wire [15:0] cpu_a; // Output address from CPU (used for IORQ) wire [19:0] mmu_a; // Output address from MMU (within a device) reg [7:0] msel; // Decoded device selects for MREQ# reg [7:0] mselwr; // Decoded device selects for MREQ# + RD# reg [7:0] mselrd; // Decoded device selects for MREQ# + WR# reg [7:0] cpu_di; // Input data to CPU wire [7:0] cpu_do; // Output data from CPU wire cpu_m1_n; // M1# from CPU wire cpu_iorq_n; // IORQ# from CPU wire cpu_mreq_n; // MREQ# from CPU wire cpu_rd_n; // RD# from CPU wire cpu_wr_n; // WR# from CPU wire cpu_rfsh_n; // RFSH# from CPU wire cpu_halt_n; // HALT# from CPU wire cpu_busak_n; // BUSAK# from CPU (not used) wire cpu_int_n; // INT# to CPU wire cpu_nmi_n; // NMI# to CPU // RETI# is a non-Z80 signal indicating that a RETI has been // executed. We provide it in the CPU core because it is not feasible // for I/O devices to snoop the bus. wire cpu_reti_n; // RETI# from CPU // ABC-bus decoded strobes reg [7:0] abc_out_n; reg [7:0] abc_in_n; // ------------------------------------------------------------------------ // Keyboard controller // ------------------------------------------------------------------------ wire [7:0] kb_data; // Keyboard symbol output wire [7:0] kb_stat; // Keyboard status word // Keyboard status word: // 7..0 = Strobe CapsLock NumLock ScrollLock Super Alt Ctrl Shift keyboard keyboard ( .clkin ( cpu_clk ), .reset_n ( rst_n ), .ps2_kclk ( ps2_clk ), .ps2_kdata ( ps2_dat ), .ps2_mclk ( ), .ps2_mdata ( ), .kb_data ( kb_data ), .kb_stat ( kb_stat ) ); // ------------------------------------------------------------------------ // FG graphics controller - data counters // // These counters are here so they run in the cpu_clk clock domain // -- necessary to multiplex with the SRAM. // ------------------------------------------------------------------------ reg [5:0] fgxaddr; // Byte address horizontally reg [8:0] fgyaddr; // Byte address vertically x 2 (see below) reg sram_fgack; wire fgfull; wire [4:0] fgwrusedw; // FIFO fill status wire [1:0] v_fgdata; wire v_fgack; wire fgrst; wire c_fgrst; reg [7:0] fgctl; reg [4:0] fgpage; // Which 16K page in SRAM synchronize fgrst_sync (.d(fgrst), .q(c_fgrst), .reset (~rst_n), .clk (cpu_clk), .enable(1'b1)); always @(negedge rst_n or posedge cpu_clk) if ( ~rst_n ) begin fgxaddr <= 6'd0; fgyaddr <= 9'h00; // fgctl and fgpage are initialized elsewhere end else begin if ( c_fgrst ) begin fgxaddr <= 6'd0; fgyaddr <= 9'd0; end else if ( sram_fgack ) begin if ( fgxaddr >= 6'd60 ) begin fgxaddr <= 6'd0; fgyaddr <= fgyaddr + 1'b1; end else fgxaddr <= fgxaddr + 1'b1; end end // else: !if( ~rst_n | c_fgrst ) // fgyaddr[0] ignored due to double-scanning wire [18:0] sram_fgaddr = { fgpage, fgyaddr[8:1], fgxaddr }; assign fgfull = &fgwrusedw[4:3]; // Max 75% full, to deal with skid wire sram_fgreq = ~c_fgrst & ~fgfull; // As far too many systems have done, the bit order in the fgram // is bigendian, even though this is a littleendian system. wire [7:0] fifo_fgdata = { sram_fgdata[1:0], sram_fgdata[3:2], sram_fgdata[5:4], sram_fgdata[7:6] }; // FIFO to allow proper asynchronous operation fgfifo fgfifo ( .aclr ( fgrst ), .wrclk ( cpu_clk ), .data ( fifo_fgdata ), .wrreq ( sram_fgack ), .wrusedw ( fgwrusedw ), .wrfull ( ), .rdclk ( video_clk ), .q ( v_fgdata ), .rdreq ( v_fgack ) ); // ------------------------------------------------------------------------ // Video controller // ------------------------------------------------------------------------ wire [10:0] video_a; wire [7:0] video_d; wire [10:0] chargen_a; wire [7:0] chargen_d; // Only the low 6 bits are actually used wire [12:0] bgram_a; wire [5:0] bgram_d; wire [5:0] rgb; wire [7:0] vram_do; wire [7:0] cgen_do; wire [7:0] bgram_do; reg video_width; videoram video_ram ( .wren_a ( 0 ), .address_a ( video_a ), .q_a ( video_d ), .clock_a ( video_clk ), .data_b ( cpu_do ), .wren_b ( mselwr[2] ), .address_b ( mmu_a[11:0] ), .q_b ( vram_do ), .clock_b ( fast_clk ) ); chargen char_gen ( .wren_a ( 0 ), .address_a ( chargen_a ), .q_a ( chargen_d ), .clock_a ( video_clk ), .data_b ( cpu_do ), .wren_b ( mselwr[3] ), .address_b ( mmu_a[11:0] ), .q_b ( cgen_do ), .clock_b ( fast_clk ) ); bgram bg_ram ( .wren_a ( 0 ), .address_a ( bgram_a ), .q_a ( bgram_d ), .clock_a ( video_clk ), .data_b ( {cpu_do[6], cpu_do[4:0]} ), .wren_b ( mselwr[4] ), .address_b ( mmu_a[12:0] ), .q_b ( {bgram_do[6], bgram_do[4:0]} ), .clock_b ( fast_clk ) ); // These bits are fixed assign bgram_do[7] = 1'b0; assign bgram_do[5] = 1'b1; display video ( .clk ( video_clk ), .width ( video_width ), .reverse ( sw[7] ), .noblink ( sw[6] ), .testpattern ( sw[5] ), .reveal ( ~key_n[0] ), .a ( video_a ), .d ( video_d ), .ga ( chargen_a ), .gd ( chargen_d[5:0] ), .bga ( bgram_a ), .bgd ( bgram_d ), .rgb ( rgb ), .vsync ( vga_vs ), .hsync ( vga_hs ), .fg_ctl ( fgctl ), .fg_data ( v_fgdata ), .fg_ack ( v_fgack ), .fg_rst ( fgrst ) ); // SW[4] and SW[3] can be used to emulate a green or amber monitor // for the normal ABC80 screen, while still allowing colors to be // shown, just permuted. assign vga_r = {2{rgb[5:4] ^ ({2{sw[4]}} & rgb[3:2])}}; assign vga_g = {2{rgb[3:2]}}; assign vga_b = {2{rgb[1:0] ^ ({2{sw[3]}} & rgb[3:2])}}; // ------------------------------------------------------------------------ // External SRAM // // The SRAM is very fast (10 ns) but is a asychronous part, so we // generate the SRAM cycles from a 200 MHz sram_clk to make sure // things happen in the right order. The SRAM is only active when // actually addressed by the CPU so it can be multiplexed with // other functions. // // Timing budget for read: // 10 ns - input address // 3 ns - output register to pad // 1 ns - PCB propagation delay // 10 ns - SRAM latency // ? ns - propagation delay // ? ns - pad to input register // 10 ns - output data // // Events per 25 MHz CPU cycle, numbers correspond to sram_clk_phase: // // CPU or fgfifo read: // 2. Latch npled data, output MMU/fgfifo address, // CE# and OE# asserted // 3. Nop // 4. Nop // 5. Nop // 6. Latch CPU/fgfifo data, output npled driver address, // CE# and OE# asserted // 7. Nop // 0. Nop // 1. Nop // // CPU write: // 2. Latch npled data, output MMU address and CPU data, // CE# and WE# asserted // 3. Nop // 4. Nop // 5. Deassert WE# // 6. Output npled driver address, // CE# and OE# asserted // 7. Nop // 0. Nop // 1. Nop // // No CPU/fgfifo cycle: // 2. Latch npled data, CE#, WE# and OE# deasserted // 3. Nop // 4. Nop // 5. Nop // 6. Output npled driver address, CE# and OE# asserted // 7. Nop // 0. Nop // 1. Nop // // ------------------------------------------------------------------------ // This logic provides a state machine for where sram_clk is with respect to // cpu_clk. sram_clk = 0 corresponds to the rising edge of cpu_clk. reg [2:0] sram_clk_phase = 3'd0; reg [2:0] sram_clk_next_phase = 3'd1; reg last_cpu_clk = 1'b0; // Sample cpu_clk on the *negative* edge of sram_clk, to avoid the obvious // race condition of the two clocks transitioning at the same time. always @(negedge sram_clk) begin last_cpu_clk <= cpu_clk; if (cpu_clk & ~last_cpu_clk) // 1 cycle observation latency, 1 cycle latch latency sram_clk_next_phase <= 3'd2; else sram_clk_next_phase <= sram_clk_next_phase + 1'b1; end always @(posedge sram_clk) sram_clk_phase <= sram_clk_next_phase; reg [7:0] sram_do_q; // Output data to CPU reg [7:0] sram_fgdata_q; // Output data to fg unit reg sram_fg_q; // Data is for the fg unit reg sram_cpu_q; // Data is for the CPU reg sram_ce_q; reg sram_oe_q; reg sram_we_q; reg sram_fgrd; reg [18:0] sram_addr_q; reg [1:0] sram_be_q; reg [15:0] sram_d_q; // Output data (from write) reg [15:0] sram_d_en; reg [15:0] sram_q; // Latched input data (in I/O pad) reg sram_mux_ctl; // addr[0] with a delay // SRAM input mux wire [7:0] sram_mux_out = sram_mux_ctl ? sram_q[15:8] : sram_q[7:0]; wire [7:0] sram_do = sram_cpu_q ? sram_mux_out : sram_do_q; wire [7:0] sram_fgdata = sram_fg_q ? sram_mux_out : sram_fgdata_q; // Are we actually accessed by the CPU? Use msel_q[] here rather than // msel[] to save two sram_clk cycles. wire sram_cpu = msel_q[0] & ~cpu_mreq_n & cpu_clk_en_q; wire [18:0] npled_addr = 19'bx; // Just bullshit for now reg [7:0] npled_do; always @(negedge rst_n or posedge sram_clk) if ( ~rst_n ) begin sram_ce_q <= 1'b0; sram_oe_q <= 1'b0; sram_we_q <= 1'b0; sram_d_en <= ~16'b0; sram_fg_q <= 1'b0; sram_cpu_q <= 1'b0; sram_addr_q <= 19'bx; sram_be_q <= 2'b00; sram_d_q <= 16'bx; sram_q <= 16'bx; sram_do_q <= 8'bx; sram_fgdata_q <= 8'bx; npled_do <= 8'bx; end // if ( ~rst_n ) else begin case (sram_clk_phase) 3'd0: sram_mux_ctl <= sram_addr_q[0]; 3'd1: begin sram_q <= sram_dq; sram_d_q <= { cpu_do, cpu_do }; if (sram_cpu) begin sram_ce_q <= 1'b1; sram_we_q <= ~cpu_wr_n & ~mmu_ro; sram_oe_q <= ~cpu_rd_n; sram_d_en <= {16{cpu_rd_n}}; sram_addr_q <= mmu_a[18:0]; sram_be_q <= {mmu_a[0], ~mmu_a[0]}; sram_cpu_q <= 1'b1; sram_fg_q <= 1'b0; end else if (sram_fgrd) begin sram_ce_q <= 1'b1; sram_we_q <= 1'b0; sram_oe_q <= 1'b1; sram_d_en <= 16'b0; sram_addr_q <= sram_fgaddr; sram_be_q <= {sram_fgaddr[0], ~sram_fgaddr[0]}; sram_cpu_q <= 1'b0; sram_fg_q <= 1'b1; end else begin sram_ce_q <= 1'b0; sram_we_q <= 1'b0; sram_oe_q <= 1'b0; sram_d_en <= ~16'b0; // Don't float the bus sram_addr_q <= 19'bx; sram_be_q <= 2'b00; sram_cpu_q <= 1'b0; sram_fg_q <= 1'b0; end // else: !if(sram_fgrd) end 3'd2: begin npled_do <= sram_mux_out; sram_mux_ctl <= sram_addr_q[0]; end 3'd4: begin sram_we_q <= 1'b0; end 3'd5: begin sram_q <= sram_dq; sram_ce_q <= 1'b0; sram_we_q <= 1'b0; sram_oe_q <= 1'b0; sram_be_q <= 2'b00; sram_d_en <= ~16'b0; // Don't float the bus sram_d_q <= cpu_do; // For better I/O packing sram_addr_q <= npled_addr; end 3'd6: begin if (sram_cpu_q) sram_do_q <= sram_mux_out; if (sram_fg_q) sram_fgdata_q <= sram_mux_out; end 3'd7: begin sram_cpu_q <= 1'b0; sram_fg_q <= 1'b0; end default: begin // Do nothing end endcase // case (sram_clk_phase) end // else: !if( ~rst_n ) // Driving output pins. assign sram_a = sram_addr_q; assign sram_be_n = ~sram_be_q; assign sram_ce_n = ~sram_ce_q; assign sram_oe_n = ~sram_oe_q; assign sram_we_n = ~sram_we_q; genvar i; generate for (i = 0; i < 16; i=i+1) begin: gen_sram_dq assign sram_dq[i] = sram_d_en[i] ? sram_d_q[i] : 1'bz; end endgenerate always @(negedge rst_n or posedge cpu_clk) if ( ~rst_n ) begin sram_fgrd <= 1'b0; sram_fgack <= 1'b0; end else begin sram_fgack <= 1'b0; // Only asserted for one clock sram_fgrd <= sram_fgreq; if (sram_fg_q) begin sram_fgrd <= 1'b0; sram_fgack <= 1'b1; end end // else: !if( ~rst_n ) // ------------------------------------------------------------------------ // External flash ROM // Note: the flash ROM is a 70 ns part. With MMU delays, we have about // 25 ns in the initial cycle left at 25 MHz, so we need to delay for // an additional two cycles (wait states). In 3 and 6 MHz modes, those // will vanish; in 12 and 25 MHz mode accessing the flash is thus slower // than running out of RAM. We're okay with that. // // Also note the flash ROM is 4 MB in size. Right now we can only access // the low 1 MB due to MMU limitations. // ------------------------------------------------------------------------ reg [7:0] flsh_do; // Data out from flash wire flsh_oe_w = mselrd[1]; reg [1:0] flsh_wait_ctr = 2'b00; wire flsh_wait_n = ~(flsh_oe_w & ~flsh_wait_ctr[1]); assign fl_rst_n = rst_n; assign fl_oe_n = 1'b0; // Flash always output assign fl_we_n = 1'b1; // Treat the flash as readonly assign fl_ce_n = ~flsh_oe_w; assign fl_a = { 2'b00, mmu_a }; always @(negedge rst_n or posedge cpu_clk) if (~rst_n) flsh_wait_ctr <= 2'b00; else casex ({flsh_oe_w, flsh_wait_ctr}) 3'b0xx: flsh_wait_ctr <= 2'b00; 3'b100: flsh_wait_ctr <= 2'b01; 3'b101: flsh_wait_ctr <= 2'b10; 3'b11x: flsh_wait_ctr <= 2'b10; endcase always @(posedge fast_clk) flsh_do <= fl_dq; // ------------------------------------------------------------------------ // SDRAM controller - unused, but avoid floating values // ------------------------------------------------------------------------ assign dram_ba = 2'b00; assign dram_ras_n = 1'b1; assign dram_cas_n = 1'b1; assign dram_cke = 1'b0; assign dram_clk = 1'b1; assign dram_cs_n = 1'b1; assign dram_we_n = 1'b1; assign dram_dqm = 2'b11; assign dram_a = ~18'b0; assign dram_dq = ~16'b0; // ------------------------------------------------------------------------ // MMU and memory address decoding // ------------------------------------------------------------------------ wire [15:0] mmu_q; // The actual bits coming out of the MMU wire [2:0] mmu_devsel; // Undecoded device selects wire mmu_ro; // Protect data from writes (where applicable) reg [10:0] mmu_mod_addr; // Modify address holding register reg [7:0] mmu_mod_data; // Modify data holding register (low byte) wire mmu_wr_e; // MMU write enable wire [15:0] mmu_rd_data; // Read data output from MMU reg [1:0] mmu_map; // One of four MMU map x 40/80 char mode reg [7:0] msel_q; // Stashed memory selects reg [7:0] msel_wq; // Stashed memory selects for write only // The address is available one CPU cycle before MREQ#, RD# and WR# are asserted. // Make the best of that cycle by doing as much work as we can before those signals // are asserted. mmuram mmu ( .address_a ( { video_width, mmu_map, cpu_a[15:8] } ), .data_a ( 16'bx ), // Never written .q_a ( mmu_q ), .wren_a ( 1'b0 ), .clock ( fast_clk ), .address_b ( mmu_mod_addr ), .data_b ( { cpu_do, mmu_mod_data[7:0] } ), .q_b ( mmu_rd_data ), .wren_b ( mmu_wr_e ), ); assign mmu_ro = mmu_q[15]; assign mmu_devsel = mmu_q[14:12]; assign mmu_a[19:8] = mmu_q[11:0]; assign mmu_a[7:0] = cpu_a[7:0]; always @(posedge fast_clk) begin case ( mmu_devsel ) 3'h0: msel_q <= 8'b00000001; 3'h1: msel_q <= 8'b00000010; 3'h2: msel_q <= 8'b00000100; 3'h3: msel_q <= 8'b00001000; 3'h4: msel_q <= 8'b00010000; 3'h5: msel_q <= 8'b00100000; 3'h6: msel_q <= 8'b01000000; 3'h7: msel_q <= 8'b10000000; endcase // case( mmu_devsel ) end // always @ (posedge sram_clk) always @(posedge fast_clk) begin casez ( {mmu_ro, mmu_devsel} ) 4'h0: msel_wq <= 8'b00000001; 4'h1: msel_wq <= 8'b00000010; 4'h2: msel_wq <= 8'b00000100; 4'h3: msel_wq <= 8'b00001000; 4'h4: msel_wq <= 8'b00010000; 4'h5: msel_wq <= 8'b00100000; 4'h6: msel_wq <= 8'b01000000; 4'h7: msel_wq <= 8'b10000000; default: msel_wq <= 8'b00000000; endcase // casez ( {mmu_ro, mmu_devsel} ) end // always @ (posedge sram_clk) reg was_read; always @(negedge rst_n or posedge fast_clk) if ( ~rst_n ) begin msel <= 8'b0; mselrd <= 8'b0; mselwr <= 8'b0; was_read <= 1'b0; end else begin was_read <= ~cpu_mreq_n & ~cpu_wr_n; msel <= msel_q & {8{~cpu_mreq_n}}; mselrd <= msel_q & {8{~cpu_mreq_n & ~cpu_rd_n}}; mselwr <= msel_wq & {8{~cpu_mreq_n & ~cpu_wr_n & ~was_read}}; // Pulse for one fast_clk cycle end // ------------------------------------------------------------------------ // PIO // ------------------------------------------------------------------------ reg [7:0] pioa_ai; wire [7:0] pioa_do; wire [7:0] piob_do; wire [7:0] piob_ao; wire pio_sel; wire pioa_ieo; wire piob_ieo; wire pioa_int_n; wire piob_int_n; wire cas_relay; wire cas_output; wire cas_input; wire v24_dtr; wire v24_rts; wire v24_cts; wire v24_rxd; wire v24_txd; wire pr_txd; wire pr_cts; wire pr_rxd; wire pr_rts; always @(posedge cpu_clk) begin pioa_ai[6:0] <= kb_data[6:0]; // 7 bit ASCII pioa_ai[7] <= kb_stat[7]; // Strobe end T80PIO pioa ( .CLK_n ( cpu_clk ), .RESET_n ( rst_n ), .Di ( cpu_do ), .Do ( pioa_do ), .CE_n ( ~(pio_sel & ~cpu_a[1]) ), .CDsel ( cpu_a[0] ), .M1_n ( cpu_m1_n ), .IORQ_n ( cpu_iorq_n ), .RD_n ( cpu_rd_n ), .RETI_n ( cpu_reti_n ), .IEI ( 1 ), .IEO ( pioa_ieo ), .INT_n ( pioa_int_n ), .Ai ( pioa_ai ), .ASTB_n ( ctr_128us ), .BSTB_n ( /* == piob.astb_n */ 1 ) ); T80PIO piob ( .CLK_n ( cpu_clk ), .RESET_n ( rst_n ), .Di ( cpu_do ), .Do ( piob_do ), .CE_n ( ~(pio_sel & cpu_a[1]) ), .CDsel ( cpu_a[0] ), .M1_n ( cpu_m1_n ), .IORQ_n ( cpu_iorq_n ), .RD_n ( cpu_rd_n ), .RETI_n ( cpu_reti_n ), .IEI ( pioa_ieo ), .IEO ( piob_ieo ), .INT_n ( piob_int_n ), .Ai ( { cas_input, 4'b1111, v24_dtr, v24_rts, v24_rxd } ), .Ao ( piob_ao ), .ASTB_n ( 1 ), .BSTB_n ( /* unused */ 1 ) ); // V.24 (RS232) port outputs assign v24_txd = piob_ao[3]; assign v24_cts = piob_ao[4]; // Pin assignments for V.24 assign v24_dtr = ~sw[2]; assign v24_rts = 1'b0; assign v24_rxd = sw[2] ? uart_rxd : 1'b1; // Outbound UART port assign uart_txd = sw[2] ? v24_txd : pr_txd; // Inbound printer signals assign pr_cts = 1'b0; assign pr_rxd = sw[2] ? 1'b1 : uart_rxd; // Cassette outputs assign cas_relay = piob_ao[5]; assign cas_output = piob_ao[6]; // Map the cassette port to some of the very few unclaimed (by the // CF card) pins on Prototype Connector 1. //assign p1_a29 = cas_relay; //assign p1_a28 = cas_output; //assign cas_input = p1_a38; assign std_led[3] = cas_relay; assign std_led[4] = cas_output; // ------------------------------------------------------------------------ // ABC-bus // ------------------------------------------------------------------------ wire abc_sel; always @(*) begin if ( abc_sel & ~cpu_wr_n ) case ( cpu_a[2:0] ) 3'b000: abc_out_n = ~8'h01; 3'b001: abc_out_n = ~8'h02; 3'b010: abc_out_n = ~8'h04; 3'b011: abc_out_n = ~8'h08; 3'b100: abc_out_n = ~8'h10; 3'b101: abc_out_n = ~8'h20; 3'b110: abc_out_n = ~8'h40; 3'b111: abc_out_n = ~8'h80; endcase // case( cpu_a[2:0] ) else abc_out_n = ~8'h00; if ( abc_sel & ~cpu_rd_n ) case ( cpu_a[2:0] ) 3'b000: abc_in_n = ~8'h01; 3'b001: abc_in_n = ~8'h02; 3'b010: abc_in_n = ~8'h04; 3'b011: abc_in_n = ~8'h08; 3'b100: abc_in_n = ~8'h10; 3'b101: abc_in_n = ~8'h20; 3'b110: abc_in_n = ~8'h40; 3'b111: abc_in_n = ~8'h80; endcase // case( cpu_a[2:0] ) else abc_in_n = ~8'h00; end // always @ (*) // SD card controller wire [7:0] abc_sd_di; wire sd_select; wire sd_active; sdcontroller sdcontroller ( .reset_n ( rst_n ), .clk ( cpu_clk ), .sd_cs_n ( sd_dat3 ), .sd_di ( sd_cmd ), .sd_clk ( sd_clk ), .sd_do ( sd_dat0 ), /* Terasic didn't hook up the Card Detect and Write Enable switches in the SD socket to FPGA pins, so we have to make do with manual switches. */ .sd_cd_n ( ~sw[0] ), // SW0 on for inserted .sd_we_n ( sw[1] ), // SW1 on for Write Protect .abc_do ( cpu_do ), .abc_di ( abc_sd_di ), .abc_out_n ( abc_out_n[0] ), .abc_cs_n ( abc_out_n[1] ), .abc_c1_n ( abc_out_n[2] ), .abc_c2_n ( abc_out_n[3] ), .abc_c3_n ( abc_out_n[4] ), .abc_c4_n ( abc_out_n[5] ), .abc_inp_n ( abc_in_n[0] ), .abc_status_n ( abc_in_n[1] ), .abc_rst_n ( abc_in_n[7] ), .select ( sd_select ), .active ( sd_active ), .errled ( sd_errled ) ); // Printer controller wire [7:0] abc_pr_di; wire pr_select; printer printer ( .reset_n ( rst_n ), .clk ( cpu_clk ), .tty_txd ( pr_txd ), .tty_cts ( pr_cts ), .tty_rxd ( pr_rxd ), .tty_rts ( pr_rts ), .abc_out_n ( abc_out_n[0] ), .abc_cs_n ( abc_out_n[1] ), .abc_c1_n ( abc_out_n[2] ), .abc_c2_n ( abc_out_n[3] ), .abc_c3_n ( abc_out_n[4] ), .abc_inp_n ( abc_in_n[0] ), .abc_status_n ( abc_in_n[1] ), .abc_rst_n ( abc_in_n[7] ), .abc_do ( cpu_do ), .abc_di ( abc_pr_di ), .select ( pr_select ) ); // ENC28J60 SPI Ethernet interface (using GPIO1) wire [7:0] abc_eth_di; wire eth_rdy; wire eth_select; wire eth_wol_n; wire eth_irq_n; wire eth_rst_n = rst_n; wire eth_cs_n, eth_mosi, eth_sck, eth_miso; enc28j60 eth_enc28j60 ( .rst_n ( rst_n ), .clk ( cpu_clk ), .eth_cs_n ( eth_cs_n ), .eth_mosi ( eth_mosi ), .eth_sck ( eth_sck ), .eth_miso ( eth_miso ), .abc_do ( cpu_do ), .abc_di ( abc_eth_di ), .abc_out_n ( abc_out_n[0] ), .abc_cs_n ( abc_out_n[1] ), .abc_c1_n ( abc_out_n[2] ), .abc_c2_n ( abc_out_n[3] ), .abc_c3_n ( abc_out_n[4] ), .abc_inp_n ( abc_in_n[0] ), .abc_status_n ( abc_in_n[1] ), .abc_rst_n ( abc_in_n[7] ), .abc_rdy ( eth_rdy ), .select ( eth_select ) ); // The ENC28J60 module is attached to GPIO1 signals 26-33, corresponding // to pins 29-38 (including power). This is dictated by VCC33 and GND // on pins 29-30 corresponding to the MOD-ENC28J60 pins 1-2. assign gpio_1[25:0] = 26'bz; assign gpio_1[26] = 1'bz; // Optional connection to LEDA assign gpio_1[27] = 1'bz; assign eth_wol_n = gpio_1[27]; assign gpio_1[28] = 1'bz; assign eth_irq_n = gpio_1[28]; assign gpio_1[29] = eth_rst_n; assign gpio_1[30] = 1'bz; assign eth_miso = gpio_1[30]; assign gpio_1[31] = eth_mosi; assign gpio_1[32] = eth_sck; assign gpio_1[33] = eth_cs_n; assign gpio_1[35:34] = 2'bz; // The terminology gets a bit funny there. abc_do means data from // the ABC-bus to the main CPU. wire [7:0] abc_do = abc_sd_di & abc_pr_di & abc_eth_di; wire abc_wait_n = eth_rdy; // Closest thing we get to a disk LED assign std_led[0] = sd_active; assign std_led[1] = sd_select; assign std_led[2] = eth_select; // Video width control INP 4 = 80, INP 3 = 40. // Also allow KEY1 to flip it. wire key1_debounced; wire key1_strobe; debounce key1_debounce ( .clk ( cpu_clk ), .reset_n ( rst_n ), .in ( ~key_n[1] ), .out ( key1_debounced ), .strobe ( key1_strobe ) ); reg video_width_sw_q; always @(negedge rst_n or posedge cpu_clk) begin if ( ~rst_n ) begin video_width <= 1'b0; video_width_sw_q <= 1'b0; end else begin video_width_sw_q <= ~sw[9]; if ( ~abc_in_n[3] ) video_width <= 1'b0; else if ( ~abc_in_n[4] ) video_width <= 1'b1; else if ( ~sw[9] ^ video_width_sw_q ) video_width <= ~sw[9]; else if ( key1_strobe & key1_debounced ) video_width <= ~video_width; end end // Sound generator reg [7:0] sound; always @(negedge rst_n or posedge cpu_clk) begin if ( ~rst_n ) sound <= 8'b0; else if ( ~abc_out_n[6] ) sound <= cpu_do; end // ------------------------------------------------------------------------ // Audio generation // ------------------------------------------------------------------------ wire [7:0] sound_sc; reg [3:0] i2c_ctr; synchronize #(.width(8)) sound_sc_sync(.d(sound), .q(sound_sc), .reset(1'b0), .clk(audio_clk), .enable(1'b1)); sound_i2s sound_i2s ( .i2s_clk (audio_clk), .mixer_ctl ({sound_sc[5], sound_sc[3], sound_sc[4]}), .vco_sel (sound_sc[2]), .vco_pitch (sound_sc[1]), .envsel (sound_sc[7:6]), .inhibit (~sound_sc[0]), .i2s_dat (aud_dacdat), .i2s_lrck (aud_daclrck) ); // Drive the output clocks via DDR buffers for better jitter performance ddio_out aud_xck_buf ( .datain_l ( 1'b0 ), .datain_h ( 1'b1 ), .oe ( 1'b1 ), .outclock ( audio_clk ), .dataout ( aud_xck ) ); ddio_out aud_bclk_buf ( .datain_l ( 1'b0 ), .datain_h ( 1'b1 ), .oe ( 1'b1 ), .outclock ( audio_clk ), .dataout ( aud_bclk ) ); assign aud_adclrck = aud_daclrck; // I2C bus for initializing the audio DAC always @(posedge audio_clk) // 1.6 MHz strobe generation if (~rst_n | (i2c_ctr[3] & i2c_ctr[0])) // Divide by 10 i2c_ctr <= 4'h0; else i2c_ctr <= i2c_ctr + 1; sound_i2c sound_i2c ( .rst_n ( rst_n ), .clk ( audio_clk ), .clk_en ( i2c_ctr[3] & i2c_ctr[0] ), .i2c_scl ( i2c_scl ), .i2c_sda ( i2c_sda ) ); // ------------------------------------------------------------------------ // GPIO(0) header // // gpio_io: the actual state of the pins // gpio_dat: data for output pin // gpio_ctl: 0 for input/tristate, 1 for output // ------------------------------------------------------------------------ reg [35:0] gpio_io; reg [35:0] gpio_dat; reg [35:0] gpio_ctl; always @(posedge fast_clk) gpio_io <= gpio_0; genvar pin; generate for (pin = 0; pin < 36; pin = pin + 1) begin: gpio0_assign assign gpio_0[pin] = gpio_ctl[pin] ? gpio_dat[pin] : 1'bz; end endgenerate // ------------------------------------------------------------------------ // Internal non-ABC I/O registers (MMU, turbo, LED) // ------------------------------------------------------------------------ wire intio_sel; // Selected for access via I/O ports reg [7:0] intio_do; // Data out from MMU I/O ports reg iorq_q; reg turbo_set; reg nmi_dis; // Revision ROM reg [7:0] revrom_addr; wire [7:0] revrom_q; revrom revrom ( .address ( revrom_addr ), .clock ( fast_clk ), .q ( revrom_q ) ); assign mmu_wr_e = intio_sel & ~cpu_wr_n & (cpu_a[6:0] == 6'b000011); always @(negedge rst_n or posedge fast_clk) begin if ( !rst_n ) begin mmu_mod_addr <= 11'b0; mmu_mod_data <= 8'b0; mmu_map <= 2'b0; nmi_dis <= 1'b0; turbo_set <= 1'b0; prog_led_ctl <= 2'b0; prog_led <= 8'b0; prog_ledr <= 10'b0; prog_s7[0] <= 7'b0; prog_s7[1] <= 7'b0; prog_s7[2] <= 7'b0; prog_s7[3] <= 7'b0; intio_do <= ~8'b0; fgctl <= 8'h00; fgpage <= 5'h05; // After BASIC80 in RAM gpio_dat <= 36'b0; gpio_ctl <= 36'b0; revrom_addr <= 8'h00; iorq_q <= 1'b0; end else begin iorq_q <= ~cpu_iorq_n; if ( ~cpu_wr_n & ~cpu_iorq_n & cpu_m1_n & ~iorq_q & ((cpu_a[7:2] == 6'b100001) | (cpu_a[7] == 1'b0 & cpu_a[4:0] == 4'b0111)) ) begin mmu_map <= cpu_do[1:0]; nmi_dis <= cpu_do[2]; end if ( ~intio_sel ) begin intio_do <= ~8'h00; turbo_set <= 1'b0; end else if ( intio_sel & ~iorq_q & ~cpu_wr_n ) begin casez ( cpu_a[6:0] ) 7'b0000000: mmu_mod_addr[7:0] <= cpu_do[7:0]; 7'b0000001: mmu_mod_addr[10:8] <= cpu_do[2:0]; 7'b0000010: mmu_mod_data <= cpu_do[7:0]; // 7'b00001zz: // See above - mmu_map/nmi_dis 7'b0001000: revrom_addr <= cpu_do; 7'b00100zz: turbo_set <= 1'b1; 7'b0010100: prog_led_ctl <= cpu_do[3:0]; 7'b0010101: prog_led <= cpu_do[7:0]; 7'b0010110: prog_s7[0] <= cpu_do[6:0]; 7'b0010111: prog_s7[1] <= cpu_do[6:0]; 7'b0011000: prog_ledr[7:0] <= cpu_do[7:0]; 7'b0011001: prog_ledr[9:8] <= cpu_do[1:0]; 7'b0011010: prog_s7[2] <= cpu_do[6:0]; 7'b0011011: prog_s7[3] <= cpu_do[6:0]; 7'b0011110: fgctl <= cpu_do[7:0]; 7'b0011111: fgpage <= cpu_do[4:0]; 7'b0100101: gpio_dat[7:0] <= cpu_do; 7'b0100110: gpio_dat[15:8] <= cpu_do; 7'b0100111: gpio_dat[23:16] <= cpu_do; 7'b0101000: gpio_dat[31:24] <= cpu_do; 7'b0101001: gpio_dat[35:32] <= cpu_do[3:0]; 7'b0101010: gpio_ctl[7:0] <= cpu_do; 7'b0101011: gpio_ctl[15:8] <= cpu_do; 7'b0101100: gpio_ctl[23:16] <= cpu_do; 7'b0101101: gpio_ctl[31:24] <= cpu_do; 7'b0101110: gpio_ctl[35:32] <= cpu_do[3:0]; 7'b0101111: begin if ( cpu_do[5:0] < 36 ) begin gpio_ctl[cpu_do[5:0]] <= cpu_do[6]; gpio_dat[cpu_do[5:0]] <= cpu_do[7]; end end endcase // casez cpu_a[6:0] ) end // if ( intio_sel & ~cpu_wr_n ) else if ( intio_sel & ~iorq_q & ~cpu_rd_n ) begin casez ( cpu_a[6:0] ) 7'b0000000: intio_do <= mmu_mod_addr[7:0]; 7'b0000001: intio_do <= { 6'b0, mmu_mod_addr[9:8] }; 7'b0000010: intio_do <= mmu_rd_data[7:0]; 7'b0000011: intio_do <= mmu_rd_data[15:8]; 7'b00001zz: intio_do <= { video_width, 4'b0, nmi_dis, mmu_map }; 7'b0001000: intio_do <= revrom_addr; 7'b0001001: begin intio_do <= revrom_q; revrom_addr <= revrom_addr + 1'b1; end 7'b00100zz: intio_do <= { 6'b0, cpu_turbo }; 7'b0010100: intio_do <= { 6'b0, prog_led_ctl }; 7'b0010101: intio_do <= prog_led; 7'b0010110: intio_do <= { 1'b0, prog_s7[0] }; 7'b0010111: intio_do <= { 1'b0, prog_s7[1] }; 7'b0011000: intio_do <= prog_ledr[7:0]; 7'b0011001: intio_do <= prog_ledr[9:8]; 7'b0011010: intio_do <= { 1'b0, prog_s7[2] }; 7'b0011011: intio_do <= { 1'b0, prog_s7[3] }; 7'b0011110: intio_do <= fgctl; 7'b0011111: intio_do <= { 3'b0, fgpage }; 7'b0100000: intio_do <= gpio_io[7:0]; 7'b0100001: intio_do <= gpio_io[15:8]; 7'b0100010: intio_do <= gpio_io[23:16]; 7'b0100011: intio_do <= gpio_io[31:24]; 7'b0100100: intio_do <= { 4'b0, gpio_io[35:32] }; 7'b0100101: intio_do <= gpio_dat[7:0]; 7'b0100110: intio_do <= gpio_dat[15:8]; 7'b0100111: intio_do <= gpio_dat[23:16]; 7'b0101000: intio_do <= gpio_dat[31:24]; 7'b0101001: intio_do <= { 4'b0, gpio_dat[35:32] }; 7'b0101010: intio_do <= gpio_ctl[7:0]; 7'b0101011: intio_do <= gpio_ctl[15:8]; 7'b0101100: intio_do <= gpio_ctl[23:16]; 7'b0101101: intio_do <= gpio_ctl[31:24]; 7'b0101110: intio_do <= { 4'b0, gpio_ctl[35:32] }; default: intio_do <= 8'hFF; endcase // casez ( cpu_a[6:0] ) end // if ( intio_sel & ~cpu_rd_n ) end end // Turbo control: KEY3 = toggle turbo wire key3_debounced; wire key3_strobe; reg [1:0] cpu_turbo; debounce key3_debounce ( .clk ( cpu_clk ), .reset_n ( rst_n ), .in ( ~key_n[3] ), .out ( key3_debounced ), .strobe ( key3_strobe ) ); // This needs to operate in the cpu_clk domain, so use the // turbo_set register to communicate between decode and // this logic. Note that we don't reset cpu_turbo on // a CPU reset. always @(posedge cpu_clk) if ( ~power_rst_n ) cpu_turbo <= ~{2{sw[8]}}; // Set SW8 to go to 3 MHz mode on reset else if ( turbo_set ) cpu_turbo <= cpu_do[1:0]; else if ( key3_strobe & key3_debounced ) cpu_turbo <= cpu_turbo - 1; // ------------------------------------------------------------------------ // I/O address decoding // ------------------------------------------------------------------------ wire [7:0] io_do; // In original ABC80, A4 selected between the PIO and the bus controller // (which included the sound generator.) We use A7 for our own devices. // The PIO wants to see IORQ# and M1# directly. assign pio_sel = ~cpu_a[7] & cpu_a[4]; assign abc_sel = ~cpu_iorq_n & cpu_m1_n & ~cpu_a[7] & ~cpu_a[4]; assign intio_sel = ~cpu_iorq_n & cpu_m1_n & cpu_a[7]; // Internal ports // All I/O devices emit all ones when not selected, so we just AND together // the outputs. assign io_do = pioa_do & piob_do & intio_do & abc_do; // ------------------------------------------------------------------------ // Main CPU // ------------------------------------------------------------------------ assign cpu_int_n = pioa_int_n & piob_int_n; assign cpu_nmi_n = ctr_20ms | nmi_dis; wire cpu_wait_n = 1'b1; // See cpu_clk_en wire cpu_clk_en; reg cpu_clk_en_q; // Indicates that the CPU advanced // in the previous cycle always @(*) begin case ( mselrd ) 8'b00000001: cpu_di <= sram_do; 8'b00000010: cpu_di <= flsh_do; 8'b00000100: cpu_di <= vram_do; 8'b00001000: cpu_di <= cgen_do; 8'b00010000: cpu_di <= bgram_do; 8'b10000000: cpu_di <= mmu_a[15:8]; 8'b00000000: cpu_di <= io_do; default: cpu_di <= 8'hFF; endcase // case( msel ) end // always @ (*) // If cpu_turbo is 0, we want to execute at 3 MHz instead of 25 // ... which means enabling the clock 3 times every 25 cycles // // 0 1 // cycle 0123456789ABCDEF012345678 // 3 MHz -------X-------X-------X- // 6 MHz ---X---X---X---X---X---X- // 12 MHz -X-X-X-X-X-X-X-X-X-X-X-X- // 25 MHz XXXXXXXXXXXXXXXXXXXXXXXXX // reg [4:0] cpu_slow_ctr; always @(posedge cpu_clk) begin if ( &cpu_slow_ctr[4:3] ) // count 00h..18h cpu_slow_ctr <= 5'd0; else cpu_slow_ctr <= cpu_slow_ctr + 1; end reg [2:0] cpu_slow_mask; always @(posedge cpu_clk) begin case ( cpu_turbo ) 2'b00: cpu_slow_mask <= 3'b000; 2'b01: cpu_slow_mask <= 3'b100; 2'b10: cpu_slow_mask <= 3'b110; 2'b11: cpu_slow_mask <= 3'b111; endcase // case( cpu_turbo ) end // always @ (posedge cpu_clk) // T80 seems to not handle WAIT# quite right so do this via // the clock enable instead... assign cpu_clk_en = &(cpu_slow_ctr[2:0] | cpu_slow_mask) & flsh_wait_n & abc_wait_n; assign std_led[7:5] = cpu_slow_mask; always @(posedge cpu_clk) cpu_clk_en_q <= cpu_clk_en; always @(*) case ( cpu_turbo ) 2'b00: begin std_s7_1 <= 7'b0000000; // blank std_s7_0 <= 7'b1001111; // 3 end 2'b01: begin std_s7_1 <= 7'b0000000; // blank std_s7_0 <= 7'b1111101; // 6 end 2'b10: begin std_s7_1 <= 7'b0000110; // 1 std_s7_0 <= 7'b1011011; // 2 end 2'b11: begin std_s7_1 <= 7'b1011011; // 2 std_s7_0 <= 7'b1101101; // 5 end endcase // case( cpu_turbo ) T80se cpu ( .clk_n ( cpu_clk ), .clken ( cpu_clk_en ), .reset_n ( rst_n ), .wait_n ( cpu_wait_n ), .int_n ( cpu_int_n ), .nmi_n ( cpu_nmi_n ), .busrq_n ( 1 ), .busak_n ( cpu_busak_n ), .reti_n ( cpu_reti_n ), .m1_n ( cpu_m1_n ), .mreq_n ( cpu_mreq_n ), .iorq_n ( cpu_iorq_n ), .rd_n ( cpu_rd_n ), .wr_n ( cpu_wr_n ), .rfsh_n ( cpu_rfsh_n ), .halt_n ( cpu_halt_n ), .a ( cpu_a ), .di ( cpu_di ), .do ( cpu_do ) ); endmodule // abc80