Top secrets sources NedoPC pentevo

Rev

Rev 668 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

// ZX-Evo Base Configuration (c) NedoPC 2008,2009,2010,2011,2012,2013,2014,2019
//
// fpga SPI slave device -- AVR controlled.

/*
    This file is part of ZX-Evo Base Configuration firmware.

    ZX-Evo Base Configuration firmware is free software:
    you can redistribute it and/or modify it under the terms of
    the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    ZX-Evo Base Configuration firmware is distributed in the hope that
    it will be useful, but WITHOUT ANY WARRANTY; without even
    the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    See the GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ZX-Evo Base Configuration firmware.
    If not, see <http://www.gnu.org/licenses/>.
*/


`include "../include/tune.v"

module slavespi(

        input  wire fclk,
        input  wire rst_n,

        input  wire spics_n, // avr SPI iface
        output wire spidi,   //
        input  wire spido,   //
        input  wire spick,   //

        input  wire [ 7:0] status_in, // status bits to be shown to avr


        output wire [39:0] kbd_out,
        output wire        kbd_stb,

        output wire [ 7:0] mus_out,
        output wire        mus_xstb,
        output wire        mus_ystb,
        output wire        mus_btnstb,
        output wire        kj_stb,


        input  wire [ 7:0] gluclock_addr,
        input  wire [ 2:0] comport_addr,

        input  wire [ 7:0] wait_write,
        output wire [ 7:0] wait_read,
        input  wire        wait_rnw,

        output wire        wait_end,

        output wire [ 7:0] config0, // config bits for overall system
        output wire [ 7:0] config1, //

        output wire        genrst, // positive pulse, causes Z80 reset

        output wire        sd_lock_out, // SDcard control iface
        input  wire        sd_lock_in,  //
        output wire        sd_cs_n,     //
        output wire        sd_start,    //
        output wire [ 7:0] sd_datain,   //
        input  wire [ 7:0] sd_dataout   //
);

`ifdef SIMULATE
        initial
        begin
                force wait_read = 8'h00;
        end
`endif


        // re-synchronize SPI
        //
        reg [2:0] spics_n_sync;
        reg [1:0] spido_sync;
        reg [2:0] spick_sync;
        //
        always @(posedge fclk)
        begin
                spics_n_sync[2:0] <= { spics_n_sync[1:0], spics_n };
                spido_sync  [1:0] <= { spido_sync    [0], spido   };
                spick_sync  [2:0] <= { spick_sync  [1:0], spick   };
        end
        //
        wire scs_n = spics_n_sync[1]; // scs_n - synchronized CS_N
        wire sdo   = spido_sync[1];
        wire sck   = spick_sync[1];
        //
        wire scs_n_01 = (~spics_n_sync[2]) &   spics_n_sync[1] ;
        wire scs_n_10 =   spics_n_sync[2]  & (~spics_n_sync[1]);
        //
        wire sck_01 = (~spick_sync[2]) &   spick_sync[1] ;
        wire sck_10 =   spick_sync[2]  & (~spick_sync[1]);


        reg [7:0] regnum; // register number holder

        reg [7:0] shift_out;

        reg [7:0] data_in;



        // register selectors
        wire sel_kbdreg, sel_kbdstb, sel_musxcr, sel_musycr, sel_musbtn, sel_kj,
             sel_rstreg, sel_waitreg, sel_gluadr, sel_comadr, sel_cfg0, sel_cfg1,
             sel_sddata, sel_sdctrl;

        // keyboard register
        reg [39:0] kbd_reg;


        // common single-byte shift-in register
        reg [7:0] common_reg;


        // wait data out register
        reg [7:0] wait_reg;

        //
        reg [7:0] cfg0_reg_out;
        reg [7:0] cfg1_reg_out;


        // SDcard access registers
        reg [7:0] sddata; // output to SDcard
        reg [1:0] sdctrl; // SDcard control (CS_n and lock)


`ifdef SIMULATE
        initial
        begin
                cfg0_reg_out[7:0] = 8'd0;
        end
`endif


        // register number
        //
        always @(posedge fclk)
        begin
                if( scs_n_01 )
                begin
                        regnum <= 8'd0;
                end
                else if( scs_n && sck_01 )
                begin
                        regnum[7:0] <= { sdo, regnum[7:1] };
                end
        end


        // send data to avr
        //
        always @*
        case(1'b1)
                sel_waitreg: data_in = wait_write;
                sel_gluadr:  data_in = gluclock_addr;
                sel_comadr:  data_in = comport_addr;
                sel_sddata:  data_in = sd_dataout;
                sel_sdctrl:  data_in = { sd_lock_in, 7'bXXX_XXXX };
                default:     data_in = 8'bXXXX_XXXX;
        endcase
        //
        always @(posedge fclk)
        begin
                if( scs_n_01 || scs_n_10 ) // both edges
                begin
                        shift_out <= scs_n ? status_in : data_in;
                end
                else if( sck_01 )
                begin
                        shift_out[7:0] <= { 1'b0, shift_out[7:1] };
                end
        end
        //
        assign spidi = shift_out[0];


        // reg number decoding
        //
        assign sel_kbdreg = ( (regnum[7:4]==4'h1) && !regnum[0] ); // $10
        assign sel_kbdstb = ( (regnum[7:4]==4'h1) &&  regnum[0] ); // $11
        //
        assign sel_musxcr = ( (regnum[7:4]==4'h2) && !regnum[1] && !regnum[0] ); // $20
        assign sel_musycr = ( (regnum[7:4]==4'h2) && !regnum[1] &&  regnum[0] ); // $21
        assign sel_musbtn = ( (regnum[7:4]==4'h2) &&  regnum[1] && !regnum[0] ); // $22
        assign sel_kj     = ( (regnum[7:4]==4'h2) &&  regnum[1] &&  regnum[0] ); // $23
        //
        assign sel_rstreg = ( (regnum[7:4]==4'h3) ) ; // $30
        //
        assign sel_waitreg = ( (regnum[7:4]==4'h4) && (regnum[1:0]==2'b00) ); // $40
        assign sel_gluadr  = ( (regnum[7:4]==4'h4) && (regnum[1:0]==2'b01) ); // $41
        assign sel_comadr  = ( (regnum[7:4]==4'h4) && (regnum[1:0]==2'b10) ); // $42
        //
        assign sel_cfg0 = (regnum[7:4]==4'h5 && regnum[0]==1'b0); // $50
        assign sel_cfg1 = (regnum[7:4]==4'h5 && regnum[0]==1'b1); // $51
        //
        assign sel_sddata = ( (regnum[7:4]==4'h6) && !regnum[0] ); // $60
        assign sel_sdctrl = ( (regnum[7:4]==4'h6) &&  regnum[0] ); // $61


        // registers data-in
        //
        always @(posedge fclk)
        begin
                // kbd data shift-in
                if( !scs_n && sel_kbdreg && sck_01 )
                        kbd_reg[39:0] <= { sdo, kbd_reg[39:1] };

                // mouse data shift-in
                if( !scs_n && (sel_musxcr || sel_musycr || sel_musbtn || sel_kj) && sck_01 )
                        common_reg[7:0] <= { sdo, common_reg[7:1] };

                // wait read data shift-in
                if( !scs_n && sel_waitreg && sck_01 )
                        wait_reg[7:0] <= { sdo, wait_reg[7:1] };

                // config shift-in
                if( !scs_n && (sel_cfg0 || sel_cfg1) && sck_01 )
                        common_reg[7:0] <= { sdo, common_reg[7:1] };

                // config output
                if( scs_n_01 && sel_cfg0 )
                        cfg0_reg_out <= common_reg;
                if( scs_n_01 && sel_cfg1 )
                        cfg1_reg_out <= common_reg;

                // SD data shift-in
                if( !scs_n && sel_sddata && sck_01 )
                        common_reg[7:0] <= { sdo, common_reg[7:1] };

                // SD control shift-in
                if( !scs_n && sel_sdctrl && sck_01 )
                        common_reg[7:0] <= { sdo, common_reg[7:1] };
        end
        //
        // SD control output
        always @(posedge fclk, negedge rst_n)
        if( !rst_n )
                sdctrl <= 2'b01;
        else // posedge clk
        begin
                if( scs_n_01 && sel_sdctrl )
                        sdctrl <= { common_reg[7], common_reg[0] };
        end


        // output data
        assign kbd_out = kbd_reg;
        assign kbd_stb = sel_kbdstb && scs_n_01;

        assign mus_out    = common_reg;
        assign mus_xstb   = sel_musxcr && scs_n_01;
        assign mus_ystb   = sel_musycr && scs_n_01;
        assign mus_btnstb = sel_musbtn && scs_n_01;
        assign kj_stb     = sel_kj     && scs_n_01;

        assign genrst = sel_rstreg && scs_n_01;

        assign wait_read = wait_reg;
        assign wait_end = sel_waitreg && scs_n_01;

        assign config0 = cfg0_reg_out;
        assign config1 = cfg1_reg_out;



        // SD control output
        assign sd_lock_out = sdctrl[1];
        assign sd_cs_n     = sdctrl[0];

        // SD data output
        assign sd_datain = common_reg;
        // SD start strobe
        assign sd_start = sel_sddata && scs_n_01;


endmodule