aboutsummaryrefslogtreecommitdiffstats
path: root/abc80.v
diff options
context:
space:
mode:
Diffstat (limited to 'abc80.v')
-rw-r--r--abc80.v153
1 files changed, 84 insertions, 69 deletions
diff --git a/abc80.v b/abc80.v
index 2896498..65f2535 100644
--- a/abc80.v
+++ b/abc80.v
@@ -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),