2 * Copyright 2020 Claude Schwarz
3 * Copyright 2020 Niklas Ekström - rewrite in Verilog
6 output reg PI_TXN_IN_PROGRESS, // GPIO0
7 output reg PI_IPL_ZERO, // GPIO1
8 input [1:0] PI_A, // GPIO[3..2]
10 output reg PI_RESET, // GPIO5
13 inout [15:0] PI_D, // GPIO[23..8]
19 output reg LTCH_A_OE_n,
20 output reg LTCH_D_RD_U,
21 output reg LTCH_D_RD_L,
22 output reg LTCH_D_RD_OE_n,
23 output reg LTCH_D_WR_U,
24 output reg LTCH_D_WR_L,
25 output reg LTCH_D_WR_OE_n,
28 output reg [2:0] M68K_FC,
31 output reg M68K_UDS_n,
32 output reg M68K_LDS_n,
40 output reg M68K_VMA_n,
42 input [2:0] M68K_IPL_n,
55 localparam REG_DATA = 2'd0;
56 localparam REG_ADDR_LO = 2'd1;
57 localparam REG_ADDR_HI = 2'd2;
58 localparam REG_STATUS = 2'd3;
61 PI_TXN_IN_PROGRESS <= 1'b0;
79 always @(posedge c200m) begin
80 rd_sync <= {rd_sync[0], PI_RD};
81 wr_sync <= {wr_sync[0], PI_WR};
84 wire rd_rising = !rd_sync[1] && rd_sync[0];
85 wire wr_rising = !wr_sync[1] && wr_sync[0];
88 assign PI_D = PI_A == REG_STATUS && PI_RD ? data_out : 16'bz;
90 always @(posedge c200m) begin
91 if (rd_rising && PI_A == REG_STATUS) begin
92 data_out <= {ipl, 13'd0};
97 wire reset_out = !status[1];
99 assign M68K_RESET_n = reset_out ? 1'b0 : 1'bz;
100 assign M68K_HALT_n = reset_out ? 1'b0 : 1'bz;
108 LTCH_D_WR_U <= PI_A == REG_DATA && PI_WR;
109 LTCH_D_WR_L <= PI_A == REG_DATA && PI_WR;
111 LTCH_A_0 <= PI_A == REG_ADDR_LO && PI_WR;
112 LTCH_A_8 <= PI_A == REG_ADDR_LO && PI_WR;
114 LTCH_A_16 <= PI_A == REG_ADDR_HI && PI_WR;
115 LTCH_A_24 <= PI_A == REG_ADDR_HI && PI_WR;
117 LTCH_D_RD_OE_n <= !(PI_A == REG_DATA && PI_RD);
123 always @(posedge c200m) begin
124 s1_sync <= {s1_sync[1:0], S1};
125 s7_sync <= {s7_sync[1:0], S7};
128 wire rising_s1 = !s1_sync[2] && s1_sync[1];
129 wire rising_s7 = !s7_sync[2] && s7_sync[1];
133 always @(posedge c200m) begin
138 PI_TXN_IN_PROGRESS <= 1'b0;
144 PI_TXN_IN_PROGRESS <= 1'b1;
149 op_uds_n <= PI_D[8] ? a0 : 1'b0;
150 op_lds_n <= PI_D[8] ? !a0 : 1'b0;
161 always @(posedge c200m) begin
162 c7m_sync <= {c7m_sync[1:0], M68K_CLK};
165 wire c7m_rising = !c7m_sync[2] && c7m_sync[1];
166 wire c7m_falling = c7m_sync[2] && !c7m_sync[1];
172 always @(posedge c200m) begin
173 if (c7m_falling) begin
174 ipl_1 <= ~M68K_IPL_n;
181 PI_IPL_ZERO <= ipl == 3'd0;
184 always @(posedge c200m) begin
185 PI_RESET <= reset_out ? 1'b1 : M68K_RESET_n;
188 reg [3:0] e_counter = 4'd0;
190 always @(negedge c7m) begin
191 if (e_counter == 4'd9)
194 e_counter <= e_counter + 4'd1;
197 always @(negedge c7m) begin
198 if (e_counter == 4'd9)
200 else if (e_counter == 4'd5)
204 reg [1:0] state = 2'd0;
206 reg wait_dtack = 1'b0;
208 wire S0 = state == 2'd0 && c7m && !wait_req;
209 wire Sr = state == 2'd0 && wait_req;
210 wire S1 = state == 2'd1 && !c7m;
211 wire S2 = state == 2'd1 && c7m;
212 wire S3 = state == 2'd2 && !c7m && !wait_dtack;
213 wire S4 = state == 2'd2 && c7m && !wait_dtack;
214 wire Sw = state == 2'd2 && wait_dtack;
215 wire S5 = state == 2'd3 && !c7m;
216 wire S6 = state == 2'd3 && c7m;
217 wire S7 = state == 2'd0 && !c7m && !wait_req;
220 LTCH_A_OE_n <= !(S1 || S2 || S3 || S4 || Sw || S5 || S6 || S7);
221 LTCH_D_WR_OE_n <= !(!op_rw && (S3 || S4 || Sw || S5 || S6 || S7));
226 M68K_AS_n <= !(S2 || S3 || S4 || Sw || S5 || S6);
227 M68K_UDS_n <= (op_rw && (S2 || S3)) || (S4 || Sw || S5 || S6) ? op_uds_n : 1'b1;
228 M68K_LDS_n <= (op_rw && (S2 || S3)) || (S4 || Sw || S5 || S6) ? op_lds_n : 1'b1;
231 always @(negedge c7m) begin
233 2'd0: begin // S0|Sr -> S1|Sr
234 if (op_req_sync) begin
236 state <= state + 2'd1;
243 2'd1: begin // S2 -> S3
244 state <= state + 2'd1;
247 2'd2: begin // S4|Sw -> S5|Sw
248 if (!M68K_DTACK_n || (!M68K_VMA_n && e_counter == 4'd8)) begin
250 state <= state + 2'd1;
253 if (!M68K_VPA_n && e_counter == 4'd2) begin
260 2'd3: begin // S6 -> S7
262 state <= state + 2'd1;
269 always @(posedge c7m) begin
270 op_req_sync <= op_req;
273 2'd0: M68K_RW <= 1'b1; // S7 -> S0
274 2'd1: M68K_RW <= op_rw; // S1 -> S2