mirror of
				https://github.com/Klagarge/Cursor.git
				synced 2025-10-31 05:59:18 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			144 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
| library Common;
 | |
|   use Common.CommonLib.all;
 | |
| 
 | |
| ARCHITECTURE RTL OF lcdSerializer IS
 | |
| 
 | |
|   ------------------------------------------------------------------------------
 | |
|   -- The clock-pulse rate of the SCL line can be up to 20 MHz @3.3V
 | |
|   --    The clock frequency is divided by generic value "baudRateDivide"
 | |
|   --    The corresponding "sclEn" is further divided by 2 to generate SCL
 | |
|   --
 | |
|   signal sclCounter: unsigned(requiredBitNb(baudRateDivide-1)-1 downto 0);
 | |
| 	signal sclEn: std_ulogic;
 | |
| 	signal scl_int: std_ulogic;
 | |
| 
 | |
|   ------------------------------------------------------------------------------
 | |
|   -- The minimal reset pulse width is 1 us
 | |
|   --    "sclEn" at 40 MHz has to be divided by 40 to generate the 1 us delay
 | |
|   --
 | |
| 	constant resetCount : natural := 40;
 | |
|   signal resetCounter: unsigned(requiredBitNb(2*resetCount-1)-1 downto 0);
 | |
| 	signal resetDone: std_ulogic;
 | |
| 
 | |
| 
 | |
|   ------------------------------------------------------------------------------
 | |
|   -- Serial data bits have to be stable at the rising edge of SCL
 | |
|   --    Data bits will be updated at the falling edge of SCL
 | |
|   --
 | |
|   -- Data in comprises 9 bits: A0 (as MSB) and 8 row pixels or command bits
 | |
|   -- A0 selects between command data (A0 = 0) and pixel data (A0 = 1)
 | |
|   --
 | |
| 	constant pixelsPerColumn : positive := data'length-1;
 | |
| 	signal dataSampled : std_ulogic_vector(data'range);
 | |
| 	signal chipSelect : std_ulogic;
 | |
| 	signal updateData: std_ulogic;
 | |
|   signal dataCounter: unsigned(requiredBitNb(pixelsPerColumn+1)-1 downto 0);
 | |
| 
 | |
| BEGIN
 | |
|   ------------------------------------------------------------------------------
 | |
|                                                         -- clock divider for SCL
 | |
|   divideClock: process(reset, clock) 
 | |
| 	begin
 | |
|     if reset='1' then
 | |
| 			scl_int <= '0';
 | |
|       sclCounter <= (others => '0');
 | |
|     elsif rising_edge(clock) then
 | |
|       if sclEn = '1' then
 | |
|         sclCounter <= (others => '0');
 | |
| 				scl_int <= not scl_int;
 | |
|       else
 | |
|         sclCounter <= sclCounter + 1;
 | |
| 			end if;
 | |
|     end if;
 | |
|   end process divideClock;
 | |
| 
 | |
|   sclEn <= '1' when sclCounter = baudRateDivide-1
 | |
|     else '0';
 | |
| 
 | |
|   ------------------------------------------------------------------------------
 | |
|                                                                     -- LCD reset
 | |
| 	process(clock,reset)
 | |
| 		variable i : natural;
 | |
| 	begin
 | |
| 		if reset = '1' then
 | |
| 			resetCounter <= (others => '0');
 | |
| 		elsif rising_edge(clock) then
 | |
| 			if sclEn = '1' then
 | |
|   			if resetDone = '0' then
 | |
|   				resetCounter <= resetCounter + 1;
 | |
|   			end if;
 | |
| 			end if;
 | |
| 		end if;
 | |
| 	end process;
 | |
| 
 | |
|   resetDone <= '1' when resetCounter >= 2*resetCount-1
 | |
|     else '0';
 | |
|   RST_n <= '1' when resetCounter >= resetCount-1
 | |
|     else '0';
 | |
| 
 | |
|   ------------------------------------------------------------------------------
 | |
|                                                             -- sample input data
 | |
|   process (reset, clock)
 | |
|   begin
 | |
|     if reset = '1' then
 | |
|       dataSampled <= (others => '0');
 | |
|     elsif rising_edge(clock) then
 | |
|       if send = '1' then
 | |
|         dataSampled <= data;
 | |
|       end if;
 | |
|     end if;
 | |
| 	end process;
 | |
| 
 | |
|   ------------------------------------------------------------------------------
 | |
|                                                                            -- A0
 | |
| 	A0 <= dataSampled(data'high);
 | |
| 
 | |
|   ------------------------------------------------------------------------------
 | |
|                                                                -- serialize data
 | |
|   updateData <= sclEn and scl_int;
 | |
| 
 | |
|   process (reset, clock)
 | |
|   begin
 | |
|     if reset = '1' then
 | |
|       dataCounter <= (others => '0');
 | |
|     elsif rising_edge(clock) then
 | |
|       if resetDone = '1' then
 | |
|         if dataCounter = 0 then
 | |
|           if send = '1' then
 | |
|             dataCounter <= to_unsigned(pixelsPerColumn+1, dataCounter'length);
 | |
|           end if;
 | |
|         else
 | |
|           if updateData = '1' then
 | |
|             dataCounter <= dataCounter - 1;
 | |
|           end if;
 | |
|         end if;
 | |
|       end if;
 | |
|     end if;
 | |
| 	end process;
 | |
| 
 | |
|   busy <= '1' when (resetDone = '0') or (dataCounter > 0)
 | |
|     else '0';
 | |
| 	chipSelect <= '1' when (dataCounter > 0) and (dataCounter < pixelsPerColumn+1)
 | |
| 	  else '0';
 | |
| 
 | |
| 	sampleData: process (reset, clock)
 | |
| 	begin
 | |
| 		if reset = '1' then
 | |
|       CS_n <= '1';
 | |
|       SCL  <= '1';
 | |
|       SI   <= '1';
 | |
| 		elsif rising_edge(clock) then
 | |
| 			if chipSelect = '1' then
 | |
|         CS_n <= '0';
 | |
|         SCL <= scl_int or not(chipSelect);
 | |
| 				SI <= dataSampled(to_integer(dataCounter-1));
 | |
| 			else
 | |
|         CS_n <= '1';
 | |
|         SCL <= '1';
 | |
|         SI <= '1';
 | |
| 			end if;
 | |
| 		end if;
 | |
| 	end process sampleData;
 | |
| 
 | |
| END ARCHITECTURE RTL;
 |