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 |