diff options
Diffstat (limited to 'abc80.v')
-rw-r--r-- | abc80.v | 153 |
1 files changed, 84 insertions, 69 deletions
@@ -277,7 +277,8 @@ module abc80 ( reg [4:0] fgpage; // Which 16K page in SRAM synchronize fgrst_sync - (.d(fgrst), .q(c_fgrst), .reset (~rst_n), .clk (cpu_clk)); + (.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 ) @@ -425,37 +426,50 @@ module abc80 ( // 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: - // 0. MMU/fgfifo address is output and CE# and OE# asserted - // 1. Nop - // 2. Nop - // 3. Latch CPU/fgfifo data - // 4. Output npled driver address, CE# and OE# asserted + // 2. Latch npled data, output MMU/fgfifo address, + // CE# and OE# asserted + // 3. Nop + // 4. Nop // 5. Nop - // 6. Nop - // 7. Latch npled data + // 6. Latch CPU/fgfifo data, output npled driver address, + // CE# and OE# asserted + // 7. Nop + // 0. Nop + // 1. Nop // // CPU write: - // 0. MMU address and data are output, CE# and WE# asserted + // 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 - // 2. Nop - // 3. WE# deasserted - // 4. Output npled driver address, CE# and OE# asserted - // 5. Nop - // 6. Nop - // 7. Latch npled data // // No CPU/fgfifo cycle: - // 0. Deassert CE#, OE#, WE# - // 1. Nop - // 2. Nop + // 2. Latch npled data, CE#, WE# and OE# deasserted // 3. Nop - // 4. Output npled driver address, CE# and OE# asserted + // 4. Nop // 5. Nop - // 6. Nop - // 7. Latch npled data + // 6. Output npled driver address, CE# and OE# asserted + // 7. Nop + // 0. Nop + // 1. Nop // // ------------------------------------------------------------------------ @@ -471,7 +485,8 @@ module abc80 ( begin last_cpu_clk <= cpu_clk; if (cpu_clk & ~last_cpu_clk) - sram_clk_next_phase <= 3'd1; + // 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 @@ -486,7 +501,8 @@ module abc80 ( reg sram_oe_q; reg sram_we_q; reg sram_fgrd; - reg [18:0] sram_addr; + reg [18:0] sram_addr_q; + reg [7:0] sram_d_q; // Output data (from write) // Are we actually accessed by the CPU? wire sram_cpu = msel[0] & cpu_clk_en; @@ -497,62 +513,64 @@ module abc80 ( 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_fg_q <= 1'b0; - sram_addr <= 19'bx; - sram_do <= 8'bx; - npled_do <= 8'bx; + sram_ce_q <= 1'b0; + sram_oe_q <= 1'b0; + sram_we_q <= 1'b0; + sram_fg_q <= 1'b0; + sram_addr_q <= 19'bx; + sram_d_q <= 8'bx; + sram_do <= 8'bx; + npled_do <= 8'bx; end // if ( ~rst_n ) else begin case (sram_clk_phase) - 3'd0: + 3'd2: begin npled_do <= sram_q; - sram_do <= 8'bx; if (sram_cpu) begin - sram_ce_q <= 1'b1; - sram_we_q <= ~cpu_wr_n; - sram_oe_q <= ~cpu_rd_n; - sram_addr <= mmu_a[18:0]; - sram_fg_q <= 1'b0; + sram_ce_q <= 1'b1; + sram_we_q <= ~cpu_wr_n; + sram_oe_q <= ~cpu_rd_n; + sram_addr_q <= mmu_a[18:0]; + sram_d_q <= ~cpu_wr_n ? cpu_do : 8'bx; + 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_addr <= sram_fgaddr; - sram_fg_q <= 1'b1; + sram_ce_q <= 1'b1; + sram_we_q <= 1'b0; + sram_oe_q <= 1'b1; + sram_addr_q <= sram_fgaddr; + sram_d_q <= 8'bx; + sram_fg_q <= 1'b1; end else begin - sram_ce_q <= 1'b0; - sram_we_q <= 1'b0; - sram_oe_q <= 1'b0; - sram_addr <= 19'bx; - sram_fg_q <= 1'b0; + sram_ce_q <= 1'b0; + sram_we_q <= 1'b0; + sram_oe_q <= 1'b0; + sram_addr_q <= 19'bx; + sram_d_q <= 8'bx; + sram_fg_q <= 1'b0; end // else: !if(sram_fgrd) end - 3'd3: + 3'd5: begin sram_we_q <= 1'b0; end - 3'd4: + 3'd6: begin - sram_do <= sram_q; - npled_do <= 8'bx; + sram_do <= sram_q; - sram_ce_q <= 1'b1; - sram_we_q <= 1'b0; - sram_oe_q <= 1'b1; - sram_addr <= npled_addr; + sram_ce_q <= 1'b1; + sram_we_q <= 1'b0; + sram_oe_q <= 1'b1; + sram_addr_q <= npled_addr; end default: @@ -564,17 +582,17 @@ module abc80 ( // Driving output pins. - assign sram_a = sram_addr[18:1]; - assign sram_be_n = ~{sram_addr[0], ~sram_addr[0]}; + assign sram_a = sram_addr_q[18:1]; + assign sram_be_n = ~{sram_addr_q[0], ~sram_addr_q[0]}; assign sram_ce_n = ~sram_ce_q; assign sram_oe_n = ~sram_oe_q; assign sram_we_n = ~sram_we_q; - assign sram_dq = sram_we_q ? { cpu_do, cpu_do } : 16'bz; + assign sram_dq = sram_we_q ? { sram_d_q, sram_d_q } : 16'bz; // SRAM Input side MUX - assign sram_q = sram_addr[0] ? sram_dq[15:8] : sram_dq[7:0]; + assign sram_q = sram_addr_q[0] ? sram_dq[15:8] : sram_dq[7:0]; // fg unit FIFO handshake assign sram_fgdata = sram_do; @@ -690,11 +708,11 @@ module abc80 ( .data_a ( 16'bx ), // Never written .q_a ( mmu_q ), .wren_a ( 1'b0 ), + .clock ( sram_clk ), .address_b ( mmu_mod_addr[9:0] ), .data_b ( { cpu_do, mmu_mod_data[7:0] } ), .q_b ( mmu_rd_data ), .wren_b ( mmu_wr_e ), - .clock ( fast_clk ) ); assign mmu_patch = mmu_q[15]; @@ -702,7 +720,7 @@ module abc80 ( assign mmu_a[19:8] = mmu_q[11:0]; assign mmu_a[7:0] = cpu_a[7:0]; - always @(posedge fast_clk) + always @(posedge sram_clk) begin if ( ~cpu_mreq_n & cpu_rfsh_n ) case ( mmu_devsel ) @@ -1016,7 +1034,7 @@ module abc80 ( always @(negedge rst_n or posedge cpu_clk) begin if ( ~rst_n ) - sound <= 0; + sound <= 8'b0; else if ( ~abc_out_n[6] ) sound <= cpu_do; @@ -1026,15 +1044,12 @@ module abc80 ( // Audio generation // ------------------------------------------------------------------------ - reg [7:0] sound_sc0; - reg [7:0] sound_sc; + wire [7:0] sound_sc; reg [3:0] i2c_ctr; - always @(posedge audio_clk) - begin - sound_sc0 <= sound; // Synchronize to audio_clk - sound_sc <= sound_sc0; - end + 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), |