aboutsummaryrefslogtreecommitdiffstats
path: root/t80pio
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2003-10-02 21:44:49 +0000
committerH. Peter Anvin <hpa@zytor.com>2003-10-02 21:44:49 +0000
commit2506a1c2ea4215e964c123de9743ea13b2e78e15 (patch)
treeff581bfc209216df3a3f377caee2170c36d32895 /t80pio
parent997f364fb45e7ee6cea3d8b618b85322d9e97b77 (diff)
downloadabc80-2506a1c2ea4215e964c123de9743ea13b2e78e15.tar.gz
abc80-2506a1c2ea4215e964c123de9743ea13b2e78e15.tar.xz
abc80-2506a1c2ea4215e964c123de9743ea13b2e78e15.zip
More hunting for the interrupt bug
Diffstat (limited to 't80pio')
-rw-r--r--t80pio/t80pio.v106
1 files changed, 74 insertions, 32 deletions
diff --git a/t80pio/t80pio.v b/t80pio/t80pio.v
index 2b9691c..458bcd3 100644
--- a/t80pio/t80pio.v
+++ b/t80pio/t80pio.v
@@ -19,7 +19,9 @@ module T80PIO (
ASTB_n,
ARDY,
BSTB_n,
- BRDY
+ BRDY,
+
+ debug
);
input CLK_n;
input RESET_n;
@@ -41,6 +43,7 @@ module T80PIO (
output ARDY;
input BSTB_n;
output BRDY;
+ output [7:0] debug;
reg [6:0] V; // Interrupt vector
reg [1:0] M; // Operating mode (1's hot)
@@ -55,9 +58,15 @@ module T80PIO (
reg o_data_flag; // Have input data
reg ASTB_n_old; // Previous ASTB_n
reg irq_cond_old; // Previous irq_cond
+ reg IORQ_n_old; // Previous IORQ_n
+ reg M1_n_old; // Previous M1_n
reg [7:0] data_in; // Latched input data (Di)
+ // Are we currently being addressed?
+ wire addressed = M1_n & ~IORQ_n & ~CE_n;
+ reg addressed_old; // Previous addressed for edge detect
+
// Data as it would be read by the CPU
wire [7:0] read_data =
(M == 2'b00) ? D :
@@ -67,8 +76,8 @@ module T80PIO (
// Data out
assign Do =
- ( ~M1_n & ~IORQ_n & (my_irq | intak) ) ? { V, 1'b0 } :
- ( M1_n & ~IORQ_n & ~CE_n & ~RD_n & ~CDsel ) ? read_data :
+ ( ~M1_n & ~IORQ_n & (my_irq|intak) ) ? { V, 1'b0 } :
+ ( addressed & ~RD_n & ~CDsel ) ? read_data :
8'hFF; // Return FF if not selected
// Output data word (note: pins which would be tristated on Z80PIO
@@ -88,26 +97,46 @@ module T80PIO (
// This signal is high if we should latch the input data
wire latch_in =
+ ~addressed &
((M == 2'b01 && ~ASTB_n) |
(M == 2'b10 && ~BSTB_n) |
- (M == 2'b11)) &
- ~( ~IORQ_n & ~CE_n );
+ (M == 2'b11));
// Output INT#
reg need_irq; // Need to issue interrupt
+ reg need_irq_sync; // Synchronized to M1#
reg intak; // INTAK in process
reg servicing_irq; // Waiting for RETI
- wire my_irq = need_irq & IEI;
-
+ wire my_irq = need_irq_sync & IEI;
assign INT_n = ~my_irq;
- assign IEO = IEI & ~need_irq & ~intak & ~servicing_irq;
+ assign IEO = IEI & ~need_irq_sync & ~intak & ~servicing_irq;
// This computes the mode 3 interrupt condition
- wire [7:0] xor_mask = ICW[1] ? 8'hFF : 8'h00;
- wire irq_cond_and = ((read_data ^ xor_mask) & MB) == 0;
- wire irq_cond_or = (~(read_data ^ xor_mask) & MB) != 0;
- wire irq_cond = ICW[2] ? irq_cond_and : irq_cond_or;
-
+ wire [7:0] xor_mask = (ICW[2]^ICW[1]) ? 8'h00 : 8'hFF;
+ wire irq_cond = (((read_data ^ xor_mask) & ~MB) != 8'h00) ^ ICW[2];
+
+ reg [2:0] intak_debug;
+
+ always @(posedge CLK_n or negedge RESET_n)
+ begin
+ if ( !RESET_n )
+ intak_debug <= 0;
+ else
+ begin
+ if ( ~M1_n & ~IORQ_n & (my_irq|intak) )
+ intak_debug[0] <= 1;
+ if ( ~M1_n & ~IORQ_n & ~(my_irq|intak) )
+ intak_debug[1] <= 1;
+ end
+ end // always @ (posedge CLK_n or negedge RESET_n)
+
+ assign debug[0] = irq_cond;
+ assign debug[1] = servicing_irq;
+ assign debug[2] = need_irq;
+ assign debug[3] = ~INT_n;
+ assign debug[4] = read_data[7];
+ assign debug[7:5] = intak_debug;
+
always @(posedge CLK_n or negedge RESET_n)
begin
if ( !RESET_n )
@@ -115,7 +144,7 @@ module T80PIO (
M <= 2'b01;
IO <= 0;
ICW <= 0;
- MB <= 8'hFF;
+ MB <= 0;
D <= 0;
io_next <= 0;
mb_next <= 0;
@@ -124,10 +153,12 @@ module T80PIO (
servicing_irq <= 0;
ASTB_n_old <= ASTB_n;
irq_cond_old <= 0;
+ addressed_old <= 0;
end
else
begin
- if ( M1_n & ~IORQ_n & ~CE_n )
+ // Only do this once per access cycle
+ if ( addressed & ~addressed_old )
begin
case ( { RD_n, CDsel } )
2'b00: // Data Read
@@ -186,12 +217,27 @@ module T80PIO (
if ( latch_in )
data_in <= Ai;
+ // Actual interrupt-generating logic. We have two
+ // possible states to be in; both can be active:
+ // need_irq (INT# -> INTAK) and servicing_irq (INTAK -> RETI).
+ if ( ~M1_n & ~IORQ_n & (my_irq | intak) )
+ begin
+ servicing_irq <= 1;
+ intak <= 1;
+ end
+ else if ( intak )
+ begin
+ intak <= 0;
+ need_irq <= 0;
+ end
+
// Mode 3 interrupt control
if ( M == 2'b11 )
begin
if ( ICW[3] & irq_cond & ~irq_cond_old )
need_irq <= 1;
end
+
// Input strobe detect (mode != 3)
else if ( ASTB_n & ~ASTB_n_old ) // ASTB_n rising edge
begin
@@ -204,25 +250,21 @@ module T80PIO (
i_data_flag <= 1; // Data received, now full
end
- // Delayed ASTB# and irq_cond for edge detection
- ASTB_n_old <= ASTB_n;
- irq_cond_old <= irq_cond;
-
- // Actual interrupt-generating logic. We have two
- // possible states to be in; both can be active:
- // need_irq (INT# -> INTAK) and servicing_irq (INTAK -> RETI).
- if ( ~M1_n & ~IORQ_n & (my_irq | intak) )
- begin
- servicing_irq <= 1;
- intak <= 1;
- need_irq <= 0;
- end
- else
- intak <= 0;
-
+ // End of interrupt detection
if ( ~RETI_n )
servicing_irq <= 0;
-
+
+ // Synchronize interrupt to the rising edge of M1#
+ if ( M1_n & ~M1_n_old )
+ need_irq_sync <= need_irq;
+
+ // Delayed signals for edge detection
+ ASTB_n_old <= ASTB_n;
+ irq_cond_old <= irq_cond;
+ addressed_old <= addressed;
+ IORQ_n_old <= IORQ_n;
+ M1_n_old <= M1_n;
+
end // else: !if( !RESET_n )
end // always @ (posedge CLK_n or negedge RESET_n)
endmodule // T80PIO