📄 blitter.v
字号:
// Copyright 2006, 2007 Dennis van Weeren//// This file is part of Minimig//// Minimig is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 3 of the License, or// (at your option) any later version.//// Minimig is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program. If not, see <http://www.gnu.org/licenses/>.//////// This is the Blitter (part of the Agnus chip)//// 14-08-2005 -started coding// 16-08-2005 -done more coding// 19-08-2005 -added C source channel// -added minterm function generator// 21-08-2005 -added proper masking for A channel// -added fill logic and D destination channel// -added normal/line mode control logic// -added address generator but it needs more work to reduce slices// 23-08-2005 -done more work// -added blitsize counter// 24-08-2005 -done some cleanup// 28-08-2005 -redesigned address generator module// -started coding of main state machine// 29-08-2005 -added blitter zero detect// -added logic for special line mode to channel D // 31-08-2005 -blitsize is now decremented automatically during channel D cycle// -added delayed version for lwt called lwtd (needed for pipelining)// 04-09-2005 -added state machine for normal blitter mode // -added data output gate in channel D (needed for integration into Agnus)// 05-09-2005 -fixed bug in bltaddress module// -modified state machine start of blit handling// 06-09-2005 -restored state machine, we should now have a working blitter (normal mode)// -fixed bug, channel B preload didn't work// 14-09-2005 -fixed bug in channel A masking logic when doing 1 word wide blits// (and subsequently found another error in the Hardware Reference Manual)// 18-09-2005 -added sign bit handling for line mode// -redesigned address pointer ALU// -adapted state machine to use new style ALU codes// -added experimental line mode for octant 0,3,4,7// 19-09-2005 -fixed bugs in line mode state machine and it begins to start working..// 20-09-2005 -testing// 25-09-2005 -complete redesign of controller logic// -added new linemode logic for all octants// 27-09-2005 -fixed problem in linemode with dma/channel D modulo: it seems like the real blitter// uses only C modulo for channel C and D during linemode, same for USEC/USED// -sign is taken from bit 15 of pointer A, NOT bit 20! -->fixed// -line drawing in octant 0,3,4,7 now works!// 28-09-2005 -line drawing in octant 1,2,5,6 now works too!// 02-10-2005 -special line draw mode added (single bit per horizontal line)// this completes the blitter (but some bugs may still remain...)// 17-10-2005 -fixed typo in sensitivity list of always block// 22-01-2006 -fixed bug in special line draw mode// 25-01-2006 -added bblck signal // 14-02-2006 -improved bblck table// 07-07-2006 -added some comments// JB:// 2008-03-03 -added BLTCON0L, BLTSIZH and BLTSIZV// 2008-07-08 -clean upmodule blitter( input clk, //bus clock input reset, //reset output reqdma, //blitter requests dma cycle input ackdma, //agnus dma priority logic grants dma cycle output reg bzero, //blitter zero status output bbusy, //blitter busy status output reg bblck, //blitter is blocking cpu, cpu may not access chip bus input horbeam, //least significant bit of horbeam[] output wr, //write (blitter writes to memory) input [15:0] datain, //bus data in output [15:0] dataout, //bus data out input [8:1] regaddressin, //register address inputs output [20:1] addressout //chip address outputs);//register names and adresses parameter BLTCON0 = 9'h040;parameter BLTCON0L = 9'h05A;parameter BLTCON1 = 9'h042;parameter BLTAFWM = 9'h044;parameter BLTALWM = 9'h046;parameter BLTADAT = 9'h074;parameter BLTBDAT = 9'h072;parameter BLTCDAT = 9'h070;parameter BLTSIZE = 9'h058;parameter BLTSIZH = 9'h05E;parameter BLTSIZV = 9'h05C;//channel select codesparameter CHA = 2'b00; //channel Aparameter CHB = 2'b01; //channel Bparameter CHC = 2'b10; //channel Cparameter CHD = 2'b11; //channel D//local signalsreg [15:0]bltcon0; //blitter control register 0reg [15:0]bltcon1; //blitter control register 1reg [15:0]bltafwm; //blitter first word mask for source Areg [15:0]bltalwm; //blitter last word mask for source Areg [15:0]bltadat; //blitter source A preload data registerreg [15:0]bltbdat; //blitter source B preload data registerreg [15:0]bltaold; //blitter source A 'old' datareg [15:0]bltbold; //blitter source B 'old' datareg [15:0]ahold; //A holding registerreg [15:0]bhold; //B holding registerreg [15:0]chold; //C holding registerreg [15:0]dhold; //D holding registerreg [10:0]bltwidth; //blitsize number of words (width)reg [14:0]bltheight; //blitsize number of lines (height)reg [14:0]bltsizv; //register valuereg [4:0]bltstate; //blitter statereg [4:0]bltnext; //blitter next statereg ife; //enable inclusive fill modereg efe; //enable exclusive fill modereg desc; //descending modereg bpa; //bypass preload register for channel Areg bpb; //bypass preload register for channel Breg tmb; //channel B is in texturing modereg sing; //single bit per horizontal line (special line mode)reg enable; //blit cycle enable signalreg [1:0]chs; //channel select(A,B,C,D)wire ame; //instruct address generator to add or subtract modulo (enable)reg ams; //instruct address generator to subtract modulowire ape; //instruct address generator increment or decrement pointer (enable)reg apd; //instruct address generator to decrement pointerwire amb; //instruct address generator to only use modulo B and Cwire sbz; //set blitter zero bitwire incash; //increment ASH (line mode)wire decash; //decrement ASH (line mode)wire rlb; //rotate B holding register to the left (line mode)reg fpl; //first pixel on horizontal line signal used for special line draw mode (SING) reg start; //blitter is started by write to BLTSIZEwire fwt; //first word timewire lwt; //last word timereg bbusyd; //bbusy delayed for channel D modulo handlingreg lwtd; //last word time delayed for channel D modulo handlingwire nml; //no more lines to blit (blit is done), only valid during first word timewire signout; //new accumulator sign calculated by address generator (line mode)reg sign; //current sign of accumulator (line mode)reg plr; //move pointer left or right due to shifter roll over (line mode) //--------------------------------------------------------------------------------------//bltcon0 ASH part//In order to move the $8000 value in BLTADAT around during line mode//the value of ASH can be changed by the main controlling state machinealways @(posedge clk) if(reset) bltcon0[15:12]<=0; else if(enable && incash)//increment (used in line mode) bltcon0[15:12]<=bltcon0[15:12]+{decash,decash,decash,1'b1}; else if(enable && decash)//decrement (used in line mode) bltcon0[15:12]<=bltcon0[15:12]+{decash,decash,decash,1'b1}; else if (regaddressin[8:1]==BLTCON0[8:1])//written from bus (68000 or copper) bltcon0[15:12]<=datain[15:12];//generate plr signal, this is used to detect if we have to increment/decrement channel C/D pointers//during line mode (sort of shifter carry out/roll over out)always @(bltcon0 or bltcon1) if(bltcon1[4])//octant 0,3,4,7 plr=(bltcon0[15]&bltcon0[14]&bltcon0[13]&bltcon0[12]&!bltcon1[2]) | (!bltcon0[15]&!bltcon0[14]&!bltcon0[13]&!bltcon0[12]&bltcon1[2]); else//octant 1,2,5,6 plr=(bltcon0[15]&bltcon0[14]&bltcon0[13]&bltcon0[12]&!bltcon1[3]) | (!bltcon0[15]&!bltcon0[14]&!bltcon0[13]&!bltcon0[12]&bltcon1[3]);//bltcon0 USE and LF partalways @(posedge clk) if(reset) bltcon0[11:8]<=0; else if (regaddressin[8:1]==BLTCON0[8:1]) bltcon0[11:8]<=datain[11:8];//bltcon0 USE and LF partalways @(posedge clk) if(reset) bltcon0[7:0]<=0; else if (regaddressin[8:1]==BLTCON0[8:1] || regaddressin[8:1]==BLTCON0L[8:1]) bltcon0[7:0]<=datain[7:0];//writing of bltcon1 from busalways @(posedge clk) if(reset) bltcon1[15:0]<=0; else if (regaddressin[8:1]==BLTCON1[8:1]) bltcon1[15:0]<=datain[15:0];//--------------------------------------------------------------------------------------//writing of bltafwm from busalways @(posedge clk) if(reset) bltafwm[15:0]<=0; else if (regaddressin[8:1]==BLTAFWM[8:1]) bltafwm[15:0]<=datain[15:0];//writing of bltalwm from busalways @(posedge clk) if(reset) bltalwm[15:0]<=0; else if (regaddressin[8:1]==BLTALWM[8:1]) bltalwm[15:0]<=datain[15:0];//writing of bltadat from bus (preload)always @(posedge clk) if(reset) bltadat[15:0]<=0; else if(regaddressin[8:1]==BLTADAT[8:1]) bltadat[15:0]<=datain[15:0];//writing of bltbdat from bus (preload)always @(posedge clk) if(reset) bltbdat[15:0]<=0; else if(regaddressin[8:1]==BLTBDAT[8:1]) bltbdat[15:0]<=datain[15:0];//--------------------------------------------------------------------------------------//A and B channel processing chain//these channels share a single barrel shifter to save slices//The channel B holding register can be directly loaded by writing from the bus//to BLTBDAT. //local signalsreg [15:0]amux;reg [15:0]amask;reg [15:0]bmux;wire [15:0]newmux;wire [15:0]oldmux;wire [3:0]shmux;wire [15:0]shiftout;//channel A mask selectalways @(bltafwm or bltalwm or fwt or lwt) if(fwt && lwt) amask[15:0]=bltafwm[15:0]&bltalwm[15:0]; else if(fwt) amask[15:0]=bltafwm[15:0]; else if(lwt) amask[15:0]=bltalwm[15:0]; else amask[15:0]=16'b1111111111111111; //channel A source select muxalways @(bltadat or datain or amask or bpa) if(bpa) amux[15:0]=datain[15:0]&amask[15:0]; else amux[15:0]=bltadat[15:0]&amask[15:0];//channel A 'old' registeralways @(posedge clk) if(!bbusy) bltaold[15:0]<=0; else if(enable && (chs[1:0]==CHA[1:0])) bltaold[15:0]<=amux[15:0];//channel A holding registeralways @(posedge clk) if(enable && (chs[1:0]==CHA[1:0])) ahold[15:0]<=shiftout[15:0];//channel B source select muxalways @(bltbdat or datain or bpb or regaddressin) if(bpb || (regaddressin[8:1]==BLTBDAT[8:1])) bmux[15:0]=datain[15:0]; else bmux[15:0]=bltbdat[15:0]; //channel B 'old' registeralways @(posedge clk) if(!bbusy) bltbold[15:0]<=0; else if(enable && (chs[1:0]==CHB[1:0])) bltbold[15:0]<=bmux[15:0];//channel B holding registeralways @(posedge clk) if(enable && rlb)//rotate register to the left (line mode) bhold[15:0]<={bhold[14:0],bhold[15]}; else if((enable && (chs[1:0]==CHB[1:0])) || (regaddressin[8:1]==BLTBDAT[8:1])) bhold[15:0]<=shiftout[15:0]; //multiplexed barrel shifter for channel A and channel B//the multiplexer is controlled by lhs (holding register select)assign newmux[15:0]=(chs[1:0]==CHA[1:0])?amux[15:0]:bmux[15:0];assign oldmux[15:0]=(chs[1:0]==CHA[1:0])?bltaold[15:0]:bltbold[15:0];assign shmux[3:0]=(chs[1:0]==CHA[1:0])?bltcon0[15:12]:bltcon1[15:12];bltshift blts1( .desc(desc), .sh(shmux), .new(newmux), .old(oldmux), .out(shiftout));//--------------------------------------------------------------------------------------//C channel processing chain//This channel is very simple as it has only a holding register//the holding register can be preloaded from the bus or loaded by dma//channel C holding registeralways @(posedge clk) if((enable && (chs[1:0]==CHC[1:0])) || (regaddressin[8:1]==BLTCDAT[8:1])) chold[15:0]<=datain[15:0];//--------------------------------------------------------------------------------------//D channel processing chain//The D channel is the output channel. The data from sources A,B and C are//combined here by the minterm generator. Then the data is fed through the//fill logic and loaded into the channel D holding register.//local signalsreg [15:0]ain; //A channel input for minterm generatorreg [15:0]bin; //B channel input for minterm generatorwire [15:0]mintermout; //minterm generator outputwire [15:0]fillout; //fill logic outputwire fci; //fill carry inwire fco; //fill carry out to next wordreg fcy; //fill carry latch//minterm A channel input select: special line draw mode or normal blit modealways @(sing or fpl or ahold) if(sing && !fpl) ain[15:0]=16'h0000; else ain[15:0]=ahold[15:0];//minterm A channel input select: line texturing mode or normal blit modealways @(tmb or bhold) if(tmb)//nomal line draw mode (apply texture) bin[15:0]={bhold[0],bhold[0],bhold[0],bhold[0],bhold[0],bhold[0],bhold[0],bhold[0],bhold[0],bhold[0],bhold[0],bhold[0],bhold[0],bhold[0],bhold[0],bhold[0]}; else//normal blit mode bin[15:0]=bhold[15:0]; //minterm generator instantationbltminterm bltmt1( .lf(bltcon0[7:0]), .ain(ain[15:0]), .bin(bin[15:0]), .cin(chold[15:0]), .out(mintermout[15:0])); //fill logic instantiationbltfill bltfl1( .ife(ife), .efe(efe), .fci(fci), .fco(fco), .in(mintermout[15:0]), .out(fillout[15:0]));//fill carry controlassign fci=(fwt)?bltcon1[2]:fcy;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -