Subversion Repositories pentevo

Rev

Rev 98 | Rev 228 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. // (c) 2010 NedoPC
  2. //
  3. // fpga SPI slave device.
  4.  
  5.  
  6. `include "../include/tune.v"
  7.  
  8. module slavespi(
  9.  
  10.         input  wire fclk,
  11.         input  wire rst_n,
  12.  
  13.         input  wire spics_n, // avr SPI iface
  14.         output wire spidi,   //
  15.         input  wire spido,   //
  16.         input  wire spick,   //
  17.  
  18.         input  wire [ 7:0] status_in, // status bits to be shown to avr
  19.  
  20.  
  21.         output wire [39:0] kbd_out,
  22.         output wire        kbd_stb,
  23.  
  24.         output wire [ 7:0] mus_out,
  25.         output wire        mus_xstb,
  26.         output wire        mus_ystb,
  27.         output wire        mus_btnstb,
  28.         output wire        kj_stb,
  29.  
  30.  
  31.         input  wire [ 7:0] gluclock_addr,
  32.  
  33.         input  wire [ 7:0] wait_write,
  34.         output wire [ 7:0] wait_read,
  35.         input  wire        wait_rnw,
  36.  
  37.         output wire        wait_end,
  38.  
  39.         output wire [ 7:0] config0, // config bits for overall system
  40.  
  41.         output wire       genrst, // positive pulse, causes Z80 reset
  42.         output wire [1:0] rstrom  // number of ROM page to reset to
  43. );
  44.  
  45.         // re-synchronize SPI
  46.         //
  47.         reg [2:0] spics_n_sync;
  48.         reg [1:0] spido_sync;
  49.         reg [2:0] spick_sync;
  50.         //
  51.         always @(posedge fclk)
  52.         begin
  53.                 spics_n_sync[2:0] <= { spics_n_sync[1:0], spics_n };
  54.                 spido_sync  [1:0] <= { spido_sync    [0], spido   };
  55.                 spick_sync  [2:0] <= { spick_sync  [1:0], spick   };
  56.         end
  57.         //
  58.         wire scs_n = spics_n_sync[1]; // scs_n - synchronized CS_N
  59.         wire sdo   = spido_sync[1];
  60.         wire sck   = spick_sync[1];
  61.         //
  62.         wire scs_n_01 = (~spics_n_sync[2]) &   spics_n_sync[1] ;
  63.         wire scs_n_10 =   spics_n_sync[2]  & (~spics_n_sync[1]);
  64.         //
  65.         wire sck_01 = (~spick_sync[2]) &   spick_sync[1] ;
  66.         wire sck_10 =   spick_sync[2]  & (~spick_sync[1]);
  67.  
  68.  
  69.         reg [7:0] regnum; // register number holder
  70.  
  71.         reg [7:0] shift_out;
  72.  
  73.         reg [7:0] data_in;
  74.  
  75.  
  76.  
  77.         // register selectors
  78.         wire sel_kbdreg, sel_kbdstb, sel_musxcr, sel_musycr, sel_musbtn, sel_kj;
  79.         wire sel_rstreg, sel_waitreg, sel_gluadr, sel_cfg0;
  80.  
  81.         // keyboard register
  82.         reg [39:0] kbd_reg;
  83.  
  84.         // mouse register
  85.         reg [7:0] mouse_buf;
  86.  
  87.         // reset register
  88.         reg [7:0] rst_reg;
  89.  
  90.         // wait data out register
  91.         reg [7:0] wait_reg;
  92.  
  93.         //
  94.         reg [7:0] cfg0_reg_in, cfg0_reg_out; // one for shifting, second for storing values
  95.  
  96.  
  97.  
  98. `ifdef SIMULATE
  99.         initial
  100.         begin
  101.                 rstrom = 2'b00;
  102.                 genrst = 1'b0;
  103.         end
  104. `endif
  105.  
  106.  
  107.         // register number
  108.         //
  109.         always @(posedge fclk)
  110.         begin
  111.                 if( scs_n_01 )
  112.                 begin
  113.                         regnum <= 8'd0;
  114.                 end
  115.                 else if( scs_n && sck_01 )
  116.                 begin
  117.                         regnum[7:0] <= { sdo, regnum[7:1] };
  118.                 end
  119.         end
  120.  
  121.  
  122.         // send data to avr
  123.         //
  124.         always @*
  125.         begin
  126.                 if( sel_waitreg )
  127.                         data_in = wait_write; // TODO: add here selection of different input registers
  128.                 else if( sel_gluadr )
  129.                         data_in = gluclock_addr;
  130.                 else data_in = 8'hFF;
  131.         end
  132.         //
  133.         always @(posedge fclk)
  134.         begin
  135.                 if( scs_n_01 || scs_n_10 ) // both edges
  136.                 begin
  137.                         shift_out <= scs_n ? status_in : data_in;
  138.                 end
  139.                 else if( sck_01 )
  140.                 begin
  141.                         shift_out[7:0] <= { 1'b0, shift_out[7:1] };
  142.                 end
  143.         end
  144.         //
  145.         assign spidi = shift_out[0];
  146.  
  147.  
  148.         // reg number decoding
  149.         //
  150.         assign sel_kbdreg = ( (regnum[7:4]==4'h1) && !regnum[0] ); // $10
  151.         assign sel_kbdstb = ( (regnum[7:4]==4'h1) &&  regnum[0] ); // $11
  152.         //
  153.         assign sel_musxcr = ( (regnum[7:4]==4'h2) && !regnum[1] && !regnum[0] ); // $20
  154.         assign sel_musycr = ( (regnum[7:4]==4'h2) && !regnum[1] &&  regnum[0] ); // $21
  155.         assign sel_musbtn = ( (regnum[7:4]==4'h2) &&  regnum[1] && !regnum[0] ); // $22
  156.         assign sel_kj     = ( (regnum[7:4]==4'h2) &&  regnum[1] &&  regnum[0] ); // $23
  157.         //
  158.         assign sel_rstreg = ( (regnum[7:4]==4'h3) ) ; // $30
  159.         //
  160.         assign sel_waitreg = ( (regnum[7:4]==4'h4) && !regnum[0] ); // $40
  161.         assign sel_gluadr  = ( (regnum[7:4]==4'h4) &&  regnum[0] ); // $41
  162.         //
  163.         assign sel_cfg0 = (regnum[7:4]==4'h5); // $50
  164.  
  165.  
  166.         // registers data-in
  167.         //
  168.         always @(posedge fclk)
  169.         begin
  170.                 if( !scs_n && sel_kbdreg && sck_01 )
  171.                         kbd_reg[39:0] <= { sdo, kbd_reg[39:1] };
  172.  
  173.                 if( !scs_n && (sel_musxcr || sel_musycr || sel_musbtn || sel_kj) && sck_01 )
  174.             mouse_buf[7:0] <= { sdo, mouse_buf[7:1] };
  175.  
  176.                 if( !scs_n && sel_rstreg && sck_01 )
  177.                         rst_reg[7:0] <= { sdo, rst_reg[7:1] };
  178.  
  179.                 if( !scs_n && sel_waitreg && sck_01 )
  180.                         wait_reg[7:0] <= { sdo, wait_reg[7:1] };
  181.  
  182.                 if( !scs_n && sel_cfg0 && sck_01 )
  183.                         cfg0_reg_in[7:0] <= { sdo, cfg0_reg_in[7:1] };
  184.  
  185.                 if( scs_n_01 && sel_cfg0 )
  186.                         cfg0_reg_out <= cfg0_reg_in;
  187.         end
  188.  
  189.  
  190.         // output data
  191.         assign kbd_out = kbd_reg;
  192.         assign kbd_stb = sel_kbdstb && scs_n_01;
  193.  
  194.         assign mus_out    = mouse_buf;
  195.         assign mus_xstb   = sel_musxcr && scs_n_01;
  196.         assign mus_ystb   = sel_musycr && scs_n_01;
  197.         assign mus_btnstb = sel_musbtn && scs_n_01;
  198.         assign kj_stb     = sel_kj     && scs_n_01;
  199.  
  200.         assign genrst = sel_rstreg && scs_n_01;
  201.         assign rstrom = rst_reg[5:4];
  202.  
  203.         assign wait_read = wait_reg;
  204.         assign wait_end = sel_waitreg && scs_n_01;
  205.  
  206.         assign config0 = cfg0_reg_out;
  207.  
  208. endmodule
  209.  
  210.