Subversion Repositories pentevo

Rev

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

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