Subversion Repositories tsfmpro

Rev

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

  1. // TurboFMpro project
  2. // (C) 2018 NedoPC
  3.  
  4. // bus control:
  5. // data buffering, async signals filtering, access cycles forming
  6.  
  7. // ym2203 info:
  8. //  address setup: 10ns (min 1Tc)
  9. //  cs/rd/wr pulse width: 250ns (min 14Tc)
  10. // total: 15Tc
  11. //  read time: 250ns -- read will only work at Z80@7MHz or slower!
  12. // ymA0=0 -- wr addr/read status
  13. // ymA0=1 -- wr data/read data
  14. //
  15. // saa1099 info:
  16. //  address setup: 0ns
  17. //  wr pulse width: 100ns (min 6Tc)
  18. //  cs to wr min: 50ns (min 3Tc)
  19. // total: 9Tc
  20. // saaA0=0 -- data, saaA0=1 -- address
  21. //
  22. // Z80 @ 14MHz:
  23. //  access width: 178ns
  24. //  min repetition time: 785ns
  25. //
  26. // 56MHz period: 17.8ns
  27. //
  28. //
  29. // time plan:
  30. // fclk:          __/``\__/``\__/``\__/``\__/``\__/``\__/``\__/``\__/``\__/``\__/``\__/``\__/``\__/``\__/``\
  31. // async access:  ___/````````
  32. // resync1:       _________/```````
  33. // resync2:       _______________/``````
  34. // filt:          _____________________/`````````````
  35. // output cs/wr:  ___________________________/````````````
  36. //
  37. // deltaT:           |<--------------------->| = 4Tc = 71ns -> less than Z80@14MHz /IORQ length
  38. //
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45. module bus
  46. (
  47.         input  wire clk,
  48.         input  wire rst_n,
  49.  
  50.         input  wire        aybc1,
  51.         input  wire        aybc2,
  52.         input  wire        aybdir,
  53.         input  wire        aya8,
  54.         input  wire        aya9_n,
  55.  
  56.         // data busses
  57.         inout  wire [7:0]  ayd, // INPUT DATA BUS!!! (from host)
  58.         inout  wire [7:0]  d,   // internal data bus (to ym2203/sa1099)
  59.  
  60.         // write strobe for Fx config port
  61.         output wire wr_port,
  62.        
  63.         // strobes/addr for ym2203
  64.         output reg  yma0,
  65.         output reg  ymcs0_n,
  66.         output reg  ymcs1_n,
  67.         output reg  ymrd_n,
  68.         output reg  ymwr_n,
  69.  
  70.         // strobes/addr for saa1099
  71.         output reg  saaa0,
  72.         output reg  saacs_n,
  73.         output reg  saawr_n,
  74.  
  75.  
  76.  
  77.         // config inputs
  78.         input  wire ym_sel,  // 0 -- YM #0 selected, 1 -- YM #1
  79.         input  wire ym_stat, // 1 -- read YM status reg
  80.         input  wire saa_sel  // 1 -- saa selected, 0 -- YM selected
  81. );
  82.  
  83.         wire [7:0] decode_wraddr;
  84.  
  85.         wire async_wrport,
  86.              async_wraddr,
  87.              async_wrdata,
  88.              async_rddata;
  89.  
  90.         reg  [2:0] wrport;
  91.         reg  [2:0] wraddr;
  92.         reg  [2:0] wrdata;
  93.         reg  [2:0] rddata;
  94.  
  95.         reg wrport_on,
  96.             wraddr_on,
  97.             wrdata_on,
  98.             rddata_on;
  99.  
  100.         wire wraddr_beg,
  101.              wrdata_beg,
  102.              rddata_beg;
  103.  
  104.         wire wrport_beg;
  105.  
  106.  
  107.         reg [7:0] write_latch;
  108.         reg [7:0] read_latch;
  109.  
  110.  
  111.  
  112.         reg [3:0] saa_ctr = 4'hF; // for simulation
  113.  
  114.         reg [3:0] ym_ctr  = 4'hF; // for simulation
  115.  
  116.  
  117.  
  118.  
  119.         // control signals decoding
  120.         //     YM/AY                         YM2203                    
  121.         //  BDIR  BC2  BC1  A8  _A9      _WR  _RD  A0                  
  122.         //   0     0    0   1    0         inactive                    
  123.         //   0     0    1   1    0        0    1   0   (write address)  
  124.         //   0     1    0   1    0         inactive                    
  125.         //   0     1    1   1    0        1    0   1   (read register)  
  126.         //   1     0    0   1    0        0    1   0   (write address)  
  127.         //   1     0    1   1    0         inactive                    
  128.         //   1     1    0   1    0        0    1   1   (write register)
  129.         //   1     1    1   1    0        0    1   0   (write address)  
  130.         //          other                  inactive                    
  131.         //
  132.         assign decode_wraddr[3'b000] = 1'b0;
  133.         assign decode_wraddr[3'b001] = 1'b1;
  134.         assign decode_wraddr[3'b010] = 1'b0;
  135.         assign decode_wraddr[3'b011] = 1'b0;
  136.         assign decode_wraddr[3'b100] = 1'b1;
  137.         assign decode_wraddr[3'b101] = 1'b0;
  138.         assign decode_wraddr[3'b110] = 1'b0;
  139.         assign decode_wraddr[3'b111] = 1'b1;
  140.         //
  141.         assign async_wrport = decode_wraddr[{aybdir,aybc2,aybc1}] && aya8 && !aya9_n && ayd[7:4]==4'hF;
  142.         assign async_wraddr = decode_wraddr[{aybdir,aybc2,aybc1}] && aya8 && !aya9_n && ayd[7:4]!=4'hF;
  143.         assign async_wrdata =  aybdir &&  aybc2 && !aybc1         && aya8 && !aya9_n;
  144.         assign async_rddata = !aybdir &&  aybc2 &&  aybc1         && aya8 && !aya9_n;
  145.  
  146.  
  147.  
  148.         // resync
  149.         always @(posedge clk)
  150.         begin
  151.                 wrport[2:0] <= { wrport[1:0], async_wrport };
  152.                 wraddr[2:0] <= { wraddr[1:0], async_wraddr };
  153.                 wrdata[2:0] <= { wrdata[1:0], async_wrdata };
  154.                 rddata[2:0] <= { rddata[1:0], async_rddata };
  155.         end
  156.  
  157.         // filtering
  158.         always @(posedge clk, negedge rst_n)
  159.         if( !rst_n )
  160.                 wrport_on <= 1'b0;
  161.         else if( !wrport_on && wrport[2:1]==2'b11 )
  162.                 wrport_on <= 1'b1;
  163.         else if(  wrport_on && wrport[2:1]==2'b00 )
  164.                 wrport_on <= 1'b0;
  165.         //
  166.         always @(posedge clk, negedge rst_n)
  167.         if( !rst_n )
  168.                 wraddr_on <= 1'b0;
  169.         else if( !wraddr_on && wraddr[2:1]==2'b11 )
  170.                 wraddr_on <= 1'b1;
  171.         else if(  wraddr_on && wraddr[2:1]==2'b00 )
  172.                 wraddr_on <= 1'b0;
  173.         //
  174.         always @(posedge clk, negedge rst_n)
  175.         if( !rst_n )
  176.                 wrdata_on <= 1'b0;
  177.         else if( !wrdata_on && wrdata[2:1]==2'b11 )
  178.                 wrdata_on <= 1'b1;
  179.         else if(  wrdata_on && wrdata[2:1]==2'b00 )
  180.                 wrdata_on <= 1'b0;
  181.         //
  182.         always @(posedge clk, negedge rst_n)
  183.         if( !rst_n )
  184.                 rddata_on <= 1'b0;
  185.         else if( !rddata_on && rddata[2:1]==2'b11 )
  186.                 rddata_on <= 1'b1;
  187.         else if(  rddata_on && rddata[2:1]==2'b00 )
  188.                 rddata_on <= 1'b0;
  189.  
  190.         // start strobes
  191.         assign wrport_beg = !wrport_on && wrport[2:1]==2'b11;
  192.         assign wraddr_beg = !wraddr_on && wraddr[2:1]==2'b11;
  193.         assign wrdata_beg = !wrdata_on && wrdata[2:1]==2'b11;
  194.         assign rddata_beg = !rddata_on && rddata[2:1]==2'b11;
  195.  
  196.  
  197.  
  198.  
  199.         // saa control
  200.         always @(posedge clk)
  201.         if( saa_sel && (wraddr_beg || wrdata_beg) )
  202.                 saa_ctr <= 4'd0;
  203.         else if( !saa_ctr[3] )
  204.                 saa_ctr <= saa_ctr + 4'd1;
  205.         //
  206.         always @(posedge clk)
  207.         if( wraddr_beg || wrdata_beg )
  208.                 saaa0 <= wraddr_beg;
  209.         //
  210.         always @(posedge clk)
  211.         if( saa_sel && (wraddr_beg || wrdata_beg) )
  212.                 saacs_n <= 1'b0;
  213.         else if( saa_ctr[3] )
  214.                 saacs_n <= 1'b1;
  215.         //
  216.         always @(posedge clk)
  217.         if( saa_ctr[3] )
  218.                 saawr_n <= 1'b1;
  219.         else if( saa_ctr[1] )
  220.                 saawr_n <= 1'b0;
  221.  
  222.  
  223.  
  224.  
  225.  
  226.         // ym control
  227.         always @(posedge clk)
  228.         if( !saa_sel && (wraddr_beg || wrdata_beg || rddata_beg) )
  229.                 ym_ctr[3:0] <= 4'd0;
  230.         else if( !(&ym_ctr[3:1]) /*ym_ctr[3:0]<4'd14*/ )
  231.                 ym_ctr[3:0] <= ym_ctr[3:0] + 4'd1;
  232.         //
  233.         always @(posedge clk)
  234.         if( wraddr_beg || wrdata_beg || rddata_beg )
  235.                 yma0 <= wrdata_beg || (rddata_beg && !ym_stat);
  236.         //
  237.         always @(posedge clk)
  238.         if( &ym_ctr[3:1] /*ym_ctr[3:0]==4'd14*/ )
  239.         begin
  240.                 ymcs0_n <= 1'b1;
  241.                 ymcs1_n <= 1'b1;
  242.                 ymrd_n  <= 1'b1;
  243.                 ymwr_n  <= 1'b1;
  244.         end
  245.         else if( !ym_ctr[3:0] ) // 1 clock after counter start
  246.         begin
  247.                 ymcs0_n <=  ym_sel;
  248.                 ymcs1_n <= !ym_sel;
  249.                 //
  250.                 ymrd_n  <= !rddata_on;
  251.                 ymwr_n  <= !(wraddr_on || wrdata_on);
  252.         end
  253.  
  254.  
  255.         // config port write strobe
  256.         assign wr_port = wrport_beg;
  257.  
  258.  
  259.  
  260.  
  261.  
  262.         // write latch
  263.         always @(posedge clk)
  264.         if( wraddr_beg || wrdata_beg )
  265.                 write_latch <= ayd;
  266.        
  267.         // read latch
  268.         always @*
  269.         if( !ymrd_n )
  270.                 read_latch = d;
  271.  
  272.  
  273.  
  274.         // busses intercommutation
  275.         assign ayd = async_rddata ? read_latch : 8'hZZ;
  276.         //
  277.         assign d = (!saawr_n || !ymwr_n) ? write_latch : 8'hZZ;
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284. endmodule
  285.  
  286.