Skip navigation

Monthly Archives: June 2013

Continuing with my learning experiments with the LED Matrix attached to the Papilio dev board, today I am adding PWM output to generate different light intensities. If your not familiar with PWM (pulse width modulation), it’s just a simple digital to analog conversion technique where the pin is switched on and off very fast, so the output effectively becomes an analog average between the time it’s on and the time is off. This is done by changing the duty cycle, which is the ratio to on time versus off time. In our VHDL project, this is a good opportunity to explore adding a new file to the project, a new entity, and interfacing multiple entities together. I added the new file for the PWM entity through the ISE Project Navigator, and followed the wizard, basically just giving the name of the file, entity, and the ports. The ports for this entity are pretty simple, we just need a value in to set the output of the PWM, the output bit, and the system clock in. I added a single process to the architecture, and this time decided to use a variable for internal counting instead of a signal. See this question about signals versus variables. Also being a little different from the code of parts 1 and 2, I am using the integer type, with the range specification. The operation of the PWM is really simple, each rising clock edge, the count variable is incremented. When the count is greater than the set value, the output is turned on, else its turned off. No other logic is needed since the count will keep rolling over back to zero. The higher the set value, the longer the bit stays on, and the higher the output. Just to note, with our clock period set at 31.25nS, and our count variable declared as 0 to 255, our wave will be exactly 256 clock cycles long, or 8uS. That comes out to be a 125KHz PWM frequency. Here’s the code for that part. I deleted out some of the automatic comments the wizard inserted in the file.



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


entity PWM is
    Port ( Value_In : in  integer range 0 to 255 ; --input for pwm value
           Bit_Out : out  STD_LOGIC;					--pwm output
			  clk : in STD_LOGIC);							--system clock
end PWM;

architecture Behavioral of PWM is

begin

	pwm: process(clk)
		variable count: integer range 0 to 255 := 0; --variable, internal to process, 8 bit counter
	begin
		if rising_edge(clk) then
			--increment count variable (note variable uses := not <=
			count := count + 1;

			if count < Value_In then
			   --while the counter is less than value, set bit
				--this ensures duty cycle is proportional to value
				Bit_Out <= '1';
			else
				--off during other half of cycle, while counter is greater than value
				Bit_Out <= '0';
			end if;

		end if;

	end process;



end Behavioral;

That seems like it will work. Now the trouble I had after this was trying to figure out how to tie the main entity in with this one so I could use it. I changed quite a bit of other stuff in the code to, since we now have to support multiple values for each LED, not just single bit on and off. I changed the display array to be a 2 dimensional array of 8 bit integers. The declaration and instantiation looked like this.


 type display_t is array(7 downto 0, 7 downto 0) of integer range 0 to 255; --array type for new image data, a 2d array of integers
 signal display : display_t := ((1, 1, 1, 1, 1, 1, 1, 1 ),
											(3, 3, 3, 3, 3, 3, 3, 3) ,
											(7, 7, 7, 7, 7, 7, 7, 7) ,
											(15,15,15,15,15,15,15,15) ,
											(31,31,31,31,31,31,31,31) ,
											(63,63,63,63,63,63,63,63) ,
											(127,127,127,127,127,127,127,127) ,
											(255,255,255,255,255,255,255,255 ));

With the 2D array, i also had to set a row_count and col_count to keep track of the position in the array. I also learned that I can define those as ranged integers, so they can be used to index the array directly without conversion. As for the col output, I added an if on the PWM output that would use the col mask if it was true or “00000000” if false. That statement was triggering on the same clock as the PWM so the output will be kept up to the PWM output. Our counter in this process is 9 bits, so each pixel should be getting about 2 PWM waves per scan.

Now to attach the PWM together with the main process here, I learned about the ‘port map’ and ‘component’ structures, component defined under the architecture and port map defined after the architecture’s begin statement. The component I believe acts like a port definition for the referenced entity, and the port map links the signals together.

--component definition for the PWM
component PWM is
    Port ( Value_In : in  integer range 0 to 255 ;
           Bit_Out : out  STD_LOGIC;
			  clk : in STD_LOGIC);
end component;

	--port map for linking to the PWM
	PW1 : PWM port map(Value_In => col_value,
							 Bit_out => pwm_bit,
							 clk => clk);

Looking at the port map, the signal col_value is mapped to PWM’s Value_In, so when we read the pixel value from the array into col_value, it is transferred to the input of the PWM. Likewise, pwm_bit will always be set to the value of the PWM’s Bit_out.

Here is the complete code.


--Standard includes
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

--Entity definiton
entity First is
    Port ( A : out  STD_LOGIC_VECTOR (16 downto 0); -- maps to pins 0 to 16 of port A
			  clk : in STD_LOGIC); --clock signal
end First;

--architecture definition
architecture Behavioral of First is

--component definition for the PWM
component PWM is
    Port ( Value_In : in  integer range 0 to 255 ;
           Bit_Out : out  STD_LOGIC;
			  clk : in STD_LOGIC);
end component;

 --Interial signals
 signal counter : STD_LOGIC_VECTOR(8 downto 0) := (others => '0'); --counter to control state and delay
 signal row : STD_LOGIC_VECTOR(7 downto 0) := "11111110";				--signal for LED rows
 signal col : STD_LOGIC_VECTOR(7 downto 0) := "00000001";				--signal for LED columns
 type display_t is array(7 downto 0, 7 downto 0) of integer range 0 to 255; --array type for new image data, a 2d array of integers
 signal display : display_t := ((1, 1, 1, 1, 1, 1, 1, 1 ),
											(3, 3, 3, 3, 3, 3, 3, 3) ,
											(7, 7, 7, 7, 7, 7, 7, 7) ,
											(15,15,15,15,15,15,15,15) ,
											(31,31,31,31,31,31,31,31) ,
											(63,63,63,63,63,63,63,63) ,
											(127,127,127,127,127,127,127,127) ,
											(255,255,255,255,255,255,255,255 ));

 signal col_value : integer range 0 to 255 := 0;					--used to retrieve value from array, mapped to PWM input
 signal row_count : integer range 0 to 7 := 1;						--pointer for array
 signal col_count : integer range 0 to 7 := 1;						--pointer for array
 signal pwm_bit : STD_LOGIC;												--signal to be mapped to PWM output

begin

	--port map for linking to the PWM
	PW1 : PWM port map(Value_In => col_value,
							 Bit_out => pwm_bit,
							 clk => clk);

	--Process Definition
	count: process(clk)
   begin
		-- triggers action on rising edge of clock signal
     if rising_edge(clk) then
	    --increment counter
       counter <= counter+1;
		 --clock period is 31.25ns, counter is 9 bits, should scan whole matrix in < 1ms
			--trigger each time counter rolls over back to zero
			if counter = 0 then
				-- Left Rotate col
				col <= col(6 downto 0) & col(7);
				col_count <= col_count + 1;
				-- Trigger when last column becomes active
				if col = "10000000" then
					-- Left rotate row
					row <= row(6 downto 0) & row(7);
					-- increment row count
					row_count <= row_count + 1;
					-- get column mask from current position in array
					col_value <=  display(row_count, col_count);

				end if;
			end if;
			--copy signals to outputs
			A(7 downto 0) <= row;
			--combine column with mask to only display selected pixels
			if pwm_bit = '1' then
				A(15 downto 8) <= (col);
			else
				A(15 downto 8) <= "00000000";
			end if;

     end if;
   end process;




end Behavioral;


And of course, the working example.

In the second part of this article, we’re going to try and get a little more interesting stuff going on with our FPGA powered LED matrix. To start, we will try to get a simple image to display on the matrix. To do this we will need a way to store the image. VHDL allows for array types so we can accomplish this by creating an eight element array of eight bit vectors, giving us one bit per pixel. We can then use each of these vectors as a mask value to AND with the col signal. This is a little confusing (at least in my head), as each col value contains a bit for each row in the column, so we AND that with the col_mask value, which is essential the pixels for a row of the display. Starting with the same setup from last time, we are adding these new signals to the architecture.


 type display_t is array(7 downto 0) of STD_LOGIC_VECTOR(7 downto 0);
 signal display : display_t := ("00000000" ,    -- A simple image to display
											"01100110" , 	-- stored in an array
											"01100110" ,
											"00000000" ,
											"00000000" ,
											"11000011" ,
											"00111100" ,
											"00000000");

 signal col_mask : STD_LOGIC_VECTOR(7 downto 0) := "00000000";		--mask value used to activate only desired pixels
 signal row_count : unsigned(2 downto 0) := "000";						--pointer for array

Note that for the array, you have do declare an array type first, then declare an array of that type. Like many languages, we are allowed to instantiate the array with some values. Notice the nice smiley face. Also note that the array is declared 7 downto 0, meaning the first element essentially is the last one in the instantiation list. Since row 0 of our display is at the bottom, this means the image should appear just as the bits appear in the code. I also added a row_count signal, declared as unsigned because it will be used numerically. This will just count up as we scan the matrix rows and serve as a pointer to our array. Also added is the col_mask signal. This signal stores the current row loaded from the array. Below is the added code to increment the row_count and retrieve the col_mask. Note that the row_count is declared as 3 bits, meaning it will automatically rollover back to zero after 7.


					-- increment row count
					row_count <= row_count + 1;
					-- get column mask from current position in array
					col_mask <= display(conv_integer(row_count));

And then of course we AND the mask to the output.


			--combine column with mask to only display selected pixels
			A(15 downto 8) <= (col AND col_mask);

Here is the complete code for this example.

--Standard includes
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

--Entity definiton
entity First is
    Port ( A : out  STD_LOGIC_VECTOR (16 downto 0); -- maps to pins 0 to 16 of port A
			  clk : in STD_LOGIC); --clock signal
end First;

--architecture definition
architecture Behavioral of First is
 --Interial signals
 signal counter : STD_LOGIC_VECTOR(8 downto 0) := (others => '0'); --counter to control state and delay
 signal row : STD_LOGIC_VECTOR(7 downto 0) := "11111110";				--signal for LED rows
 signal col : STD_LOGIC_VECTOR(7 downto 0) := "00000001";				--signal for LED columns
 type display_t is array(7 downto 0) of STD_LOGIC_VECTOR(7 downto 0);
 signal display : display_t := ("00000000" ,    -- A simple image to display
											"01100110" , 	-- stored in an array
											"01100110" ,
											"00000000" ,
											"00000000" ,
											"11000011" ,
											"00111100" ,
											"00000000");

 signal col_mask : STD_LOGIC_VECTOR(7 downto 0) := "00000000";		--mask value used to activate only desired pixels
 signal row_count : unsigned(2 downto 0) := "000";						--pointer for array

begin
	--Process Definition
	count: process(clk)
   begin
		-- triggers action on rising edge of clock signal
     if rising_edge(clk) then
	    --increment counter
       counter <= counter+1;
		 --clock period is 31.25ns, counter is 9 bits, should scan whole matrix in < 1ms
			--trigger each time counter rolls over back to zero
			if counter = 0 then
				-- Left Rotate col
				col <= col(6 downto 0) & col(7);
				-- Trigger when last column becomes active
				if col = "10000000" then
					-- Left rotate row
					row <= row(6 downto 0) & row(7);
					-- increment row count
					row_count <= row_count + 1;
					-- get column mask from current position in array
					col_mask <= display(conv_integer(row_count));
				end if;
			end if;
			--copy signals to outputs
			A(7 downto 0) <= row;
			--combine column with mask to only display selected pixels
			A(15 downto 8) <= (col AND col_mask);
     end if;
   end process;


end Behavioral;

This give the following output.

Now if you noticed, it looks good, but that’s not the image we intended. Its shifted up by one row! See my question on Stack Overflow for an explanation of where I went wrong. Apparently signals are updated at the end of the process, so the value is definitely updated after the value is retrieved from the array. The fix is pretty simple, I just instantiate my row_count to 1 to compensate.

 signal row_count : unsigned(2 downto 0) := "001";						--pointer for array

Now it displays correctly.

Now for one more experiment in this installment, lets create a vertical scrolling effect. In the above example where I screwed it up the first time, having the wrong value for row_count shifts the image up and down. We can use this to create our scrolling effect. My first thought was to add a second process with a delay counter and just subtract one from the row_count value. However, that produces a compile error, “this signal is connected to multiple drivers.” I’m guessing that means its illegal to set a signal from multiple processes. So, instead we will add a new signal, row_offset, same type as row_count. Then we will use the second process to increment that, and just subtract it from row_count when indexing the array.

We add these two new signals.

 signal row_offset : unsigned(2 downto 0) := "000";					--offset to control vertical scrolling
 signal scroll_delay : STD_LOGIC_VECTOR(22 downto 0) := (others => '0'); --counter for vertical scroll delay

And we add this new process to the same architecture.

	vscroll: process(clk)
		begin

			if rising_edge(clk) then
				--counter is 23 bits, will rollover at .26 seconds
				scroll_delay <= scroll_delay+1;

				if scroll_delay = 0 then
					--decrement to mis-align row count, to give a vertical scrolling effect
					row_offset <= row_offset+1;
				end if;
			end if;
		end process;

The we modify the array access like this.

					-- get column mask from current position in array
					col_mask <= display(conv_integer(row_count) - conv_integer(row_offset));

I had to use the two separate conv_integer functions as the compiler complained of trying to do the math first, then calling conv_integer. Here is the complete code.

--Standard includes
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

--Entity definiton
entity First is
    Port ( A : out  STD_LOGIC_VECTOR (16 downto 0); -- maps to pins 0 to 16 of port A
			  clk : in STD_LOGIC); --clock signal
end First;

--architecture definition
architecture Behavioral of First is
 --Interial signals
 signal counter : STD_LOGIC_VECTOR(8 downto 0) := (others => '0'); --counter to control state and delay
 signal row : STD_LOGIC_VECTOR(7 downto 0) := "11111110";				--signal for LED rows
 signal col : STD_LOGIC_VECTOR(7 downto 0) := "00000001";				--signal for LED columns
 type display_t is array(7 downto 0) of STD_LOGIC_VECTOR(7 downto 0);
 signal display : display_t := ("00000000" ,    -- A simple image to display
											"01100110" , 	-- stored in an array
											"01100110" ,
											"00000000" ,
											"00000000" ,
											"11000011" ,
											"00111100" ,
											"00000000");

 signal col_mask : STD_LOGIC_VECTOR(7 downto 0) := "00000000";		--mask value used to activate only desired pixels
 signal row_count : unsigned(2 downto 0) := "001";						--pointer for array
 signal row_offset : unsigned(2 downto 0) := "000";					--offset to control vertical scrolling
 signal scroll_delay : STD_LOGIC_VECTOR(22 downto 0) := (others => '0'); --counter for vertical scroll delay

begin
	--Process Definition
	count: process(clk)
   begin
		-- triggers action on rising edge of clock signal
     if rising_edge(clk) then
	    --increment counter
       counter <= counter+1;
		 --clock period is 31.25ns, counter is 9 bits, should scan whole matrix in < 1ms
			--trigger each time counter rolls over back to zero
			if counter = 0 then
				-- Left Rotate col
				col <= col(6 downto 0) & col(7);
				-- Trigger when last column becomes active
				if col = "10000000" then
					-- Left rotate row
					row <= row(6 downto 0) & row(7);
					-- increment row count
					row_count <= row_count + 1;
					-- get column mask from current position in array
					col_mask <= display(conv_integer(row_count) - conv_integer(row_offset));
				end if;
			end if;
			--copy signals to outputs
			A(7 downto 0) <= row;
			--combine column with mask to only display selected pixels
			A(15 downto 8) <= (col AND col_mask);
     end if;
   end process;

	vscroll: process(clk)
		begin

			if rising_edge(clk) then
				--counter is 23 bits, will rollover at .26 seconds
				scroll_delay <= scroll_delay+1;

				if scroll_delay = 0 then
					--decrement to mis-align row count, to give a vertical scrolling effect
					row_offset <= row_offset+1;
				end if;
			end if;
		end process;


end Behavioral;



And here is the scrolling effect in action.

Next time we will see about making a simple animation with several frames. See you then!

Today, I’m learning about the magical and mystical world of FPGAs. FPGAs can be a challenging subject to get into for some of us, especially those of us who spent their days in college learning about programming computers, and not electrical engineering. Like many in this subject, I really had no idea where to start. So, I’ve setup a simple experiment using everyone’s favorite low cost FPGA dev board, the Papilio, a standard bread board, and a cheap red LED matrix from EBay.

If you go to the Papilio website like I did to start gathering knowledge, they seem to want to push you towards starting by loading an implementation of an AVR soft processor. Personally, I think it kinda defeats the purpose of trying to learn about FPGAs and VHDL, if you just load up a pre-built processor and go back to writing C code. Other than that, if you look around you will find nice step by step instructions for setting up a simple project. This includes the links and instructions for installing the Xilinx tools required to synthesize the VHDL into a bitstream that can be loaded on Papilio’s Xilinx Spartan 3 FPGA.

Once you’ve finished with setting up your first project from the tutorial on the Papilio site, let’s setup the bread board for our experiments. The idea here is simple, using 16 of the IO pins from the FPGA, we will drive the 8 rows and 8 columns of the LED matrix. With the IO pins set to output, it should be as simple as putting one column high, and one row low, thus creating a current through the diode in the correct direction. The diode action prevents the low column outputs from sinking current from the high rows. Now, a little bit of care is noted here, as I don’t know the maximum current source and sink rating of the IO pins, or if they contain any short kind of protection. Potentially, as I can only assume, connecting a high output directly to a low output would create a short circuit and damage your FPGA. Also, I should assume using too low of a value resistor could potentially draw too much current and damage the IO pins as well, but I could be completely wrong about that as well. If you followed the tutorial above to setup your project, all the output pins should be configured as LVCMOS33, which means a logic 1 will put 3.3 volts on the pin. In my circuit, I have 330 ohm resistor, so taking V = IR, that gives 10mA. That should be plenty to power the LED and doesn’t seem like it should be too much for the FPGA IO pins to handle. Again, I couldn’t find the spec for that, so its just a guess. You could use a higher value resistor as well, I just had those 330s in my parts bin. A 1K would probably work as well.

Here is the circuit. Basically, we have all the rows of the LED matrix attached to IO pins A0 to A7 on the Papilio board. The pinout and polarity of the matrix I figured out mostly from other sources online using similar parts, and a little probing with the multimeter. Im not sure why, but the most trouble I had with understanding this matrix is that the lower left hand corner in the picture is row 1, column 1, with the rows and columns increasing across and up. The actuall FPGA pin mapping to the logical Papilio ports is defined in that .UCF file you added in the above tutorial.


NET A(0)     LOC="P18"  | IOSTANDARD=LVCMOS33;                             # A0
NET A(1)     LOC="P23"  | IOSTANDARD=LVCMOS33;                             # A1
NET A(2)     LOC="P26"  | IOSTANDARD=LVCMOS33;                             # A2
NET A(3)     LOC="P33"  | IOSTANDARD=LVCMOS33;                             # A3
NET A(4)     LOC="P35"  | IOSTANDARD=LVCMOS33;                             # A4
NET A(5)     LOC="P40"  | IOSTANDARD=LVCMOS33;                             # A5
NET A(6)     LOC="P53"  | IOSTANDARD=LVCMOS33;                             # A6
NET A(7)     LOC="P57"  | IOSTANDARD=LVCMOS33;                             # A7
NET A(8)     LOC="P60"  | IOSTANDARD=LVCMOS33;                             # A8
NET A(9)     LOC="P62"  | IOSTANDARD=LVCMOS33;                             # A9
NET A(10)    LOC="P65"  | IOSTANDARD=LVCMOS33;                             # A10
NET A(11)    LOC="P67"  | IOSTANDARD=LVCMOS33;                             # A11
NET A(12)    LOC="P70"  | IOSTANDARD=LVCMOS33;                             # A12
NET A(13)    LOC="P79"  | IOSTANDARD=LVCMOS33;                             # A13
NET A(14)    LOC="P84"  | IOSTANDARD=LVCMOS33;                             # A14
NET A(15)    LOC="P86"  | IOSTANDARD=LVCMOS33;                             # A15

To create an image, we can turn the LEDs on and off, one at a time, really fast, so it makes it look like an image appears. This eliminates the need to have 64 IO lines to control each led. So the first experiment we can do is to generate a slow scan of all the LEDs to verify that everything is hooked up correctly and our VHDL code works. After a bit of experimentation, modifying the code from the Papilio tutorial, and a little Googling, I came up with this.


--Standard includes
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

--Entity definiton
entity First is
    Port ( A : out  STD_LOGIC_VECTOR (16 downto 0); -- maps to pins 0 to 16 of port A
			  clk : in STD_LOGIC); --clock signal
end First;

--architecture definition
architecture Behavioral of First is
 --Interial signals
 signal counter : STD_LOGIC_VECTOR(22 downto 0) := (others => '0'); --counter to control state and delay
 signal row : STD_LOGIC_VECTOR(7 downto 0) := "11111110";				--signal for LED rows
 signal col : STD_LOGIC_VECTOR(7 downto 0) := "00000001";				--signal for LED columns
begin
	--Process Definition
	count: process(clk)
   begin
		-- triggers action on rising edge of clock signal
     if rising_edge(clk) then
	    --increment counter
       counter <= counter+1;
		 --clock period is 31.25ns, counter is 22 bits, should roll over every 260ms
			--trigger each time counter rolls over back to zero
			if counter = 0 then
				-- Left Rotate col
				col <= col(6 downto 0) & col(7);
				-- Trigger when last column becomes active
				if col = "10000000" then
					-- Left rotate row
					row <= row(6 downto 0) & row(7);
				end if;
			end if;
			--copy signals to outputs
			A(7 downto 0) <= row;
			A(15 downto 8 ) <= col;
     end if;
   end process;


end Behavioral;

I’ve commented the code to try and make it easy to follow. The important thing to remember is that VHDL code defines hardware, it DOES NOT RUN. As a programmer this is a difficult concept to grasp, as I am so ingrained in the idea of procedural code, running instructions one at a time. For the most part, everything in VHDL happens simultaneously, with the IF statements basically defining when each block of stuff can happen. For our current experiment, we want things to run in a procedural manner, lighting one LED at a time in order. To do this, we have to implement a primitive state machine, using a counter to create a delay and the current row and col values as the state, triggering off of the clk signal. Staring at the beginning, we have our counter signal defined as 22 down to 0 (23 bits), defaulted to all zeros. The size of the counter was chosen so that at our clock period of 31.25ns, the counter would roll over back to zero in about 260ms, giving a nice slow visible scan of the martix. Row is an 8 bit value we are defaulting to “11111110” and col is an 8 bit value defaulting to “00000001”. As you see in the defaults, row 1 and column 1 are defaulted to be on. To create the scan, these two values will be rotated, so that the row that is set to 0 and the column that is set to 1 will light the correct LED. The first if statement detects and activates on the rising edge of the clock signal. Again, not a procedural language, when we hit the rising edge of the clock, everything in the block will be run. Two basic assignments happen in this block, first we add one to the counter signal, second we copy the row and col values to the outputs of port A. The nested if activates when the counter rolls over and hits zero again. When that happens we rotate the col signal to the left. We do that by taking the right most 6 bits and appending the 7th bit to the end of it. Another nested if detects when col reaches the value “10000000”, meaning its on the last column, we rotate the row signal.

If you generate the bit file for the code above and load it into your board you should see the LED scroll through each row and column on the display. After we’ve verified that it in fact scans the matrix in the correct direction and that all the LEDs light up, we can just decrease the size of the counter signal to increase the scroll speed. If we take it down to 9 bits, it should scan through the entire matrix in less than 1ms. This will give the impression that all the LEDs are on at once.


--Standard includes
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

--Entity definiton
entity First is
    Port ( A : out  STD_LOGIC_VECTOR (16 downto 0); -- maps to pins 0 to 16 of port A
			  clk : in STD_LOGIC); --clock signal
end First;

--architecture definition
architecture Behavioral of First is
 --Interial signals
 signal counter : STD_LOGIC_VECTOR(8 downto 0) := (others => '0'); --counter to control state and delay
 signal row : STD_LOGIC_VECTOR(7 downto 0) := "11111110";				--signal for LED rows
 signal col : STD_LOGIC_VECTOR(7 downto 0) := "00000001";				--signal for LED columns
begin
	--Process Definition
	count: process(clk)
   begin
		-- triggers action on rising edge of clock signal
     if rising_edge(clk) then
	    --increment counter
       counter <= counter+1;
		 --clock period is 31.25ns, counter is 9 bits, should scan whole matrix in < 1ms
			--trigger each time counter rolls over back to zero
			if counter = 0 then
				-- Left Rotate col
				col <= col(6 downto 0) & col(7);
				-- Trigger when last column becomes active
				if col = "10000000" then
					-- Left rotate row
					row <= row(6 downto 0) & row(7);
				end if;
			end if;
			--copy signals to outputs
			A(7 downto 0) <= row;
			A(15 downto 8 ) <= col;
     end if;
   end process;


end Behavioral;

Again, all that changed is the counter size, but running it now shows a fully lit matrix.

OK! We’ve learned a bit, and managed to generate a signal that can drive an LED matrix. Next time, I’ll be attempting to modify this code to read some simple images from memory and display them on the matrix.