]> git.ozlabs.org Git - minimigmac.git/blob - fpga/iwm.v
Initial commit
[minimigmac.git] / fpga / iwm.v
1 `timescale 1ns / 100ps
2
3 /*
4  * IWM module for minimigmac.
5  * 
6  *              Location to     Location to
7  *  IWM line    turn line on    turn line off
8  *
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
14  *
15  *  Disk enable line:
16  *    ENABLE    dBase+motorOn   dBase+motorOff
17  *
18  *  IWM internal states:
19  *    SELECT    dBase+extDrive  dBase+intDrive
20  *    Q6        dBase+q6H       dBase+q6L
21  *    Q7        dBase+q7H       dBase+q7L
22  *
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
39  */
40
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
57
58
59 module iwm(input        sysclk,
60            input        reset,
61
62            /* Bus interface. 4-bit address, to be wired
63             * appropriately upstream (to A9..A12)
64             */
65            input                cs,
66            input                we,
67            output               ack,
68            input                phase,
69            input [3:0]          rs,
70            input [7:0]          wdata,
71            output [7:0]         rdata,
72
73            /* Backbus interface */
74            input [5:0]          bb_addr,
75            input [7:0]          bb_wdata,
76            output reg [7:0]     bb_rdata,
77            input                bb_strobe,
78            input                bb_wr,
79
80            /* SEL line from VIA */
81            input                via_sel
82            );
83
84         /* IWM state register broken up by name */
85         reg     CA0;
86         reg     CA1;
87         reg     CA2;
88         reg     LSTRB;
89         reg     ENABLE;
90         reg     SELECT;
91         reg     Q6;
92         reg     Q7;
93
94         /* Internal wires */
95         wire    new_Q6;
96         wire    new_Q7;
97         wire    new_EN;
98         wire    reg_wr;
99
100         /* Internal data & mode registers */
101         reg [7:0] data_reg;
102         reg [4:0] mode_reg;
103
104         /* Status and write handshake are just wires */
105         wire [7:0] stat_reg;
106         wire [7:0] whsk_reg;
107
108         /* Sense line from disk */
109         wire       sense;
110
111         /* enbl1 and enbl2 lines (not inverted here unlike real HW) */
112         reg        enbl1;
113         reg        enbl2;
114
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 ?*/
134         
135         /* Toggle control lines */
136         always@(posedge reset or posedge sysclk) begin
137                 if (reset) begin
138                         CA0 <= 0;
139                         CA1 <= 0;
140                         CA2 <= 0;
141                         LSTRB <= 0;
142                         ENABLE <= 0;
143                         SELECT <= 0;
144                         Q6 <= 0;
145                         Q7 <= 0;
146                 end else if (cs && phase) begin
147                         case(rs[3:1])
148                                 0: CA0 <= rs[0];
149                                 1: CA1 <= rs[0];
150                                 2: CA2 <= rs[0];
151                                 3: LSTRB <= rs[0];
152                                 4: ENABLE <= rs[0];
153                                 5: SELECT <= rs[0];
154                                 6: Q6 <= rs[0];
155                                 7: Q7 <= rs[0];
156                         endcase
157                 end             
158         end
159
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
162          */
163         always@(posedge reset or posedge sysclk) begin
164                 if (reset) begin
165                         enbl1 <= 0;
166                         enbl2 <= 0;
167                 end else begin
168                         if (cs && phase && rs[3:1] == 4) begin
169                                 if (SELECT)
170                                   enbl2 <= rs[0];
171                                 else
172                                   enbl1 <= rs[0];
173                         end
174                 end
175         end
176                 
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.
180          */
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];
185
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;
190
191         /* Internal write to mode register */
192         always@(posedge reset or posedge sysclk) begin
193                 if (reset)
194                   mode_reg <= 0;
195                 else if (reg_wr && !ENABLE)
196                   mode_reg <= wdata[4:0];
197         end
198         
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 */  
202
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];
207         assign sense = 1'b1;    
208
209         /* Test values for disk regs */
210         always@(posedge reset or posedge sysclk) begin
211                 if (reset) begin
212 //                      diskregs[0] <= 16'b1001_1100_0001_0110;
213 //                      diskregs[1] <= 16'b1111_1111_1111_1111;
214                 end
215         end
216         
217         /* For now always ack immediately, we'll change that
218          * eventually when we have something with real data
219          */
220         assign ack = cs;
221 endmodule