Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20638 Discussions

matrix array in vhdl

Altera_Forum
Honored Contributor II
9,450 Views

Dear all, 

 

I have 4x4 matrix and I want to read this matrix row by row on each clock cycle. For example, row1 is read in cycle1, row2 is read in cycle2 and so on. 

Can anyone give idea how to write this code? Many thanks
0 Kudos
22 Replies
Altera_Forum
Honored Contributor II
3,129 Views

it depends. If you have an array of arrays, its going to be much easier: 

 

type row_t is array(0 to 3) of std_logic_vector(7 downto 0); type matrix_t is array(0 to 3) of row_t; signal matrix : matrix_t; signal temp_row : row_t; signal count : unsigned(1 downto 0) := "00"; begin process(clk) begin if rising_edge(clk) then temp_row <= matrix( to_integer(count) ); count <= count + 1; end if; end process;  

 

If you're using a 2d, matrix type, things get a little more complicated as you have to use a function to extract the row, but it should generate the same logic. 

 

type row_t is array(0 to 3) of std_logic_vector(7 downto 0); type matrix_t is array(0 to 3, 0 to 3) of std_logic_vector(7 downto 0);; signal matrix : matrix_t; signal temp_row : row_t; signal count : unsigned(1 downto 0) := "00"; function extract_row( m : matrix_t; row : integer) return row_t is variable ret : row_t; begin for i in row_t'range loop ret(i) := m(row, i); end loop; return ret; end function; begin process(clk) begin if rising_edge(clk) then temp_row <= extract_row( matrix, to_integer(count) ); count <= count + 1; end if; end process;  

 

NB: Matrix could be an input to your entity.
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

Dear Tricky, 

 

From the code you give above, the input will be a matrix std_logic_vector data type right? As I know the input will be like "0011". 

How if I want the input is a matrix with integer data type? It is I need to change the data type std_logic_vector to integer? Thanks for reply
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

yes, just change std_logic_vector to integer.

0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

Dear Tricky, 

 

Now I try to write for 2D matrix with integer data type. I change the std_logic_vector to integer as below: 

 

--before: 

 

entity TM is 

port(input: in std_logic_vector (0 to 3); 

clk: in std_logic); 

end TM; 

 

--after: 

 

entity TM is 

port(input: in integer range 0 to 3; 

clk: in std_logic); 

end TM; 

 

It is right I declare my 2D input as code above? But, I think its 1D..Then I change to range (0 to 3, 0 to 3) but error occurs. What the right way should I write..Thanks for reply
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

input : in integer range 0 to 3 

 

is not an array at all, it is just a single value. to make an array and put it on a port you have to declare an array type in a package. If you you're going to use the row_t I declared for you , you need to move that into a package.
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

Dear Tricky, 

 

Did you mean like this: 

 

package newtype is 

type row_t is array(0 to 3) of integer; 

type matrix_t is array(0 to 3, 0 to 3) of integer; 

end newtype; 

 

library ieee; 

use ieee.std_logic_1164.all; 

use ieee.numeric_std.all; 

use work.newtype.all; 

 

entity test is 

port(input: in matrix_t; 

clk: in std_logic); 

end test; 

 

Thanks for reply
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

yes, like that.

0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

Dear Tricky, 

 

I have simulate the code and the result shows that the 4x4 input matrix does not obtain in the correct clock cycle. All the rows obtain at the same clock cycle in one time. Below is the main code and testbench: 

 

---main code 

package newtype is 

type row_t is array(0 to 3) of integer; 

type matrix_t is array(0 to 3, 0 to 3) of integer; 

end newtype; 

 

library ieee; 

use ieee.std_logic_1164.all; 

use ieee.numeric_std.all; 

use work.newtype.all; 

 

entity test is 

port(input: in matrix_t; 

clk: in std_logic); 

end test; 

 

architecture arch of test is  

 

signal matrix : matrix_t; 

signal temp_row : row_t; 

signal count : unsigned(1 downto 0) := "0"; 

 

function extract_row( m : matrix_t; row : integer) return row_t is 

variable ret : row_t; 

begin 

for i in row_t'range loop 

ret(i) := m(row, i); 

end loop; 

 

return ret; 

end function; 

 

begin 

 

process(clk) 

begin 

if rising_edge(clk) then 

temp_row <= extract_row( matrix, to_integer(count) ); 

count <= count + 1; 

end if; 

end process; 

end arch; 

 

---testbench 

library IEEE; 

use IEEE.Std_logic_1164.all; 

use IEEE.Numeric_Std.all; 

use work.newtype.all; 

 

entity test_tb is 

end; 

 

architecture bench of test_tb is 

 

component test 

port(input: in matrix_t; 

clk: in std_logic); 

end component; 

 

signal input: matrix_t; 

signal clk: std_logic; 

 

constant clock_period: time := 10 ns; 

signal stop_the_clock: boolean; 

 

begin 

 

uut: test port map ( input => input, 

clk => clk ); 

 

stimulus: process 

begin 

input <= ((0,1,2,9), (3,5,6,10), (9,8,11,2), (9,7,1,6)); 

wait for 50ns; 

 

stop_the_clock <= true; 

wait; 

end process; 

 

clocking: process 

begin 

while not stop_the_clock loop 

clk <= '1', '0' after clock_period / 2; 

wait for clock_period; 

end loop; 

wait; 

end process; 

end; 

 

What the mistake I have done? Help me please..thanks foR reply
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

first of all, your code has a compile error. Count needs to be initialised to "00" not "0". So you cant have simulated this exact code. 

 

Secondly, because you have left my code pretty much intact, you're extracting the row from the internal signal matrix that is not connected to anything. You need to put "input", rather than "matrix" into the extract_row function. 

 

Once I'd fixed these two problems, the row extraction works fine for me. Where do you expect the exctracted rows to go?
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

Dear Tricky, 

 

I have fixed for the first problem. But Iam not clear the second problem. Can you explain more? 

 

I expect the extracted rows to be read out by columns for the output. I hope you understand what I try to do. Thanks for reply.
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

delete the "matrix" signal insde the entity "test", and change the process to this: 

 

process(clk) begin if rising_edge(clk) then temp_row <= extract_row( input , to_integer(count) ); count <= count + 1; end if; end process;  

 

Now, how can you expect to read anything "out". There is no output from test. Currently the rows are extracted into the temp_row signal
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

Dear Tricky, 

 

I understand what you said just before. I can't see the rows obtained in different clock cycles. 

 

What Iam try to do is, I want the input matrix to be read row by row in different clock cycle. Then, the first row will be read out as output1 in column. It is possible I do like that? Thanks for reply.
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

temp_row contains the row currently. If you run the simulation for 50ns you can see the row selected changing every clock cycle, as per the attached image (shows its working for me). 

 

For your outputs, you will need to add them to the code. It sounds like you're trying to do a matrix transpose - but there is no need to do a transpose synchronously - because all you are doing is re-wiring the array, it doesnt cost any resources, and doesnt need to be synchronous.
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

Dear Tricky, 

 

Yes, I try to do a matrix transpose. Before this I write directly the transpose code but then when I compile for 8x8 input matrix an error occur which is the input pin required is to much. 

 

So, I try to transpose the matrix row by row. My idea is when the second row is read, the first row will be read out as a column and so on. It is possible Tricky if I do like that? Thanks for reply.
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

you can do it like that, but there is no need to do it row by row, you can do the whole thing in one go via a function. It doesnt need a clock.

0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

Dear Tricky, 

 

Did you mean I can transpose the whole matrix directly? Even a big input matrix (8x8 matrix). And what do you mean by doesnt need a clock? 

Thanks for reply.
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

you can transpose the entire thing yes. You just need to write a transpose function, like this: 

 

function transpose( matrix : matrix_t ) return matrix_t is variable ret : matrix_t; begin for i in matrix'range(1) loop for j in matrix'range(2) loop ret(j, i) := matrix(i,j); end loop; end loop; return ret; end function; ..... transposed_matrix <= transpose(input);  

 

This is not like softwear where you have to move everything around a memory - all you are doing is shifting all the "wires" around, so the data doesnt actually move, the output just connects to different inputs. There is no resource cost involved - its free. 

 

one big but: 

 

I think we've spoken before on this very subject, and it was clear then you had little understanding of digital logic. That doesnt seem to have changed. I recommend you go and learn about digital logic before you get any further with this. Otherwise you are going to hit some brick walls very quickly and you will not understand why.
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

Dear Tricky, 

 

I will study the code function first before write the transpose code for my system. By the way, many thanks for your help and advice. I appreciate it. 

Any problem I will let you know later. Thanks for reply.
0 Kudos
Altera_Forum
Honored Contributor II
3,129 Views

This is my transpose code: 

 

package newtype is 

type matrix_t is array (0 to 8, 0 to 8) of integer; 

end newtype; 

 

library ieee; 

use ieee.std_logic_1164.all; 

use ieee.numeric_std.all; 

use work.newtype.all; 

 

entity transpose is 

port(input: in matrix_t; 

clk: in std_logic; 

transposed_matrix: out matrix_t); 

end transpose; 

 

architecture arch of transpose is 

function change (matrix: matrix_t) return matrix_t is 

variable ret: matrix_t; 

begin 

for i in matrix'range(1) loop 

for j in matrix'range(2) loop 

ret (j,i):= matrix (i,j); 

end loop; 

end loop; 

return ret; 

end function; 

 

begin 

transposed_matrix <= change (input); 

end arch; 

 

The same error with my previous code that not use a function is occurs; 

Error: Design requires 5185 I/O resources -- too many to fit in 1264 available in the selected device or any device in the device family. 

 

Why the same error still occurs? I confuse now, need your helps. Many thanks.
0 Kudos
Altera_Forum
Honored Contributor II
2,619 Views

That's the problem when using abstract data types like integer. You can use them in hardware design, but you should know what you are doing. By default, integer is a signed 32 bit quantity, thus each integer array element is infered as signed(31 downto 0). It's easy to calculate the amount of port bits needed to represent the array. 

 

To learn about reasonable usage of the integer type in hardware designs, you can review the Quartus VHDL binary counter template. Generally you need to constrain it by setting a range in the type definition. 

 

My personal opinion is, that you should better use signed or unsigned types for the top entitie's port. Altough the port is represented by a bit_vector, you can't access individual bits without type casting the signal, because integer abstracts from it. Somewhat confusing, I think. Integers are however appropriate for internal signals.
0 Kudos
Reply