Subversion Repositories pentevo

Rev

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

  1. `include "../include/tune.v"
  2.  
  3. // PentEvo project (c) NedoPC 2008-2011
  4. //
  5. // DRAM arbiter. Shares DRAM between processor and video data fetcher
  6. //
  7.  
  8.  
  9.  
  10.  
  11.  
  12. // 14.06.2011:
  13. // removed cpu_stall and cpu_waitcyc.
  14. // changed cpu_strobe behavior (only strobes read data arrival now).
  15. // added cpu_next signal (shows whether next DRAM cycle CAN be grabbed by CPU)
  16. //
  17. // Now it is a REQUIREMENT for 'go' signal only starting and ending on
  18. // beginning of DRAM cycle (i.e. right after 'cend' strobe).
  19. //
  20.  
  21.  
  22. // 13.06.2011:
  23. // ╧Ёшф╕Єё  яюЄЁхсютрЄ№, ўЄюс go єёЄрэртыштрыё  ёЁрчє яюёых cend (є ьхэ  [lvd] ¤Єю Єръ).
  24. // ¤Єю фы  Єюую, ўЄюс√ яЁюЎхёёюЁ эр 14ьуЎ ьюу чрЁрэхх ш т ы■сющ ьюьхэЄ чэрЄ№, эр
  25. // ёъюы№ъю чртхщЄшЄ№ё . ┬ьхёЄю cpu_ack ттхфхь фЁєующ ёшуэры, ъюЄюЁ√щ т Єхўхэшх тёхую
  26. // фЁрь-Ўшъыр сєфхЄ яюърч√трЄ№, ўхщ ьюцхЄ с√Є№ ёыхфє■∙шщ Ўшъы - яЁюЎхёёюЁр шыш Єюы№ъю
  27. // тшфхю. ╧ю ёєЄш ¤Єю ш сєфхЄ Єръцх cpu_ack, эю трышфэ√щ т ьюьхэЄ cpu_req (Є.х.
  28. // т ьюьхэЄ cend) ш Ёрэхх.
  29.  
  30. // 12.06.2011:
  31. // яЁюсыхьр: хёыш Ўяє яЁюёшЄ Ўшъы ўЄхэш , р хую фрЄ№ эх ьюуєЄ,
  32. // Єю юэ фюыцхэ фхЁцрЄ№ cpu_req. юфэръю, ёэ Є№ юэ хую ьюцхЄ
  33. // Єюы№ъю яю cpu_strobe, яЁш ¤Єюь Єръцх юЄяЁртшЄё  х∙х юфшэ
  34. // чряЁюё ўЄхэш !!!
  35. // Ёх°хэшх: фюсртшЄ№ ёшуэры cpu_ack, яю ъюЄюЁюьє єчэр╕Єё , ўЄю
  36. // рЁсшЄЁ чюїртры чряЁюё (чряшёш шыш ўЄхэш ), ъюЄюЁ√щ сєфхЄ
  37. // ёютярфрЄ№ ё э√эх°эшь cpu_strobe эр чряшёш (cbeg), р сєфє∙шщ
  38. // cpu_strobe ёфхырЄ№ Єюы№ъю ъръ ёЄЁюс фрээ√ї эр чюїртрээюь
  39. // чряЁюёх ўЄхэ .
  40. // ¤Єю, тючьюцэю, яючтюышЄ єфрышЄ№ тё ъшх cpu_waitcyc...
  41.  
  42.  
  43. // Arbitration is made on full 8-cycle access blocks. Each cycle is defined by dram.v and consists of 4 fpga clocks.
  44. // During each access block, there can be either no videodata access, 1 videodata access, 2, 4 or full 8 accesses.
  45. // All spare cycles can be used by processor. If nobody uses memory in the given cycle, refresh cycle is performed
  46. //
  47. // In each access block, videodata accesses are spreaded all over the block so that processor receives cycle
  48. // as fast as possible, until there is absolute need to fetch remaining video data
  49. //
  50. // Examples:
  51. //
  52. // |                 access block                  | 4 video accesses during block, no processor accesses. video accesses are done
  53. // | vid | vid | vid | vid | ref | ref | ref | ref | as soon as possible, spare cycles are refresh ones
  54. //
  55. // |                 access block                  | 4 video accesses during block, processor requests access every other cycle
  56. // | vid | prc | vid | prc | vid | prc | vid | prc |
  57. //
  58. // |                 access block                  | 4 video accesses, processor begins requesting cycles continously from second one
  59. // | vid | prc | prc | prc | prc | vid | vid | vid | so it is given cycles while there is such possibility. after that processor
  60. //                                                   can't access mem until the end of access block and stalls
  61. //
  62. // |                 access block                  | 8 video accesses, processor stalls, if it is requesting cycles
  63. // | vid | vid | vid | vid | vid | vid | vid | vid |
  64. //
  65. // |                 access block                  | 2 video accesses, single processor request, other cycles are refresh ones
  66. // | vid | vid | ref | ref | cpu | ref | ref | ref |
  67. //
  68. // |                 access block                  | 4 video accesses, single processor request, other cycles are refresh ones
  69. // | vid | vid | cpu | vid | vid | ref | ref | ref |
  70. //
  71. // access block begins at any dram cycle, then blocks go back-to-back
  72. //
  73. // key signals are go and cpu_req, sampled at the end of each dram cycle. Must be set to the module
  74. // one clock cycle earlier the clock of the beginning current dram cycle
  75.  
  76. module arbiter(
  77.  
  78.         input clk,
  79.         input rst_n,
  80.  
  81.         // dram.v interface
  82.         output     [20:0] dram_addr,   // address for dram access
  83.         output reg        dram_req,    // dram request
  84.         output reg        dram_rnw,    // Read-NotWrite
  85.         input             dram_cbeg,   // cycle begin
  86.         input             dram_rrdy,   // read data ready (coincides with cend)
  87.         output      [1:0] dram_bsel,   // positive bytes select: bsel[1] for wrdata[15:8], bsel[0] for wrdata[7:0]
  88.         input      [15:0] dram_rddata, // data just read
  89.         output     [15:0] dram_wrdata, // data to be written
  90.  
  91.  
  92.         output reg cend,      // regenerates this signal: end of DRAM cycle. cend is one-cycle positive pulse just before cbeg pulse
  93.         output reg pre_cend,  // one clock earlier cend
  94.         output reg post_cbeg, // one more earlier
  95.  
  96.  
  97.         input go, // start video access blocks
  98.  
  99.         input [1:0] bw, // required bandwidth: 3'b00 - 1 video cycle per block
  100.                         //                     3'b01 - 2 video accesses
  101.                         //                     3'b10 - 4 video accesses
  102.                         //                     3'b11 - 8 video accesses (stall of CPU)
  103.  
  104.         input  [20:0] video_addr,   // during access block, only when video_strobe==1
  105.         output [15:0] video_data,   // read video data which is valid only during video_strobe==1 because video_data
  106.                                     // is just wires to the dram.v's rddata signals
  107.         output reg    video_strobe, // positive one-cycle strobe as soon as there is next video_data available.
  108.                                     // if there is video_strobe, it coincides with cend signal
  109.         output reg    video_next,   // on this signal you can change video_addr; it is one clock leading the video_strobe
  110.  
  111.  
  112.  
  113.         input  wire        cpu_req,
  114.         input  wire        cpu_rnw,
  115.         input  wire [20:0] cpu_addr,
  116.         input  wire [ 7:0] cpu_wrdata,
  117.         input  wire        cpu_wrbsel,
  118.  
  119.         output wire [15:0] cpu_rddata,
  120.         output reg         cpu_next,
  121.         output reg         cpu_strobe
  122. );
  123.  
  124.         wire cbeg;
  125.  
  126.         reg [1:0] cctr; // DRAM cycle counter: 0 when cbeg is 1, then 1,2,3,0, etc...
  127.  
  128.  
  129.         reg stall;
  130.         reg cpu_rnw_r;
  131.  
  132.         reg [2:0] blk_rem;  // remaining accesses in a block (7..0)
  133.         reg [2:0] blk_nrem; // remaining for the next dram cycle
  134.  
  135.         reg [2:0] vid_rem;  // remaining video accesses in block (4..0)
  136.         reg [2:0] vid_nrem; // for rhe next cycle
  137.  
  138.  
  139.         wire [2:0] vidmax; // max number of video cycles in a block, depends on bw input
  140.  
  141.  
  142.  
  143.         localparam CYC_VIDEO = 2'b00; // do             there
  144.         localparam CYC_CPU   = 2'b01; //   not     since     are   dependencies
  145.         localparam CYC_FREE  = 2'b10; //      alter             bit
  146.  
  147.         reg [1:0] curr_cycle; // type of the cycle in progress
  148.         reg [1:0] next_cycle; // type of the next cycle
  149.  
  150.  
  151.  
  152.  
  153.  
  154.         initial // simulation only!
  155.         begin
  156.                 curr_cycle = CYC_FREE;
  157.                 blk_rem = 0;
  158.                 vid_rem = 0;
  159.         end
  160.  
  161.  
  162.  
  163.  
  164.         assign cbeg = dram_cbeg; // just alias
  165.  
  166.         // make cycle strobe signals
  167.         always @(posedge clk)
  168.         begin
  169.                 post_cbeg <= cbeg;
  170.                 pre_cend  <= post_cbeg;
  171.                 cend      <= pre_cend;
  172.         end
  173.  
  174.  
  175.         // track blk_rem counter: how many cycles left to the end of block (7..0)
  176.         always @(posedge clk) if( cend )
  177.         begin
  178.                 blk_rem <= blk_nrem;
  179.  
  180.                 if( (blk_rem==3'd0) )
  181.                         stall <= (bw==2'd3) & go;
  182.         end
  183.  
  184.         always @*
  185.         begin
  186.                 if( (blk_rem==3'd0) && go )
  187.                         blk_nrem = 7;
  188.                 else
  189.                         blk_nrem = (blk_rem==0) ? 3'd0 : (blk_rem-3'd1);
  190.         end
  191.  
  192.  
  193.  
  194.         // track vid_rem counter
  195.         assign vidmax = (3'b001) << bw; // 1,2,4 or 8 - just to know how many cycles to perform
  196.  
  197.         always @(posedge clk) if( cend )
  198.         begin
  199.                 vid_rem <= vid_nrem;
  200.         end
  201.  
  202.         always @*
  203.         begin
  204.                 if( go && (blk_rem==3'd0) )
  205.                         vid_nrem = cpu_req ? vidmax : (vidmax-3'd1);
  206.                 else
  207.                         if( next_cycle==CYC_VIDEO )
  208.                                 vid_nrem = (vid_rem==3'd0) ? 3'd0 : (vid_rem-3'd1);
  209.                         else
  210.                                 vid_nrem = vid_rem;
  211.         end
  212.  
  213.  
  214.  
  215.  
  216.         // next cycle decision
  217.         always @*
  218.         begin
  219.                 if( blk_rem==3'd0 )
  220.                 begin
  221.                         if( go )
  222.                         begin
  223.                                 if( bw==2'b11 )
  224.                                 begin
  225.                                         cpu_next = 1'b0;
  226.  
  227.                                         next_cycle = CYC_VIDEO;
  228.                                 end
  229.                                 else
  230.                                 begin
  231.                                         cpu_next = 1'b1;
  232.  
  233.                                         if( cpu_req )
  234.                                                 next_cycle = CYC_CPU;
  235.                                         else
  236.                                                 next_cycle = CYC_VIDEO;
  237.                                 end
  238.                         end
  239.                         else // !go
  240.                         begin
  241.                                 cpu_next = 1'b1;
  242.  
  243.                                 if( cpu_req )
  244.                                         next_cycle = CYC_CPU;
  245.                                 else
  246.                                         next_cycle = CYC_FREE;
  247.                         end
  248.                 end
  249.                 else // blk_rem!=3'd0
  250.                 begin
  251.                         if( stall )
  252.                         begin
  253.                                 cpu_next = 1'b0;
  254.  
  255.                                 next_cycle = CYC_VIDEO;
  256.                         end
  257.                         else
  258.                         begin
  259.                                 if( vid_rem==blk_rem )
  260.                                 begin
  261.                                         cpu_next = 1'b0;
  262.        
  263.                                         next_cycle = CYC_VIDEO;
  264.                                 end
  265.                                 else
  266.                                 begin
  267.                                         cpu_next = 1'b1;
  268.        
  269.                                         if( cpu_req )
  270.                                                 next_cycle = CYC_CPU;
  271.                                         else
  272.                                                 if( vid_rem==3'd0 )
  273.                                                         next_cycle = CYC_FREE;
  274.                                                 else
  275.                                                         next_cycle = CYC_VIDEO;
  276.                                 end
  277.                         end
  278.                 end
  279.         end
  280.  
  281.  
  282.  
  283.  
  284.         // just current cycle register
  285.         always @(posedge clk) if( cend )
  286.         begin
  287.                 curr_cycle <= next_cycle;
  288.         end
  289.  
  290.  
  291.  
  292.  
  293.         // route required data/etc. to and from the dram.v
  294.  
  295.         assign dram_wrdata[15:0] = { cpu_wrdata[7:0], cpu_wrdata[7:0] };
  296.         assign dram_bsel[1:0] = { ~cpu_wrbsel, cpu_wrbsel };
  297.  
  298.         assign dram_addr = next_cycle[0] ? cpu_addr : video_addr;
  299.  
  300.         assign cpu_rddata = dram_rddata;
  301.         assign video_data = dram_rddata;
  302.  
  303.         always @*
  304.         begin
  305.                 if( next_cycle[1] ) // CYC_FREE
  306.                 begin
  307.                         dram_req = 1'b0;
  308.                         dram_rnw = 1'b1;
  309.                 end
  310.                 else // CYC_CPU or CYC_VIDEO
  311.                 begin
  312.                         dram_req = 1'b1;
  313.                         if( next_cycle[0] ) // CYC_CPU
  314.                                 dram_rnw = cpu_rnw;
  315.                         else // CYC_VIDEO
  316.                                 dram_rnw = 1'b1;
  317.                 end
  318.         end
  319.  
  320.  
  321.  
  322.         // generation of read strobes: for video and cpu
  323.  
  324.  
  325.         always @(posedge clk)
  326.         if( cend )
  327.                 cpu_rnw_r <= cpu_rnw;
  328.  
  329.  
  330.         always @(posedge clk)
  331.         begin
  332.                 if( (curr_cycle==CYC_CPU) && cpu_rnw_r && pre_cend )
  333.                         cpu_strobe <= 1'b1;
  334.                 else
  335.                         cpu_strobe <= 1'b0;
  336.         end
  337.  
  338.  
  339.         always @(posedge clk)
  340.         begin
  341.                 if( (curr_cycle==CYC_VIDEO) && pre_cend )
  342.                         video_strobe <= 1'b1;
  343.                 else
  344.                         video_strobe <= 1'b0;
  345.  
  346.                 if( (curr_cycle==CYC_VIDEO) && post_cbeg )
  347.                         video_next <= 1'b1;
  348.                 else
  349.                         video_next <= 1'b0;
  350.         end
  351.  
  352.  
  353.  
  354. endmodule
  355.  
  356.