--Frame Reader --Author: Billy Kozak --Created for the CMPE 490 final project for University of Alberta --Computer Engineering Program library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity frameReader is generic (FRAME_READER_BASE : STD_LOGIC_VECTOR := x"1880000"); port( --mm master stuff to read from memory avm_inter_address : out STD_LOGIC_VECTOR (31 downto 0); avm_inter_read :out STD_LOGIC := '0'; avm_inter_readdata : in STD_LOGIC_VECTOR (15 downto 0); avm_inter_waitrequest : in STD_LOGIC; avm_inter_readdatavalid : in STD_LOGIC; avm_inter_burstcount : out STD_LOGIC_VECTOR (11 downto 0); clk : in STD_LOGIC; --mm slave stuff to set and stop a go bit avs_slav_write: in STD_LOGIC; avs_slav_writedata : in STD_LOGIC_VECTOR (31 downto 0); --pixel value stuff coe_x_export : in STD_LOGIC_VECTOR (9 downto 0); coe_y_export : in STD_LOGIC_VECTOR (9 downto 0); --transitions when VGA controller is about to read pixels for the next row coe_rowClock_export : IN STD_LOGIC; --color value outputs coe_blue_export : out STD_LOGIC_VECTOR(9 downto 0); coe_red_export : out STD_LOGIC_VECTOR(9 downto 0); coe_green_export : out STD_LOGIC_VECTOR(9 downto 0); --reset signal to the VGA syncer coe_rst_export : out STD_LOGIC := '0'; --singal to let us know to reset the column count coe_resetCol_export : in STD_LOGIC ); end entity frameReader; architecture rtl of frameReader is --row/col counters to keep track of where to read from next signal rowCount : STD_LOGIC_VECTOR (11 downto 0) := x"000"; signal colCount : STD_LOGIC_VECTOR (11 downto 0) := x"000"; --if zero write to buffer 0 if 1 write to buffer 1 signal writeTo : STD_LOGIC := '0'; --buffers to be used as ping pong buffer subtype pixel is STD_LOGIC_VECTOR(15 downto 0); type buff is array (319 downto 0) of pixel; signal buff0 : buff; signal buff1 : buff; --signal to drive the read output line signal readReg : STD_LOGIC := '0'; signal byteCountReg : STD_LOGIC_VECTOR (11 downto 0) := x"140"; --signal to denote that the system is in synchronization mode signal synchronize : STD_LOGIC := '1'; signal syncCount : STD_LOGIC_VECTOR (1 downto 0) := "00"; --so that the synchronize funtion can cause the writeTo buffer to switch --when we come out of syncronization mode signal sync_to_write : STD_LOGIC := '0'; signal write_from_sync : STD_LOGIC := '0'; signal readOK : STD_LOGIC := '1'; signal burstBegin : STD_LOGIC := '0'; signal bursting : STD_LOGIC := '0'; signal bufferFilled : STD_LOGIC := '0'; signal stopRead : STD_LOGIC := '0'; signal resetRequested : STD_LOGIC := '0'; signal resetCount : STD_LOGIC := '0'; --go bit set when we want to continue reding from memory signal goBit : STD_LOGIC := '1'; signal writeStarted : STD_LOGIC; begin --thread to read from memory as fast as possible mem_read:process(clk,readReg,avm_inter_waitrequest) begin if(clk'event and clk = '1') then --if we aren't waiting for a read to complete --start a new read if(stopRead = '1' or synchronize = '1') then bursting <= '0'; bufferFilled <= '0'; elsif(readOK = '1' and burstBegin = '0' and bursting = '0') then readReg <= '1'; byteCountReg <= x"140"; burstBegin <= '1'; --as soon as wait request goes low read the data lines elsif (burstBegin = '1' and bursting = '0') then if(avm_inter_waitrequest = '0') then readReg <= '1'; bursting <= '1'; burstBegin <= '0'; end if; elsif(bursting = '1') then readReg <= '0'; if(avm_inter_readdatavalid = '1') then if(writeTo = '0') then buff0(conv_integer(colCount)) <= avm_inter_readdata; elsif(writeTo = '1') then buff1(conv_integer(colCount)) <= avm_inter_readdata; end if; bufferFilled <= '1'; else bufferFilled <= '0'; end if; end if; end if; end process mem_read; --process to track our horizontal read position h_track:process(clk,readReg,colCount,coe_resetCol_export) begin if(clk'event and clk = '0') then --if read reg is zero a read just finished --and we can increment colCount if(coe_resetCol_export = '1') then if(resetCount = '0') then resetCount <= '1'; elsif(resetCount = '1') then resetCount <= '0'; resetRequested <= '1'; end if; end if; if(resetRequested = '1') then resetRequested <= '0'; if(stopRead = '1' and goBit = '1') then colCount <= x"000"; stopRead <= '0'; readOK <= '1'; stopRead <= '0'; end if; end if; if(bufferFilled = '1') then --if colCount gets here stop and wait for it to become zero --DOUBLE 13F TO INCREASE RESOLUTION if(colCount >= x"13F") then colCount <= x"140"; readOK <= '0'; stopRead <= '1'; else colCount <= colCount + x"001"; end if; end if; end if; end process h_track; --process to track our vertical read position --MAKE THIS PROCESS TRIGGER ON BOTH EDGES TO INCREASE RESOLUTION --IF THAT DOESN'T WORK WILL NEED TO MODIFY ROW CLOCK IN VGA_SYNC SO THAT --WE CAN DETECT EVERY TIME THE ROW CHANGES v_track:process(coe_rowClock_export) begin if(coe_rowClock_export'event and coe_rowClock_export = '1') then --update row count as soon as the rowClock rises if(rowCount = x"0EF") then rowCount <= x"000"; else rowCount <= rowCount+x"001"; end if; --inform mem_read that it needs to read from different buffer writeto <= not writeto; end if; end process v_track; --hold synchronize high for 4 cycles to establish proper synchronization syncDown:process(clk) begin if(clk'event and clk = '1') then if(syncCount < "11") then syncCount <= syncCount +"01"; else synchronize <= '0'; end if; end if; end process syncDown; goStop:process(clk) begin if(clk'event and clk = '1') then if(avs_slav_write = '1') then goBit <= avs_slav_writedata(0); end if; end if; end process goStop; --TO INCREASE RESOLUTION CHANGE "9 DOWNTO 1 TO 9 DOWNTO 0" IN CODE BELOW --output the pixel values as they are requested from the controller --masking away the last bit of x causes horizontally adjacent pixels to be identical --read from the read buffer with writeTo SELECT coe_red_export <= buff1(conv_integer(coe_x_export(9 downto 1)))(14 downto 10) &"00000" when '0', buff0(conv_integer(coe_x_export(9 downto 1)))(14 downto 10) &"00000" when '1', "0000000000" when others; with writeTo SELECT coe_green_export <= buff1(conv_integer(coe_x_export(9 downto 1)))(9 downto 5) &"00000" when '0', buff0(conv_integer(coe_x_export(9 downto 1)))(9 downto 5) &"00000" when '1', "0000000000" when others; with writeTo SELECT coe_blue_export <= buff1(conv_integer(coe_x_export(9 downto 1)))(4 downto 0) &"00000" when '0', buff0(conv_integer(coe_x_export(9 downto 1)))(4 downto 0) &"00000" when '1', "0000000000" when others; --hard assign those signals that need it avm_inter_address <= x"0"&RowCount*(x"0280") + FRAME_READER_BASE; avm_inter_read <= readReg; coe_rst_export <= synchronize; avm_inter_burstcount <= byteCountReg; end architecture rtl;