Rev 543 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
668 | lvd | 1 | // ZX-Evo Base Configuration (c) NedoPC 2008,2009,2010,2011,2012,2013,2014 |
67 | lvd | 2 | // |
543 | lvd | 3 | // fpga SPI slave device -- AVR controlled. |
67 | lvd | 4 | |
668 | lvd | 5 | /* |
6 | This file is part of ZX-Evo Base Configuration firmware. |
||
67 | lvd | 7 | |
668 | lvd | 8 | ZX-Evo Base Configuration firmware is free software: |
9 | you can redistribute it and/or modify it under the terms of |
||
10 | the GNU General Public License as published by |
||
11 | the Free Software Foundation, either version 3 of the License, or |
||
12 | (at your option) any later version. |
||
543 | lvd | 13 | |
668 | lvd | 14 | ZX-Evo Base Configuration firmware is distributed in the hope that |
15 | it will be useful, but WITHOUT ANY WARRANTY; without even |
||
16 | the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
17 | See the GNU General Public License for more details. |
||
543 | lvd | 18 | |
668 | lvd | 19 | You should have received a copy of the GNU General Public License |
20 | along with ZX-Evo Base Configuration firmware. |
||
21 | If not, see <http://www.gnu.org/licenses/>. |
||
22 | */ |
||
23 | |||
30 | lvd | 24 | `include "../include/tune.v" |
25 | |||
4 | lvd | 26 | module slavespi( |
27 | |||
67 | lvd | 28 | input wire fclk, |
29 | input wire rst_n, |
||
4 | lvd | 30 | |
67 | lvd | 31 | input wire spics_n, // avr SPI iface |
32 | output wire spidi, // |
||
33 | input wire spido, // |
||
34 | input wire spick, // |
||
4 | lvd | 35 | |
67 | lvd | 36 | input wire [ 7:0] status_in, // status bits to be shown to avr |
4 | lvd | 37 | |
38 | |||
67 | lvd | 39 | output wire [39:0] kbd_out, |
40 | output wire kbd_stb, |
||
4 | lvd | 41 | |
67 | lvd | 42 | output wire [ 7:0] mus_out, |
43 | output wire mus_xstb, |
||
44 | output wire mus_ystb, |
||
45 | output wire mus_btnstb, |
||
110 | lvd | 46 | output wire kj_stb, |
67 | lvd | 47 | |
48 | |||
88 | lvd | 49 | input wire [ 7:0] gluclock_addr, |
228 | lvd | 50 | input wire [ 2:0] comport_addr, |
88 | lvd | 51 | |
52 | input wire [ 7:0] wait_write, |
||
53 | output wire [ 7:0] wait_read, |
||
54 | input wire wait_rnw, |
||
55 | |||
56 | output wire wait_end, |
||
57 | |||
98 | lvd | 58 | output wire [ 7:0] config0, // config bits for overall system |
59 | |||
543 | lvd | 60 | output wire genrst, // positive pulse, causes Z80 reset |
61 | |||
62 | output wire sd_lock_out, // SDcard control iface |
||
63 | input wire sd_lock_in, // |
||
64 | output wire sd_cs_n, // |
||
65 | output wire sd_start, // |
||
66 | output wire [ 7:0] sd_datain, // |
||
67 | input wire [ 7:0] sd_dataout // |
||
4 | lvd | 68 | ); |
69 | |||
200 | lvd | 70 | `ifdef SIMULATE |
71 | initial |
||
72 | begin |
||
425 | lvd | 73 | force wait_read = 8'h00; |
200 | lvd | 74 | end |
75 | `endif |
||
76 | |||
77 | |||
67 | lvd | 78 | // re-synchronize SPI |
79 | // |
||
80 | reg [2:0] spics_n_sync; |
||
81 | reg [1:0] spido_sync; |
||
82 | reg [2:0] spick_sync; |
||
83 | // |
||
84 | always @(posedge fclk) |
||
85 | begin |
||
86 | spics_n_sync[2:0] <= { spics_n_sync[1:0], spics_n }; |
||
87 | spido_sync [1:0] <= { spido_sync [0], spido }; |
||
88 | spick_sync [2:0] <= { spick_sync [1:0], spick }; |
||
89 | end |
||
90 | // |
||
91 | wire scs_n = spics_n_sync[1]; // scs_n - synchronized CS_N |
||
92 | wire sdo = spido_sync[1]; |
||
93 | wire sck = spick_sync[1]; |
||
94 | // |
||
95 | wire scs_n_01 = (~spics_n_sync[2]) & spics_n_sync[1] ; |
||
96 | wire scs_n_10 = spics_n_sync[2] & (~spics_n_sync[1]); |
||
97 | // |
||
88 | lvd | 98 | wire sck_01 = (~spick_sync[2]) & spick_sync[1] ; |
99 | wire sck_10 = spick_sync[2] & (~spick_sync[1]); |
||
4 | lvd | 100 | |
40 | lvd | 101 | |
67 | lvd | 102 | reg [7:0] regnum; // register number holder |
103 | |||
104 | reg [7:0] shift_out; |
||
105 | |||
88 | lvd | 106 | reg [7:0] data_in; |
67 | lvd | 107 | |
108 | |||
109 | |||
110 | // register selectors |
||
543 | lvd | 111 | wire sel_kbdreg, sel_kbdstb, sel_musxcr, sel_musycr, sel_musbtn, sel_kj, |
112 | sel_rstreg, sel_waitreg, sel_gluadr, sel_comadr, sel_cfg0, |
||
113 | sel_sddata, sel_sdctrl; |
||
67 | lvd | 114 | |
115 | // keyboard register |
||
116 | reg [39:0] kbd_reg; |
||
117 | |||
118 | |||
543 | lvd | 119 | // common single-byte shift-in register |
120 | reg [7:0] common_reg; |
||
67 | lvd | 121 | |
543 | lvd | 122 | |
88 | lvd | 123 | // wait data out register |
124 | reg [7:0] wait_reg; |
||
67 | lvd | 125 | |
98 | lvd | 126 | // |
543 | lvd | 127 | reg [7:0] cfg0_reg_out; // one for shifting, second for storing values |
67 | lvd | 128 | |
129 | |||
543 | lvd | 130 | // SDcard access registers |
131 | reg [7:0] sddata; // output to SDcard |
||
132 | reg [1:0] sdctrl; // SDcard control (CS_n and lock) |
||
67 | lvd | 133 | |
543 | lvd | 134 | |
40 | lvd | 135 | `ifdef SIMULATE |
136 | initial |
||
137 | begin |
||
200 | lvd | 138 | cfg0_reg_out[7:0] = 8'd0; |
40 | lvd | 139 | end |
140 | `endif |
||
141 | |||
142 | |||
67 | lvd | 143 | // register number |
144 | // |
||
145 | always @(posedge fclk) |
||
146 | begin |
||
147 | if( scs_n_01 ) |
||
148 | begin |
||
149 | regnum <= 8'd0; |
||
150 | end |
||
69 | lvd | 151 | else if( scs_n && sck_01 ) |
67 | lvd | 152 | begin |
153 | regnum[7:0] <= { sdo, regnum[7:1] }; |
||
154 | end |
||
155 | end |
||
40 | lvd | 156 | |
157 | |||
67 | lvd | 158 | // send data to avr |
159 | // |
||
88 | lvd | 160 | always @* |
543 | lvd | 161 | case(1'b1) |
162 | sel_waitreg: data_in = wait_write; |
||
163 | sel_gluadr: data_in = gluclock_addr; |
||
164 | sel_comadr: data_in = comport_addr; |
||
165 | sel_sddata: data_in = sd_dataout; |
||
166 | sel_sdctrl: data_in = { sd_lock_in, 7'bXXX_XXXX }; |
||
167 | default: data_in = 8'bXXXX_XXXX; |
||
168 | endcase |
||
88 | lvd | 169 | // |
67 | lvd | 170 | always @(posedge fclk) |
171 | begin |
||
172 | if( scs_n_01 || scs_n_10 ) // both edges |
||
173 | begin |
||
174 | shift_out <= scs_n ? status_in : data_in; |
||
175 | end |
||
176 | else if( sck_01 ) |
||
177 | begin |
||
178 | shift_out[7:0] <= { 1'b0, shift_out[7:1] }; |
||
179 | end |
||
180 | end |
||
181 | // |
||
182 | assign spidi = shift_out[0]; |
||
183 | |||
184 | |||
185 | // reg number decoding |
||
186 | // |
||
110 | lvd | 187 | assign sel_kbdreg = ( (regnum[7:4]==4'h1) && !regnum[0] ); // $10 |
188 | assign sel_kbdstb = ( (regnum[7:4]==4'h1) && regnum[0] ); // $11 |
||
67 | lvd | 189 | // |
110 | lvd | 190 | assign sel_musxcr = ( (regnum[7:4]==4'h2) && !regnum[1] && !regnum[0] ); // $20 |
191 | assign sel_musycr = ( (regnum[7:4]==4'h2) && !regnum[1] && regnum[0] ); // $21 |
||
192 | assign sel_musbtn = ( (regnum[7:4]==4'h2) && regnum[1] && !regnum[0] ); // $22 |
||
193 | assign sel_kj = ( (regnum[7:4]==4'h2) && regnum[1] && regnum[0] ); // $23 |
||
67 | lvd | 194 | // |
110 | lvd | 195 | assign sel_rstreg = ( (regnum[7:4]==4'h3) ) ; // $30 |
88 | lvd | 196 | // |
228 | lvd | 197 | assign sel_waitreg = ( (regnum[7:4]==4'h4) && (regnum[1:0]==2'b00) ); // $40 |
198 | assign sel_gluadr = ( (regnum[7:4]==4'h4) && (regnum[1:0]==2'b01) ); // $41 |
||
199 | assign sel_comadr = ( (regnum[7:4]==4'h4) && (regnum[1:0]==2'b10) ); // $42 |
||
98 | lvd | 200 | // |
110 | lvd | 201 | assign sel_cfg0 = (regnum[7:4]==4'h5); // $50 |
543 | lvd | 202 | // |
203 | assign sel_sddata = ( (regnum[7:4]==4'h6) && !regnum[0] ); // $60 |
||
204 | assign sel_sdctrl = ( (regnum[7:4]==4'h6) && regnum[0] ); // $61 |
||
67 | lvd | 205 | |
206 | |||
207 | // registers data-in |
||
208 | // |
||
209 | always @(posedge fclk) |
||
210 | begin |
||
543 | lvd | 211 | // kbd data shift-in |
70 | lvd | 212 | if( !scs_n && sel_kbdreg && sck_01 ) |
67 | lvd | 213 | kbd_reg[39:0] <= { sdo, kbd_reg[39:1] }; |
214 | |||
543 | lvd | 215 | // mouse data shift-in |
110 | lvd | 216 | if( !scs_n && (sel_musxcr || sel_musycr || sel_musbtn || sel_kj) && sck_01 ) |
543 | lvd | 217 | common_reg[7:0] <= { sdo, common_reg[7:1] }; |
67 | lvd | 218 | |
543 | lvd | 219 | // wait read data shift-in |
88 | lvd | 220 | if( !scs_n && sel_waitreg && sck_01 ) |
221 | wait_reg[7:0] <= { sdo, wait_reg[7:1] }; |
||
98 | lvd | 222 | |
543 | lvd | 223 | // config shift-in |
98 | lvd | 224 | if( !scs_n && sel_cfg0 && sck_01 ) |
543 | lvd | 225 | common_reg[7:0] <= { sdo, common_reg[7:1] }; |
98 | lvd | 226 | |
543 | lvd | 227 | // config output |
98 | lvd | 228 | if( scs_n_01 && sel_cfg0 ) |
543 | lvd | 229 | cfg0_reg_out <= common_reg; |
230 | |||
231 | // SD data shift-in |
||
232 | if( !scs_n && sel_sddata && sck_01 ) |
||
233 | common_reg[7:0] <= { sdo, common_reg[7:1] }; |
||
234 | |||
235 | // SD control shift-in |
||
236 | if( !scs_n && sel_sdctrl && sck_01 ) |
||
237 | common_reg[7:0] <= { sdo, common_reg[7:1] }; |
||
67 | lvd | 238 | end |
543 | lvd | 239 | // |
240 | // SD control output |
||
241 | always @(posedge fclk, negedge rst_n) |
||
242 | if( !rst_n ) |
||
243 | sdctrl <= 2'b01; |
||
244 | else // posedge clk |
||
245 | begin |
||
246 | if( scs_n_01 && sel_sdctrl ) |
||
247 | sdctrl <= { common_reg[7], common_reg[0] }; |
||
248 | end |
||
67 | lvd | 249 | |
250 | |||
251 | // output data |
||
252 | assign kbd_out = kbd_reg; |
||
70 | lvd | 253 | assign kbd_stb = sel_kbdstb && scs_n_01; |
67 | lvd | 254 | |
543 | lvd | 255 | assign mus_out = common_reg; |
67 | lvd | 256 | assign mus_xstb = sel_musxcr && scs_n_01; |
257 | assign mus_ystb = sel_musycr && scs_n_01; |
||
258 | assign mus_btnstb = sel_musbtn && scs_n_01; |
||
110 | lvd | 259 | assign kj_stb = sel_kj && scs_n_01; |
67 | lvd | 260 | |
261 | assign genrst = sel_rstreg && scs_n_01; |
||
262 | |||
88 | lvd | 263 | assign wait_read = wait_reg; |
264 | assign wait_end = sel_waitreg && scs_n_01; |
||
4 | lvd | 265 | |
98 | lvd | 266 | assign config0 = cfg0_reg_out; |
4 | lvd | 267 | |
543 | lvd | 268 | |
269 | |||
270 | // SD control output |
||
271 | assign sd_lock_out = sdctrl[1]; |
||
272 | assign sd_cs_n = sdctrl[0]; |
||
273 | |||
274 | // SD data output |
||
275 | assign sd_datain = common_reg; |
||
276 | // SD start strobe |
||
277 | assign sd_start = sel_sddata && scs_n_01; |
||
278 | |||
279 | |||
4 | lvd | 280 | endmodule |
281 |