Rev 668 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
826 | lvd | 1 | // ZX-Evo Base Configuration (c) NedoPC 2008,2009,2010,2011,2012,2013,2014,2019 |
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 |
826 | lvd | 59 | output wire [ 7:0] config1, // |
98 | lvd | 60 | |
543 | lvd | 61 | output wire genrst, // positive pulse, causes Z80 reset |
62 | |||
63 | output wire sd_lock_out, // SDcard control iface |
||
64 | input wire sd_lock_in, // |
||
65 | output wire sd_cs_n, // |
||
66 | output wire sd_start, // |
||
67 | output wire [ 7:0] sd_datain, // |
||
68 | input wire [ 7:0] sd_dataout // |
||
4 | lvd | 69 | ); |
70 | |||
200 | lvd | 71 | `ifdef SIMULATE |
72 | initial |
||
73 | begin |
||
425 | lvd | 74 | force wait_read = 8'h00; |
200 | lvd | 75 | end |
76 | `endif |
||
77 | |||
78 | |||
67 | lvd | 79 | // re-synchronize SPI |
80 | // |
||
81 | reg [2:0] spics_n_sync; |
||
82 | reg [1:0] spido_sync; |
||
83 | reg [2:0] spick_sync; |
||
84 | // |
||
85 | always @(posedge fclk) |
||
86 | begin |
||
87 | spics_n_sync[2:0] <= { spics_n_sync[1:0], spics_n }; |
||
88 | spido_sync [1:0] <= { spido_sync [0], spido }; |
||
89 | spick_sync [2:0] <= { spick_sync [1:0], spick }; |
||
90 | end |
||
91 | // |
||
92 | wire scs_n = spics_n_sync[1]; // scs_n - synchronized CS_N |
||
93 | wire sdo = spido_sync[1]; |
||
94 | wire sck = spick_sync[1]; |
||
95 | // |
||
96 | wire scs_n_01 = (~spics_n_sync[2]) & spics_n_sync[1] ; |
||
97 | wire scs_n_10 = spics_n_sync[2] & (~spics_n_sync[1]); |
||
98 | // |
||
88 | lvd | 99 | wire sck_01 = (~spick_sync[2]) & spick_sync[1] ; |
100 | wire sck_10 = spick_sync[2] & (~spick_sync[1]); |
||
4 | lvd | 101 | |
40 | lvd | 102 | |
67 | lvd | 103 | reg [7:0] regnum; // register number holder |
104 | |||
105 | reg [7:0] shift_out; |
||
106 | |||
88 | lvd | 107 | reg [7:0] data_in; |
67 | lvd | 108 | |
109 | |||
110 | |||
111 | // register selectors |
||
543 | lvd | 112 | wire sel_kbdreg, sel_kbdstb, sel_musxcr, sel_musycr, sel_musbtn, sel_kj, |
826 | lvd | 113 | sel_rstreg, sel_waitreg, sel_gluadr, sel_comadr, sel_cfg0, sel_cfg1, |
543 | lvd | 114 | sel_sddata, sel_sdctrl; |
67 | lvd | 115 | |
116 | // keyboard register |
||
117 | reg [39:0] kbd_reg; |
||
118 | |||
119 | |||
543 | lvd | 120 | // common single-byte shift-in register |
121 | reg [7:0] common_reg; |
||
67 | lvd | 122 | |
543 | lvd | 123 | |
88 | lvd | 124 | // wait data out register |
125 | reg [7:0] wait_reg; |
||
67 | lvd | 126 | |
98 | lvd | 127 | // |
826 | lvd | 128 | reg [7:0] cfg0_reg_out; |
129 | reg [7:0] cfg1_reg_out; |
||
67 | lvd | 130 | |
131 | |||
543 | lvd | 132 | // SDcard access registers |
133 | reg [7:0] sddata; // output to SDcard |
||
134 | reg [1:0] sdctrl; // SDcard control (CS_n and lock) |
||
67 | lvd | 135 | |
543 | lvd | 136 | |
40 | lvd | 137 | `ifdef SIMULATE |
138 | initial |
||
139 | begin |
||
200 | lvd | 140 | cfg0_reg_out[7:0] = 8'd0; |
40 | lvd | 141 | end |
142 | `endif |
||
143 | |||
144 | |||
67 | lvd | 145 | // register number |
146 | // |
||
147 | always @(posedge fclk) |
||
148 | begin |
||
149 | if( scs_n_01 ) |
||
150 | begin |
||
151 | regnum <= 8'd0; |
||
152 | end |
||
69 | lvd | 153 | else if( scs_n && sck_01 ) |
67 | lvd | 154 | begin |
155 | regnum[7:0] <= { sdo, regnum[7:1] }; |
||
156 | end |
||
157 | end |
||
40 | lvd | 158 | |
159 | |||
67 | lvd | 160 | // send data to avr |
161 | // |
||
88 | lvd | 162 | always @* |
543 | lvd | 163 | case(1'b1) |
164 | sel_waitreg: data_in = wait_write; |
||
165 | sel_gluadr: data_in = gluclock_addr; |
||
166 | sel_comadr: data_in = comport_addr; |
||
167 | sel_sddata: data_in = sd_dataout; |
||
168 | sel_sdctrl: data_in = { sd_lock_in, 7'bXXX_XXXX }; |
||
169 | default: data_in = 8'bXXXX_XXXX; |
||
170 | endcase |
||
88 | lvd | 171 | // |
67 | lvd | 172 | always @(posedge fclk) |
173 | begin |
||
174 | if( scs_n_01 || scs_n_10 ) // both edges |
||
175 | begin |
||
176 | shift_out <= scs_n ? status_in : data_in; |
||
177 | end |
||
178 | else if( sck_01 ) |
||
179 | begin |
||
180 | shift_out[7:0] <= { 1'b0, shift_out[7:1] }; |
||
181 | end |
||
182 | end |
||
183 | // |
||
184 | assign spidi = shift_out[0]; |
||
185 | |||
186 | |||
187 | // reg number decoding |
||
188 | // |
||
110 | lvd | 189 | assign sel_kbdreg = ( (regnum[7:4]==4'h1) && !regnum[0] ); // $10 |
190 | assign sel_kbdstb = ( (regnum[7:4]==4'h1) && regnum[0] ); // $11 |
||
67 | lvd | 191 | // |
110 | lvd | 192 | assign sel_musxcr = ( (regnum[7:4]==4'h2) && !regnum[1] && !regnum[0] ); // $20 |
193 | assign sel_musycr = ( (regnum[7:4]==4'h2) && !regnum[1] && regnum[0] ); // $21 |
||
194 | assign sel_musbtn = ( (regnum[7:4]==4'h2) && regnum[1] && !regnum[0] ); // $22 |
||
195 | assign sel_kj = ( (regnum[7:4]==4'h2) && regnum[1] && regnum[0] ); // $23 |
||
67 | lvd | 196 | // |
110 | lvd | 197 | assign sel_rstreg = ( (regnum[7:4]==4'h3) ) ; // $30 |
88 | lvd | 198 | // |
228 | lvd | 199 | assign sel_waitreg = ( (regnum[7:4]==4'h4) && (regnum[1:0]==2'b00) ); // $40 |
200 | assign sel_gluadr = ( (regnum[7:4]==4'h4) && (regnum[1:0]==2'b01) ); // $41 |
||
201 | assign sel_comadr = ( (regnum[7:4]==4'h4) && (regnum[1:0]==2'b10) ); // $42 |
||
98 | lvd | 202 | // |
826 | lvd | 203 | assign sel_cfg0 = (regnum[7:4]==4'h5 && regnum[0]==1'b0); // $50 |
204 | assign sel_cfg1 = (regnum[7:4]==4'h5 && regnum[0]==1'b1); // $51 |
||
543 | lvd | 205 | // |
206 | assign sel_sddata = ( (regnum[7:4]==4'h6) && !regnum[0] ); // $60 |
||
207 | assign sel_sdctrl = ( (regnum[7:4]==4'h6) && regnum[0] ); // $61 |
||
67 | lvd | 208 | |
209 | |||
210 | // registers data-in |
||
211 | // |
||
212 | always @(posedge fclk) |
||
213 | begin |
||
543 | lvd | 214 | // kbd data shift-in |
70 | lvd | 215 | if( !scs_n && sel_kbdreg && sck_01 ) |
67 | lvd | 216 | kbd_reg[39:0] <= { sdo, kbd_reg[39:1] }; |
217 | |||
543 | lvd | 218 | // mouse data shift-in |
110 | lvd | 219 | if( !scs_n && (sel_musxcr || sel_musycr || sel_musbtn || sel_kj) && sck_01 ) |
543 | lvd | 220 | common_reg[7:0] <= { sdo, common_reg[7:1] }; |
67 | lvd | 221 | |
543 | lvd | 222 | // wait read data shift-in |
88 | lvd | 223 | if( !scs_n && sel_waitreg && sck_01 ) |
224 | wait_reg[7:0] <= { sdo, wait_reg[7:1] }; |
||
98 | lvd | 225 | |
543 | lvd | 226 | // config shift-in |
826 | lvd | 227 | if( !scs_n && (sel_cfg0 || sel_cfg1) && sck_01 ) |
543 | lvd | 228 | common_reg[7:0] <= { sdo, common_reg[7:1] }; |
98 | lvd | 229 | |
543 | lvd | 230 | // config output |
98 | lvd | 231 | if( scs_n_01 && sel_cfg0 ) |
543 | lvd | 232 | cfg0_reg_out <= common_reg; |
826 | lvd | 233 | if( scs_n_01 && sel_cfg1 ) |
234 | cfg1_reg_out <= common_reg; |
||
543 | lvd | 235 | |
236 | // SD data shift-in |
||
237 | if( !scs_n && sel_sddata && sck_01 ) |
||
238 | common_reg[7:0] <= { sdo, common_reg[7:1] }; |
||
239 | |||
240 | // SD control shift-in |
||
241 | if( !scs_n && sel_sdctrl && sck_01 ) |
||
242 | common_reg[7:0] <= { sdo, common_reg[7:1] }; |
||
67 | lvd | 243 | end |
543 | lvd | 244 | // |
245 | // SD control output |
||
246 | always @(posedge fclk, negedge rst_n) |
||
247 | if( !rst_n ) |
||
248 | sdctrl <= 2'b01; |
||
249 | else // posedge clk |
||
250 | begin |
||
251 | if( scs_n_01 && sel_sdctrl ) |
||
252 | sdctrl <= { common_reg[7], common_reg[0] }; |
||
253 | end |
||
67 | lvd | 254 | |
255 | |||
256 | // output data |
||
257 | assign kbd_out = kbd_reg; |
||
70 | lvd | 258 | assign kbd_stb = sel_kbdstb && scs_n_01; |
67 | lvd | 259 | |
543 | lvd | 260 | assign mus_out = common_reg; |
67 | lvd | 261 | assign mus_xstb = sel_musxcr && scs_n_01; |
262 | assign mus_ystb = sel_musycr && scs_n_01; |
||
263 | assign mus_btnstb = sel_musbtn && scs_n_01; |
||
110 | lvd | 264 | assign kj_stb = sel_kj && scs_n_01; |
67 | lvd | 265 | |
266 | assign genrst = sel_rstreg && scs_n_01; |
||
267 | |||
88 | lvd | 268 | assign wait_read = wait_reg; |
269 | assign wait_end = sel_waitreg && scs_n_01; |
||
4 | lvd | 270 | |
98 | lvd | 271 | assign config0 = cfg0_reg_out; |
826 | lvd | 272 | assign config1 = cfg1_reg_out; |
4 | lvd | 273 | |
543 | lvd | 274 | |
275 | |||
276 | // SD control output |
||
277 | assign sd_lock_out = sdctrl[1]; |
||
278 | assign sd_cs_n = sdctrl[0]; |
||
279 | |||
280 | // SD data output |
||
281 | assign sd_datain = common_reg; |
||
282 | // SD start strobe |
||
283 | assign sd_start = sel_sddata && scs_n_01; |
||
284 | |||
285 | |||
4 | lvd | 286 | endmodule |
287 |