Skip to content

Commit a31522c

Browse files
committed
5th iteration of Z80 to Caravel mapping.
1 parent bcd2685 commit a31522c

File tree

3 files changed

+172
-98
lines changed

3 files changed

+172
-98
lines changed

src/ci2406_z80.v

Lines changed: 122 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,13 @@ module ci2406_z80(
3636
// Z80) starting roughly from a bottom left corner, pin 18 (/HALT).
3737
// CI) starting from a bottom right corner, pin 31 (mprj_io[0]).
3838
// Also:
39-
// 1) need to use CI mprj_io[0..2] pins as output and preferrably for rarely used HALT, BUSAK, M1 signals
40-
// 2) Z80 data bus pin order is "scrambled"
39+
// 1) caravel mprj_io[0] is reset, mprj_io[3] can not be used, mprj_io[0..1] must be output
40+
// 2) Z80 data bus order is "scrambled"
41+
42+
// CI Caravel mprj_io mapping to multiplxer's "design" ports io_in/out/oebp[]:
43+
// assign io_out = {design_out[35:2], wb_counter[25], design_out[1:0], 1'b0};
44+
// assign io_oeb = {design_oeb[35:2], 1'b0, design_oeb[1:0], 1'b1};
45+
4146

4247
// Z80 CPU
4348
// 1st attempt:
@@ -111,79 +116,148 @@ module ci2406_z80(
111116
// <-- /MREQ |19 - io[34] 13 * 36 io[5] - 22| /WR -->
112117
// <-- /IORQ |20 - io[35] 14 * 35 io[4] - 21| /RD -->
113118
// `-------------------------------------'
119+
//
120+
// 4th revision:
121+
// c[] - caravel mprj_io[] pin
122+
// io[] - multiplexer's io_in/out/oebp[] port
123+
// ,----------------.___.----------------.
124+
// <-- A11 1 |io[17] c[19] 57 55 c[18] io[16]|40 A10 -->
125+
// <-- A12 2 |io[18] c[20] 58 54 c[17] io[15]|39 A9 -->
126+
// <-- A13 3 |io[29] c[21] 59 53 c[16] io[14]|38 A8 -->
127+
// <-- A14 4 |io[20] c[22] 60 51 c[15] io[13]|37 A7 -->
128+
// <-- A15 5 |io[21] c[23] 61 50 c[14] io[12]|36 A6 -->
129+
// --> CLK 6 |------ ocs_o 22 48 c[13] io[11]|35 A5 -->
130+
// <-> D4 7 |io[22] c[24] 62 42 c[ 8] io[ 6]|34 A4 -->
131+
// <-> D3 8 |io[23] c[25] 2 43 c[ 9] io[ 7]|33 A3 -->
132+
// <-> D5 9 |io[24] c[26] 3 44 c[10] io[ 8]|32 A2 -->
133+
// <-> D6 10|io[25] c[27] 4 46 c[12] io[10]|31 A1 -->
134+
// VCC_5V0 11| 45 c[11] io[ 9]|30 A0 -->
135+
// <-> D2 12|io[26] c[28] 5 |29 GND
136+
// <-> D7 13|io[27] c[29] 6 41 c[ 7] io[ 5]|28 /RFSH -->
137+
// <-> D0 14|io[29] c[31] 8 33 c[ 2] io[*1]|27 /M1 -->
138+
// <-> D1 15|io[28] c[30] 7 *- * 31 c[ 0] ------|26 /RESET <--
139+
// --> /INT 16|io[31] c[33] 12 * 16 c[37] io[35]|25 /BUSRQ <--
140+
// --> /NMI 17|io[30] c[32] 11 *- 37 c[ 6] io[ 4]|24 /WAIT <--
141+
// <-- /HALT 18|io[34] c[36] 15 * 32 c[ 1] io[*0]|23 /BUSAK -->
142+
// <-- /MREQ 19|io[32] c[34] 13 36 c[ 5] io[ 3]|22 /WR -->
143+
// <-- /IORQ 20|io[33] c[35] 14 35 c[ 4] io[ 2]|21 /RD -->
144+
// `-------------------------------------'
145+
// /BUSAK, /M1 --- io[cl-1]
146+
// * --- io[cl-2]
147+
148+
// output --- io[0..3, 5..21, 32..34]
149+
// input --- io[4,30,31,35] (/WAIT, /NMI, /INT, /BUSRQ)
150+
// bidir --- io[22,23,24,25,26,27,28,29]
151+
152+
// 5th revision:
153+
// c[] - caravel mprj_io[] pin
154+
// io[] - multiplexer's io_in/out/oebp[] port
155+
// ,----------------.___.----------------.
156+
// <-- A11 1 |io[17] c[19] 57 55 c[18] io[16]|40 A10 -->
157+
// <-- A12 2 |io[18] c[20] 58 54 c[17] io[15]|39 A9 -->
158+
// <-- A13 3 |io[29] c[21] 59 53 c[16] io[14]|38 A8 -->
159+
// <-- A14 4 |io[20] c[22] 60 51 c[15] io[13]|37 A7 -->
160+
// <-- A15 5 |io[21] c[23] 61 50 c[14] io[12]|36 A6 -->
161+
// --> CLK 6 |------ ocs_o 22 48 c[13] io[11]|35 A5 -->
162+
// <-> D4 7 |io[22] c[24] 62 42 c[ 8] io[ 6]|34 A4 -->
163+
// <-> D3 8 |io[23] c[25] 2 43 c[ 9] io[ 7]|33 A3 -->
164+
// <-> D5 9 |io[24] c[26] 3 44 c[10] io[ 8]|32 A2 -->
165+
// <-> D6 10|io[25] c[27] 4 46 c[12] io[10]|31 A1 -->
166+
// VCC_5V0 11| 45 c[11] io[ 9]|30 A0 -->
167+
// <-> D2 12|io[26] c[28] 5 |29 GND
168+
// <-> D7 13|io[27] c[29] 6 41 c[ 7] io[ 5]|28 /RFSH -->
169+
// <-> D0 14|io[29] c[31] 8 33 c[ 2] io[*1]|27 /M1 -->
170+
// <-> D1 15|io[28] c[30] 7 31 c[ 0] ------|26 /RESET <--
171+
// --> /INT 16|io[31] c[33] 12 16 c[37] io[35]|25 /BUSRQ <--
172+
// --> /NMI 17|io[30] c[32] 11 37 c[ 6] io[ 4]|24 /WAIT <--
173+
// <-- /HALT 18|io[32] c[34] 13 * 32 c[ 1] io[*0]|23 /BUSAK -->
174+
// <-- /MREQ 19|io[33] c[35] 14 * 36 c[ 5] io[ 3]|22 /WR -->
175+
// <-- /IORQ 20|io[34] c[36] 15 * 35 c[ 4] io[ 2]|21 /RD -->
176+
// `-------------------------------------'
177+
// /BUSAK, /M1 --- io[cl-1]
178+
// * --- io[cl-2]
179+
180+
// output --- io[0..3, 5, 32..34] (/BUSAK, /M1, /RD, /WR, /RFSH, /HALT, /MREQ, /IORQ)
181+
// output A --- io[6..21]
182+
// input --- io[4,30,31,35] (/WAIT, /NMI, /INT, /BUSRQ)
183+
// bidir --- io[22,23,24,25,26,27,28,29]
114184

115185
// GND 29 --- vss* [56,52,38,39,29,23,20,10,1]
186+
// (GND?) 29 --- vdda1, vdda2 [47,40,30,9]
116187
// VCC_5V0 11 --- vddio [64,17]
117-
// VCC_3V3 xx --- vdda1, vdda2 [47,40,30,9]
118188
// VCC_1V8 xx --- vccd, vccd1, vccd2 [63,49,18]
189+
// VCC_1V8_R xx --- io_3_csb [34]
190+
191+
119192

120193
// @TODO: float A, D on reset
121194
// @TODO: float A, D, MREQ, RD, WR, IORQ pins on BUSAK (Figure 10 BUS Request/Acknowledge Cycle)
122195

123196
// 8 output control pins
124-
assign {io_oeb[35:34], io_oeb[7], io_oeb[5:4], io_oeb[2:0]}
197+
assign {io_oeb[34:32], io_oeb[5], io_oeb[3:0]}
125198
= { 8{1'b0}}; // 0 = Output
126199

127200
// 16 output address bus pins
128-
assign io_oeb[23:8] = {16{1'b0}}; // 0 = Output
201+
assign io_oeb[21:6] = {16{1'b0}}; // 0 = Output
129202

130203
// 8 bidirectional data bus pins
131-
assign io_oeb[31:24] = {8{~data_oe}};// 0 = Output | 1 = Input
204+
assign io_oeb[29:22] = {8{~data_oe}};// 0 = Output | 1 = Input
132205

133206
// 4 input control pins
134-
assign {io_oeb[33:32], io_oeb[6], io_oeb[3]} = {4{1'b1}}; // 1 = Input
135-
assign {io_out[33:32], io_out[6], io_out[3]} = {4{1'b0}}; // Initialize otherwise undriven pins to 0
207+
assign {io_oeb[35], io_oeb[31:30], io_oeb[4]} = {4{1'b1}}; // 1 = Input
208+
assign {io_oeb[35], io_out[31:30], io_out[4]} = {4{1'b0}}; // Initialize otherwise undriven pins to 0
136209

137210
wire data_oe;
138211
z80 z80 (
139212
.clk (z80_clk),
140213
.cen (ena),
141214
.reset_n (rst_n),
142-
.wait_n (io_in [ 6]),
143-
.int_n (io_in [33]),
144-
.nmi_n (io_in [32]),
145-
.busrq_n (io_in [ 3]),
215+
.wait_n (io_in [ 4]),
216+
.int_n (io_in [31]),
217+
.nmi_n (io_in [30]),
218+
.busrq_n (io_in [35]),
146219
// Z80 has peculiar data bus pin order, keep it to minimize wire crossing on the DIP40 PCB
147220
// Also see: http://www.righto.com/2014/09/why-z-80s-data-pins-are-scrambled.html
148-
// D7 - io[29]
149-
// D6 - io[27]
150-
// D5 - io[26]
151-
// D4 - io[24]
152-
// D3 - io[25]
153-
// D2 - io[28]
154-
// D1 - io[30]
155-
// D0 - io[31]
156-
.di ({io_in [29], io_in [27], io_in [26], io_in [24], io_in [25], io_in [28], io_in [30], io_in [31]}),
157-
.dout ({io_out[29], io_out[27], io_out[26], io_out[24], io_out[25], io_out[28], io_out[30], io_out[31]}),
221+
222+
// D7 io[27]
223+
// D6 io[25]
224+
// D5 io[24]
225+
// D4 io[22]
226+
// D3 io[23]
227+
// D2 io[26]
228+
// D1 io[28]
229+
// D0 io[29]
230+
.di ({io_in [27], io_in [25], io_in [24], io_in [22], io_in [23], io_in [26], io_in [28], io_in [29]}),
231+
.dout ({io_out[27], io_out[25], io_out[24], io_out[22], io_out[23], io_out[26], io_out[28], io_out[29]}),
158232
.doe (data_oe),
159233

160-
// io[23] - A15
234+
// io[21] - A15
161235
// ...
162-
// io[13] - A5
163-
// io[8] - A4
164-
// io[9] - A3
165-
// io[10] - A2
166-
// io[12] - A1
167-
// io[11] - A0
168-
169-
.A ({io_out[23:13], io_out[8], io_out[9], io_out[10], io_out[12], io_out[11]}),
170-
171-
// 41 io[7] - 28| /RFSH -->
172-
// 33 io[2] - 27| /M1 -->
173-
// ...
174-
// <-- /HALT |18 - io[0] io[1] - 23| /BUSAK -->
175-
// <-- /MREQ |19 - io[34] io[5] - 22| /WR -->
176-
// <-- /IORQ |20 - io[35] io[4] - 21| /RD -->
177-
// `-------------------------------------'
178-
179-
.halt_n (io_out[ 0]),
180-
.busak_n (io_out[ 1]),
181-
.m1_n (io_out[ 2]),
182-
.mreq_n (io_out[34]),
183-
.iorq_n (io_out[35]),
184-
.rd_n (io_out[ 4]),
185-
.wr_n (io_out[ 5]),
186-
.rfsh_n (io_out[ 7])
236+
// io[11] - A5
237+
// io[6] - A4
238+
// io[7] - A3
239+
// io[8] - A2
240+
// io[10] - A1
241+
// io[9] - A0
242+
243+
.A ({io_out[21:11], io_out[6], io_out[7], io_out[8], io_out[10], io_out[9]}),
244+
245+
io[ 5]| /RFSH -->
246+
io[*1]| /M1 -->
247+
...
248+
<-- /HALT |io[32] io[*0]| /BUSAK -->
249+
<-- /MREQ |io[33] io[ 3]| /WR -->
250+
<-- /IORQ |io[34] io[ 2]| /RD -->
251+
`-------------------------------------'
252+
253+
.halt_n (io_out[32]),
254+
.busak_n (io_out[ 0]),
255+
.m1_n (io_out[ 1]),
256+
.mreq_n (io_out[33]),
257+
.iorq_n (io_out[34]),
258+
.rd_n (io_out[ 2]),
259+
.wr_n (io_out[ 3]),
260+
.rfsh_n (io_out[ 5])
187261
);
188262
endmodule
189263

test_chipignite/tb.v

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,52 +20,52 @@ module tb ();
2020
wire [35:0] io_oeb;
2121

2222
wire [3:0] controls_in;
23-
wire [7:0] controls_out = {io_out[35:34], io_out[7], io_out[5:4], io_out[2:0]};
24-
wire [15:0] addr = {io_out[23:13], io_out[8], io_out[9], io_out[10], io_out[12], io_out[11]};
23+
wire [7:0] controls_out = {io_out[34:32], io_out[5], io_out[3:0]};
24+
wire [15:0] addr = {io_out[21:11], io_out[6], io_out[7], io_out[8], io_out[10], io_out[9]};
2525

26-
assign {io_in[33:32], io_in[6], io_in[3]} = controls_in;
26+
assign {io_in[35], io_in[31:30], io_in[4]} = controls_in;
2727

2828
// Z80 has a peculiar order of the pins for the data bus
29-
// <-> D4 | io[24]
30-
// <-> D3 | io[25]
31-
// <-> D5 | io[26]
32-
// <-> D6 | io[27]
33-
// VCC_5V0 |
34-
// <-> D2 | io[28]
35-
// <-> D7 | io[29]
36-
// <-> D0 | io[31]
37-
// <-> D1 | io[30]
29+
// <-> D4 7 |io[22]
30+
// <-> D3 8 |io[23]
31+
// <-> D5 9 |io[24]
32+
// <-> D6 10|io[25]
33+
// VCC_5V0 11|
34+
// <-> D2 12|io[26]
35+
// <-> D7 13|io[27]
36+
// <-> D0 14|io[29]
37+
// <-> D1 15|io[28]
3838

3939
wire [7:0] data_in;
4040
wire [7:0] data_out;
4141
wire [7:0] data_oe;
4242

43-
assign io_in [24] = data_in[4];
44-
assign io_in [25] = data_in[3];
45-
assign io_in [26] = data_in[5];
46-
assign io_in [27] = data_in[6];
47-
assign io_in [28] = data_in[2];
48-
assign io_in [29] = data_in[7];
49-
assign io_in [31] = data_in[0];
50-
assign io_in [30] = data_in[1];
43+
assign io_in [22] = data_in[4];
44+
assign io_in [23] = data_in[3];
45+
assign io_in [24] = data_in[5];
46+
assign io_in [25] = data_in[6];
47+
assign io_in [26] = data_in[2];
48+
assign io_in [27] = data_in[7];
49+
assign io_in [29] = data_in[0];
50+
assign io_in [28] = data_in[1];
5151

52-
assign data_out[4] = io_out[24];
53-
assign data_out[3] = io_out[25];
54-
assign data_out[5] = io_out[26];
55-
assign data_out[6] = io_out[27];
56-
assign data_out[2] = io_out[28];
57-
assign data_out[7] = io_out[29];
58-
assign data_out[0] = io_out[31];
59-
assign data_out[1] = io_out[30];
52+
assign data_out[4] = io_out[22];
53+
assign data_out[3] = io_out[23];
54+
assign data_out[5] = io_out[24];
55+
assign data_out[6] = io_out[25];
56+
assign data_out[2] = io_out[26];
57+
assign data_out[7] = io_out[27];
58+
assign data_out[0] = io_out[29];
59+
assign data_out[1] = io_out[28];
6060

61-
assign data_oe [4] = ~io_oeb[24];
62-
assign data_oe [3] = ~io_oeb[25];
63-
assign data_oe [5] = ~io_oeb[26];
64-
assign data_oe [6] = ~io_oeb[27];
65-
assign data_oe [2] = ~io_oeb[28];
66-
assign data_oe [7] = ~io_oeb[29];
67-
assign data_oe [0] = ~io_oeb[31];
68-
assign data_oe [1] = ~io_oeb[30];
61+
assign data_oe [4] = ~io_oeb[22];
62+
assign data_oe [3] = ~io_oeb[23];
63+
assign data_oe [5] = ~io_oeb[24];
64+
assign data_oe [6] = ~io_oeb[25];
65+
assign data_oe [2] = ~io_oeb[26];
66+
assign data_oe [7] = ~io_oeb[27];
67+
assign data_oe [0] = ~io_oeb[29];
68+
assign data_oe [1] = ~io_oeb[28];
6969

7070
// Replace tt_um_example with your module name:
7171
ci2406_z80 user_project (

test_chipignite/test.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
from cocotb.clock import Clock
66
from cocotb.triggers import ClockCycles, FallingEdge, RisingEdge
77

8-
# io[3] io[6] io[32] io[33]
9-
BUS_READY = 0b1111 # not BUSRQ, not WAIT, not INT, not NMI
8+
# io[4] io[30] io[31] io[35]
9+
BUS_READY = 0b1111 # not WAIT, not NMI, not INT, not BUSRQ
1010
OPCODE_NOP = 0x00
1111
OPCODE_LDHL = 0x21
1212
OPCODE_LDNNA = 0x32
@@ -151,18 +151,18 @@ async def start_and_reset(dut):
151151
async def z80_step(z80, cycle, verbose=False):
152152
def read_controls():
153153
controls = [bit_n(z80.controls_out, n) for n in range(8)]
154-
# | io[7] - 28| /RFSH -->
155-
# | io[2] - 27| /M1 -->
156-
# | |
157-
# | |
158-
# | |
159-
# <-- /HALT |18 - io[0] io[1] - 23| /BUSAK -->
160-
# <-- /MREQ |19 - io[34] io[5] - 22| /WR -->
161-
# <-- /IORQ |20 - io[35] io[4] - 21| /RD -->
162-
# `-------------------------------------'
163-
#
164-
# io[0] io[1] io[2] io[4] io[5] io[7] io[34] io[35]
165-
return dict(zip(['halt', 'busak', 'm1', 'rd', 'wr', 'rfsh', 'mreq', 'ioreq'], controls))
154+
155+
156+
# io[ 5]| /RFSH -->
157+
# io[*1]| /M1 -->
158+
# ...
159+
# <-- /HALT |io[32] io[*0]| /BUSAK -->
160+
# <-- /MREQ |io[33] io[ 3]| /WR -->
161+
# <-- /IORQ |io[34] io[ 2]| /RD -->
162+
# `-------------------------------------'
163+
164+
# io[0] io[1] io[2] io[3] io[5] io[32] io[33] io[34]
165+
return dict(zip(['busak', 'm1', 'rd', 'wr', 'rfsh', 'halt', 'mreq', 'ioreq'], controls))
166166

167167
def read_data():
168168
if z80.data_oe.value != 0b1111_1111:

0 commit comments

Comments
 (0)