- `include "../include/tune.v" 
-   
- // PentEvo project (c) NedoPC 2008-2011 
- // 
- // DRAM arbiter. Shares DRAM between processor and video data fetcher 
- // 
-   
-   
-   
-   
-   
- // 14.06.2011: 
- // removed cpu_stall and cpu_waitcyc. 
- // changed cpu_strobe behavior (only strobes read data arrival now). 
- // added cpu_next signal (shows whether next DRAM cycle CAN be grabbed by CPU) 
- // 
- // Now it is a REQUIREMENT for 'go' signal only starting and ending on 
- // beginning of DRAM cycle (i.e. right after 'cend' strobe). 
- // 
-   
-   
- // 13.06.2011: 
- // ╧Ёшф╕Єё  яюЄЁхсютрЄ№, ўЄюс go єёЄрэртыштрыё  ёЁрчє яюёых cend (є ьхэ  [lvd] ¤Єю Єръ). 
- // ¤Єю фы  Єюую, ўЄюс√ яЁюЎхёёюЁ эр 14ьуЎ ьюу чрЁрэхх ш т ы■сющ ьюьхэЄ чэрЄ№, эр 
- // ёъюы№ъю чртхщЄшЄ№ё . ┬ьхёЄю cpu_ack ттхфхь фЁєующ ёшуэры, ъюЄюЁ√щ т Єхўхэшх тёхую 
- // фЁрь-Ўшъыр сєфхЄ яюърч√трЄ№, ўхщ ьюцхЄ с√Є№ ёыхфє■∙шщ Ўшъы - яЁюЎхёёюЁр шыш Єюы№ъю 
- // тшфхю. ╧ю ёєЄш ¤Єю ш сєфхЄ Єръцх cpu_ack, эю трышфэ√щ т ьюьхэЄ cpu_req (Є.х. 
- // т ьюьхэЄ cend) ш Ёрэхх. 
-   
- // 12.06.2011: 
- // яЁюсыхьр: хёыш Ўяє яЁюёшЄ Ўшъы ўЄхэш , р хую фрЄ№ эх ьюуєЄ, 
- // Єю юэ фюыцхэ фхЁцрЄ№ cpu_req. юфэръю, ёэ Є№ юэ хую ьюцхЄ 
- // Єюы№ъю яю cpu_strobe, яЁш ¤Єюь Єръцх юЄяЁртшЄё  х∙х юфшэ 
- // чряЁюё ўЄхэш !!! 
- // Ёх°хэшх: фюсртшЄ№ ёшуэры cpu_ack, яю ъюЄюЁюьє єчэр╕Єё , ўЄю 
- // рЁсшЄЁ чюїртры чряЁюё (чряшёш шыш ўЄхэш ), ъюЄюЁ√щ сєфхЄ 
- // ёютярфрЄ№ ё э√эх°эшь cpu_strobe эр чряшёш (cbeg), р сєфє∙шщ 
- // cpu_strobe ёфхырЄ№ Єюы№ъю ъръ ёЄЁюс фрээ√ї эр чюїртрээюь 
- // чряЁюёх ўЄхэ . 
- // ¤Єю, тючьюцэю, яючтюышЄ єфрышЄ№ тё ъшх cpu_waitcyc... 
-   
-   
- // Arbitration is made on full 8-cycle access blocks. Each cycle is defined by dram.v and consists of 4 fpga clocks. 
- // During each access block, there can be either no videodata access, 1 videodata access, 2, 4 or full 8 accesses. 
- // All spare cycles can be used by processor. If nobody uses memory in the given cycle, refresh cycle is performed 
- // 
- // In each access block, videodata accesses are spreaded all over the block so that processor receives cycle 
- // as fast as possible, until there is absolute need to fetch remaining video data 
- // 
- // Examples: 
- // 
- // |                 access block                  | 4 video accesses during block, no processor accesses. video accesses are done 
- // | vid | vid | vid | vid | ref | ref | ref | ref | as soon as possible, spare cycles are refresh ones 
- // 
- // |                 access block                  | 4 video accesses during block, processor requests access every other cycle 
- // | vid | prc | vid | prc | vid | prc | vid | prc | 
- // 
- // |                 access block                  | 4 video accesses, processor begins requesting cycles continously from second one 
- // | vid | prc | prc | prc | prc | vid | vid | vid | so it is given cycles while there is such possibility. after that processor 
- //                                                   can't access mem until the end of access block and stalls 
- // 
- // |                 access block                  | 8 video accesses, processor stalls, if it is requesting cycles 
- // | vid | vid | vid | vid | vid | vid | vid | vid | 
- // 
- // |                 access block                  | 2 video accesses, single processor request, other cycles are refresh ones 
- // | vid | vid | ref | ref | cpu | ref | ref | ref | 
- // 
- // |                 access block                  | 4 video accesses, single processor request, other cycles are refresh ones 
- // | vid | vid | cpu | vid | vid | ref | ref | ref | 
- // 
- // access block begins at any dram cycle, then blocks go back-to-back 
- // 
- // key signals are go and cpu_req, sampled at the end of each dram cycle. Must be set to the module 
- // one clock cycle earlier the clock of the beginning current dram cycle 
-   
- module arbiter( 
-   
-         input clk, 
-         input rst_n, 
-   
-         // dram.v interface 
-         output     [20:0] dram_addr,   // address for dram access 
-         output reg        dram_req,    // dram request 
-         output reg        dram_rnw,    // Read-NotWrite 
-         input             dram_cbeg,   // cycle begin 
-         input             dram_rrdy,   // read data ready (coincides with cend) 
-         output      [1:0] dram_bsel,   // positive bytes select: bsel[1] for wrdata[15:8], bsel[0] for wrdata[7:0] 
-         input      [15:0] dram_rddata, // data just read 
-         output     [15:0] dram_wrdata, // data to be written 
-   
-   
-         output reg cend,      // regenerates this signal: end of DRAM cycle. cend is one-cycle positive pulse just before cbeg pulse 
-         output reg pre_cend,  // one clock earlier cend 
-         output reg post_cbeg, // one more earlier 
-   
-   
-         input go, // start video access blocks 
-   
-         input [1:0] bw, // required bandwidth: 3'b00 - 1 video cycle per block 
-                         //                     3'b01 - 2 video accesses 
-                         //                     3'b10 - 4 video accesses 
-                         //                     3'b11 - 8 video accesses (stall of CPU) 
-   
-         input  [20:0] video_addr,   // during access block, only when video_strobe==1 
-         output [15:0] video_data,   // read video data which is valid only during video_strobe==1 because video_data 
-                                     // is just wires to the dram.v's rddata signals 
-         output reg    video_strobe, // positive one-cycle strobe as soon as there is next video_data available. 
-                                     // if there is video_strobe, it coincides with cend signal 
-         output reg    video_next,   // on this signal you can change video_addr; it is one clock leading the video_strobe 
-   
-   
-   
-         input  wire        cpu_req, 
-         input  wire        cpu_rnw, 
-         input  wire [20:0] cpu_addr, 
-         input  wire [ 7:0] cpu_wrdata, 
-         input  wire        cpu_wrbsel, 
-   
-         output wire [15:0] cpu_rddata, 
-         output reg         cpu_next, 
-         output reg         cpu_strobe 
- ); 
-   
-         wire cbeg; 
-   
-         reg [1:0] cctr; // DRAM cycle counter: 0 when cbeg is 1, then 1,2,3,0, etc... 
-   
-   
-         reg stall; 
-         reg cpu_rnw_r; 
-   
-         reg [2:0] blk_rem;  // remaining accesses in a block (7..0) 
-         reg [2:0] blk_nrem; // remaining for the next dram cycle 
-   
-         reg [2:0] vid_rem;  // remaining video accesses in block (4..0) 
-         reg [2:0] vid_nrem; // for rhe next cycle 
-   
-   
-         wire [2:0] vidmax; // max number of video cycles in a block, depends on bw input 
-   
-   
-   
-         localparam CYC_VIDEO = 2'b00; // do             there 
-         localparam CYC_CPU   = 2'b01; //   not     since     are   dependencies 
-         localparam CYC_FREE  = 2'b10; //      alter             bit 
-   
-         reg [1:0] curr_cycle; // type of the cycle in progress 
-         reg [1:0] next_cycle; // type of the next cycle 
-   
-   
-   
-   
-   
-         initial // simulation only! 
-         begin 
-                 curr_cycle = CYC_FREE; 
-                 blk_rem = 0; 
-                 vid_rem = 0; 
-         end 
-   
-   
-   
-   
-         assign cbeg = dram_cbeg; // just alias 
-   
-         // make cycle strobe signals 
-         always @(posedge clk) 
-         begin 
-                 post_cbeg <= cbeg; 
-                 pre_cend  <= post_cbeg; 
-                 cend      <= pre_cend; 
-         end 
-   
-   
-         // track blk_rem counter: how many cycles left to the end of block (7..0) 
-         always @(posedge clk) if( cend ) 
-         begin 
-                 blk_rem <= blk_nrem; 
-   
-                 if( (blk_rem==3'd0) ) 
-                         stall <= (bw==2'd3) & go; 
-         end 
-   
-         always @* 
-         begin 
-                 if( (blk_rem==3'd0) && go ) 
-                         blk_nrem = 7; 
-                 else 
-                         blk_nrem = (blk_rem==0) ? 3'd0 : (blk_rem-3'd1); 
-         end 
-   
-   
-   
-         // track vid_rem counter 
-         assign vidmax = (3'b001) << bw; // 1,2,4 or 8 - just to know how many cycles to perform 
-   
-         always @(posedge clk) if( cend ) 
-         begin 
-                 vid_rem <= vid_nrem; 
-         end 
-   
-         always @* 
-         begin 
-                 if( go && (blk_rem==3'd0) ) 
-                         vid_nrem = cpu_req ? vidmax : (vidmax-3'd1); 
-                 else 
-                         if( next_cycle==CYC_VIDEO ) 
-                                 vid_nrem = (vid_rem==3'd0) ? 3'd0 : (vid_rem-3'd1); 
-                         else 
-                                 vid_nrem = vid_rem; 
-         end 
-   
-   
-   
-   
-         // next cycle decision 
-         always @* 
-         begin 
-                 if( blk_rem==3'd0 ) 
-                 begin 
-                         if( go ) 
-                         begin 
-                                 if( bw==2'b11 ) 
-                                 begin 
-                                         cpu_next = 1'b0; 
-   
-                                         next_cycle = CYC_VIDEO; 
-                                 end 
-                                 else 
-                                 begin 
-                                         cpu_next = 1'b1; 
-   
-                                         if( cpu_req ) 
-                                                 next_cycle = CYC_CPU; 
-                                         else 
-                                                 next_cycle = CYC_VIDEO; 
-                                 end 
-                         end 
-                         else // !go 
-                         begin 
-                                 cpu_next = 1'b1; 
-   
-                                 if( cpu_req ) 
-                                         next_cycle = CYC_CPU; 
-                                 else 
-                                         next_cycle = CYC_FREE; 
-                         end 
-                 end 
-                 else // blk_rem!=3'd0 
-                 begin 
-                         if( stall ) 
-                         begin 
-                                 cpu_next = 1'b0; 
-   
-                                 next_cycle = CYC_VIDEO; 
-                         end 
-                         else 
-                         begin 
-                                 if( vid_rem==blk_rem ) 
-                                 begin 
-                                         cpu_next = 1'b0; 
-          
-                                         next_cycle = CYC_VIDEO; 
-                                 end 
-                                 else 
-                                 begin 
-                                         cpu_next = 1'b1; 
-          
-                                         if( cpu_req ) 
-                                                 next_cycle = CYC_CPU; 
-                                         else 
-                                                 if( vid_rem==3'd0 ) 
-                                                         next_cycle = CYC_FREE; 
-                                                 else 
-                                                         next_cycle = CYC_VIDEO; 
-                                 end 
-                         end 
-                 end 
-         end 
-   
-   
-   
-   
-         // just current cycle register 
-         always @(posedge clk) if( cend ) 
-         begin 
-                 curr_cycle <= next_cycle; 
-         end 
-   
-   
-   
-   
-         // route required data/etc. to and from the dram.v 
-   
-         assign dram_wrdata[15:0] = { cpu_wrdata[7:0], cpu_wrdata[7:0] }; 
-         assign dram_bsel[1:0] = { ~cpu_wrbsel, cpu_wrbsel }; 
-   
-         assign dram_addr = next_cycle[0] ? cpu_addr : video_addr; 
-   
-         assign cpu_rddata = dram_rddata; 
-         assign video_data = dram_rddata; 
-   
-         always @* 
-         begin 
-                 if( next_cycle[1] ) // CYC_FREE 
-                 begin 
-                         dram_req = 1'b0; 
-                         dram_rnw = 1'b1; 
-                 end 
-                 else // CYC_CPU or CYC_VIDEO 
-                 begin 
-                         dram_req = 1'b1; 
-                         if( next_cycle[0] ) // CYC_CPU 
-                                 dram_rnw = cpu_rnw; 
-                         else // CYC_VIDEO 
-                                 dram_rnw = 1'b1; 
-                 end 
-         end 
-   
-   
-   
-         // generation of read strobes: for video and cpu 
-   
-   
-         always @(posedge clk) 
-         if( cend ) 
-                 cpu_rnw_r <= cpu_rnw; 
-   
-   
-         always @(posedge clk) 
-         begin 
-                 if( (curr_cycle==CYC_CPU) && cpu_rnw_r && pre_cend ) 
-                         cpu_strobe <= 1'b1; 
-                 else 
-                         cpu_strobe <= 1'b0; 
-         end 
-   
-   
-         always @(posedge clk) 
-         begin 
-                 if( (curr_cycle==CYC_VIDEO) && pre_cend ) 
-                         video_strobe <= 1'b1; 
-                 else 
-                         video_strobe <= 1'b0; 
-   
-                 if( (curr_cycle==CYC_VIDEO) && post_cbeg ) 
-                         video_next <= 1'b1; 
-                 else 
-                         video_next <= 1'b0; 
-         end 
-   
-   
-   
- endmodule 
-   
-