4 * IWM module for minimigmac.
6 * Location to Location to
7 * IWM line turn line on turn line off
9 * Disk state-control lines:
10 * CA0 dBase+ph0H dBase+ph0L
11 * CA1 dBase+ph1H dBase+ph1L
12 * CA2 dBase+ph2H dBase+ph2L
13 * LSTRB dBase+ph3H dBase+ph3L
16 * ENABLE dBase+motorOn dBase+motorOff
18 * IWM internal states:
19 * SELECT dBase+extDrive dBase+intDrive
20 * Q6 dBase+q6H dBase+q6L
21 * Q7 dBase+q7H dBase+q7L
23 * ph0L .EQU 512*0 ;CA0 off (0)
24 * ph0H .EQU 512*1 ;CA0 on (1)
25 * ph1L .EQU 512*2 ;CA1 off (0)
26 * ph1H .EQU 512*3 ;CA1 on (1)
27 * ph2L .EQU 512*4 ;CA2 off (0)
28 * ph2H .EQU 512*5 ;CA2 on (1)
29 * ph3L .EQU 512*6 ;LSTRB off (low)
30 * ph3H .EQU 512*7 ;LSTRB on (high)
31 * mtrOff .EQU 512*8 ;disk enable off
32 * mtrOn .EQU 512*9 ;disk enable on
33 * intDrive .EQU 512*10 ;select internal drive
34 * extDrive .EQU 512*11 ;select external drive
35 * q6L .EQU 512*12 ;Q6 off
36 * q6H .EQU 512*13 ;Q6 on
37 * q7L .EQU 512*14 ;Q7 off
38 * q7H .EQU 512*15 ;Q7 on
41 `define IWM_REG_ph0L 0
42 `define IWM_REG_ph0H 1
43 `define IWM_REG_ph1L 2
44 `define IWM_REG_ph1H 3
45 `define IWM_REG_ph2L 4
46 `define IWM_REG_ph2H 5
47 `define IWM_REG_ph3L 6
48 `define IWM_REG_ph3H 7
49 `define IWM_REG_mtrOff 8
50 `define IWM_REG_mtrOn 9
51 `define IWM_REG_intDrive 10
52 `define IWM_REG_extDrive 11
53 `define IWM_REG_q6L 12
54 `define IWM_REG_q6H 13
55 `define IWM_REG_q7L 14
56 `define IWM_REG_q7H 15
59 module iwm(input sysclk,
62 /* Bus interface. 4-bit address, to be wired
63 * appropriately upstream (to A9..A12)
73 /* Backbus interface */
76 output reg [7:0] bb_rdata,
80 /* SEL line from VIA */
84 /* IWM state register broken up by name */
100 /* Internal data & mode registers */
104 /* Status and write handshake are just wires */
108 /* Sense line from disk */
111 /* enbl1 and enbl2 lines (not inverted here unlike real HW) */
115 /* Disk register definitions */
116 wire [3:0] diskreg_sel;
117 `define DISK_REG_DIRTN 0 /* R/W: step direction */
118 `define DISK_REG_CSTIN 1 /* R: disk in place (1 = no disk) */
119 /* W: ?? reset disk switch flag ? */
120 `define DISK_REG_STEP 2 /* R: disk stepping (1 = complete) */
121 /* W: 0 = step disk */
122 `define DISK_REG_WRTPRT 3 /* R: 0 = disk is write-protected */
123 `define DISK_REG_MOTORON 4 /* R/W: 0 = motor on */
124 `define DISK_REG_TK0 5 /* R: 0 = head at track 0 */
125 `define DISK_REG_EJECT 6 /* R: disk switched */
126 /* W: 1 = eject disk */
127 `define DISK_REG_TACH 7 /* R: tach-o-meter */
128 `define DISK_REG_RDDATA0 8 /* R: lower head activate */
129 `define DISK_REG_RDDATA9 9 /* R: upper head activate */
130 `define DISK_REG_SIDES 12 /* R: number of sides (0=single, 1=dbl) */
131 `define DISK_REG_READY 13 /* R: disk ready (head loaded) (0=ready) */
132 `define DISK_REG_INSTALLED 14 /* R: drive present (0 = yes) */
133 `define DISK_REG_DRVIN 15 /* R: drive present (0=yes, 1=no) XXX HD ?*/
135 /* Toggle control lines */
136 always@(posedge reset or posedge sysclk) begin
146 end else if (cs && phase) begin
160 /* ENBL1/2 lines. XXX We don't do the 1 second timer yet
161 * but I don't think the Mac ROM uses it anyways
163 always@(posedge reset or posedge sysclk) begin
168 if (cs && phase && rs[3:1] == 4) begin
177 /* Now for register read/writes, we need to use
178 * the "new" value of Q6, Q7 and ENABLE in the same
179 * cycle. We hack that up here.
181 assign new_Q6 = (cs && rs[3:1] == 6) ? rs[0] : Q6;
182 assign new_Q7 = (cs && rs[3:1] == 7) ? rs[0] : Q7;
183 assign new_EN = (cs && rs[3:1] == 4) ? rs[0] : ENABLE;
184 assign reg_wr = cs & phase & new_Q6 & new_Q7 & rs[0];
186 /* Internal register reads */
187 assign rdata = (!new_Q7 && !new_Q6 && new_EN) ? data_reg :
188 (!new_Q7 && new_Q6) ? stat_reg :
189 ( new_Q7 && !new_Q6) ? whsk_reg : 8'hff;
191 /* Internal write to mode register */
192 always@(posedge reset or posedge sysclk) begin
195 else if (reg_wr && !ENABLE)
196 mode_reg <= wdata[4:0];
199 /* Make up status and write handshake register wires */
200 assign stat_reg = { sense, 1'b0, enbl1 | enbl2, mode_reg[4:0] };
201 assign whsk_reg = 8'b11000000; /* XXX fixme */
203 /* Disk register reads */
204 // assign diskreg_idx = { CA2, CA1, CA0, via_sel };
205 // assign sense = diskregs = SELECT ? diskreg_b[diskreg_idx] :
206 // diskreg_a[diskreg_idx];
209 /* Test values for disk regs */
210 always@(posedge reset or posedge sysclk) begin
212 // diskregs[0] <= 16'b1001_1100_0001_0110;
213 // diskregs[1] <= 16'b1111_1111_1111_1111;
217 /* For now always ack immediately, we'll change that
218 * eventually when we have something with real data