Blame | Last modification | View Log | Download | RSS feed
`include "../include/tune.v"// PentEvo project (c) NedoPC 2008-2009//// fetches and outs video data//// currently only 256x192 standard zx and p16c modes supported////module fetch(input clk,input cend,input line_start,input vpix, // hpix not needed! fetch.v has its own count from line_start to the hpix window openinginput int_start, // used as initializer for countersinput [1:0] vmode, // 2'b00 - standard ZX, 2'b01 - hardware multicolor, 2'b1x - p16cinput screen, // screen 0 (pg5) or screen 1 (pg7)// controlling data fetch (go to dram/arbiter.v)output reg [20:0] video_addr,input [15:0] video_data,input video_strobe,input video_next,output [1:0] bw,output reg go,output [5:0] pixel);localparam START_FETCH = 6'd36;// begin data fetching 16 cycles before actual start if hpix, (52-16)=36 cycles after line_start.reg [15:0] fbuf [0:3]; // reading memory datareg [7:0] shift [0:7]; // shifting out pixel datareg [7:0] vcnt; // vertical line counter (0-191)reg [3:0] hcnt; // horizontal word counter (0-15)reg [1:0] dcnt; // displacement or pix/attr counterreg [1:0] ddcnt; // dcnt saved for data receptionreg [5:0] scnt; // start-fetch counterwire wordsync; // synchronize words output: every 16th dram cyclereg [3:0] wcnt; // word (16 cycles) counterreg [4:0] fcnt; // fetches counter; counts from 0 to 16 as each 16cycles passes, at the end stops fetching by issuing go_endwire go_start,go_end;reg [3:0] pixnumber; // pixel number; 0 - leftmost, 15 - rightmostwire flash;reg [4:0] flashctr;reg [3:0] zxcolor;initialbegingo = 1'b0;vcnt = 8'd0;hcnt = 4'd0;dcnt = 2'd0;ddcnt = 2'd0;scnt = 6'd0;wcnt = 4'd0;fcnt = 5'd0;pixnumber = 4'd0;flashctr = 5'd0;end// flash generatoralways @(posedge clk) if( int_start )beginflashctr <= flashctr + 5'd1;endassign flash = flashctr[4];// fetchmode generatorassign bw = vmode[1] ? 2'b01 : 2'b00;// vertical counteralways @(posedge clk)beginif( int_start )vcnt <= 8'hFF;else if( line_start && vpix ) // line-start will also happen in the first pixel line, so we initialize counter with 0xFFvcnt <= vcnt + 8'h01;end// start-fetch counteralways @(posedge clk) if( cend )beginif( line_start && vpix )scnt <= (START_FETCH - 6'd2);else if( scnt!=6'd0)scnt <= scnt - 6'd1;endassign go_start = (scnt==6'd1) & cend; // start go signal 1 cycle before actual data will begin to fetch//wordsync generation and synchronizingalways @(posedge clk) if( cend )beginif( go_start )wcnt <= 4'd0;elsewcnt <= wcnt + 4'd1;endassign wordsync = (wcnt==4'd1) & cend;// fetch counteralways @(posedge clk)beginif( go_start )fcnt <= 5'd0;else if( wordsync && (~fcnt[4]) )fcnt <= fcnt + 5'd1;endassign go_end = fcnt[4] & (wcnt==4'd15) & cend;// goalways @(posedge clk)if( go_start )go <= 1'b1;else if( go_end )go <= 1'b0;// horizontal address counters: init and incrementalways @(posedge clk)beginif( line_start ) // initialize countersbeginhcnt <= 4'd0;dcnt <= 2'd0;endelse if( video_next )beginddcnt <= dcnt;dcnt <= dcnt + 2'd1;if( !vmode[1] ) // normal ZX standardbeginif( dcnt[0] )hcnt <= hcnt + 4'd1;endelse // vmode[1] - p16c modebeginif( dcnt==2'd3 )hcnt <= hcnt + 4'd1;endendend// store fetched dataalways @(posedge clk) if( video_strobe )beginif( !vmode[1] ) // ZX modefbuf[{1'b0,ddcnt[0]}] <= video_data;else // p16c modefbuf[ddcnt[1:0]] <= video_data;end// sequence video addressesalways @*beginvideo_addr[20:14] = { 6'b000001,screen }; // common part of addressif( !vmode[1] ) // ZX modebeginif( !dcnt[0] ) // pixel addrvideo_addr[13:0] = { 2'b10, vcnt[7:6], vcnt[2:0], vcnt[5:3], hcnt[3:0] };else // attr addrbeginif( !vmode[0] ) // normal ZXvideo_addr[13:0] = { 5'b10110, vcnt[7:3], hcnt[3:0] };else // hardware multicolorvideo_addr[13:0] = { 2'b11, vcnt[7:6], vcnt[2:0], vcnt[5:3], hcnt[3:0] };endendelse // p16c modebeginvideo_addr[13:0] = { dcnt[0], dcnt[1], vcnt[7:6], vcnt[2:0], vcnt[5:3], hcnt[3:0] };endend// pass read data to pixel enginealways @(posedge clk) if( wordsync )beginshift[0] <= fbuf[0][15:8];shift[1] <= fbuf[0][7:0];shift[2] <= fbuf[1][15:8];shift[3] <= fbuf[1][7:0];shift[4] <= fbuf[2][15:8];shift[5] <= fbuf[2][7:0];shift[6] <= fbuf[3][15:8];shift[7] <= fbuf[3][7:0];end// count pixels to be outalways @(posedge clk) if( cend )if( wordsync )pixnumber <= 4'd0;elsepixnumber <= pixnumber + 4'd1;// out pixelsreg [7:0] pixbyte,attrbyte;reg [3:0] pix0,pix1;always @*beginattrbyte = shift[ { 2'b01, pixnumber[3] } ][7:0];pix0 = { attrbyte[6],attrbyte[5:3] };pix1 = { attrbyte[6],attrbyte[2:0] };if( !vmode[1] ) // ZX modebegin// attribute is taken// pixelspixbyte = shift[ { 2'b00, pixnumber[3] } ][7:0];zxcolor = ( pixbyte[(~pixnumber[2:0])] ^ (flash & attrbyte[7]) ) ? pix1 : pix0;endelse // p16c modebeginpixbyte = shift[ { pixnumber[2:1], pixnumber[3] } ][7:0];zxcolor = pixnumber[0] ? { pixbyte[7],pixbyte[5:3] } : { pixbyte[6],pixbyte[2:0] };endend// redassign pixel[5:4] = zxcolor[1] ? ( zxcolor[3] ? 2'b11 : 2'b10 ) : 2'b00;// greenassign pixel[3:2] = zxcolor[2] ? ( zxcolor[3] ? 2'b11 : 2'b10 ) : 2'b00;// blueassign pixel[1:0] = zxcolor[0] ? ( zxcolor[3] ? 2'b11 : 2'b10 ) : 2'b00;endmodule