Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

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