VHDL - looping through an array - vhdl

I wanted to loop through an array elements and later output them.
I don't think that the for loop is correct.
Could someone help with this, please ?
enter image description here

In VHDL, a for loop is a shorthand notation for creating parallel paths of logic.
In your example, the loop becomes a shift-by-1 index mapping assignment:
r_array(1) <= myArray1(0);
r_array(2) <= myArray1(1);
r_array(3) <= myArray1(2);
r_array(4) <= myArray1(3);
r_array(5) <= myArray1(4);
r_array(6) <= myArray1(5);
r_array(7) <= myArray1(6);
Since r_array is scalar type integer type and not a vector, this won't work as is.
Try using r_array as an index counter, then on each rising edge clock the next index of myArray will be assigned and our array index counter will increment by 1 (or wrap over back 0).
if rising_edge(i_CE1Hz) then
if r_array <= 7 then
r_array <= r_array + 1;
else
r_array <= 0;
end if;
o_element <= myArray(r_array); -- new output signal
end if;

Related

if statement problem while converting a vector

im new at vhdl coding, and there is a problem with if statement
so my code is the following
i want to convert a vector(bar), if the statement is true (so in this example if its smaller than 10)
process(bar)
variable tmp : integer;
begin
tmp := to_integer(signed(bar));
if tmp < 10 then
good(3) <= bar(3);
good(2) <= bar(3) xor bar(2);
good(1) <= bar(2) xor bar(1);
good(0) <= bar(1) xor bar(0);
end if;
end process;
but the problem is that the statement is not working, if i put a bigger number for example "1111" it is converting in the same way as it converted before
From the comments it seems you want good to be set to 0 whenever bar >= 10. In that case you can just do:
process(bar)
variable tmp : integer;
begin
tmp := to_integer(signed(bar));
if tmp < 10 then
good(3) <= bar(3);
good(2) <= bar(3) xor bar(2);
good(1) <= bar(2) xor bar(1);
good(0) <= bar(1) xor bar(0);
else
good <= (others => '0');
end if;
end process;
The vector good is only assigned when tmp < 10. So there is a latch inferred by this process.
You need to define what's the "else" value for good in any other conditions.
You state that
if i put a bigger number for example "1111" it is converting in the
same way as it converted before
As Tricky pointed out in a comment above, your problem is this line here:
tmp := to_integer(signed(bar));
^^^^^^
You have not posted an MCVE, so I cannot be sure, but your question implies that bar is 4 bits wide. Assuming that is the case, the value "1111" as a signed number is -1. So, if bar is set to "1111", tmp will be -1. -1 is less than 10, so this if statement will evaluate as true:
if tmp < 10 then
If you consider than "1111" is greater than 10 (ie it's 15), then you need to convert via the unsigned type, ie
tmp := to_integer(unsigned(bar));
^^^^^^^^
The range of a 4-bit signed number is -8 to +7. All the values in that range are less than 10, so your if statement will evaluate as true whatever the value of bar.
The above solution assumes that bar is always zero or positive. If that is not the case, then you need more bits in the signal bar. 5 is enough. A 5-bit signed number has the range -16 to +15.
So, I can see two solutions:
use an unsigned type in your type conversion or
make bar 5 bits
or wider.
Others have pointed out that, assuming this is synthsisable code and assuming that this is intended to be combinational logic, then you are missing a branch in your if statement; you don't drive the signal good in the case that the if statement is false and so if you were to synthesise this code as combinational logic, then you would get latches. But that is not the question you asked.

VHDL storing individual numbers of a timer into an array to display in a seven segment display

So, I have a code that shows me a timer that counts up perfectly fine and has a working multiplexer, I now want to add a way to basically store the individual value of each number (1, 10 and 100s ) so I can display them. My VHDL knowledge is really basic but here is an example :
signal n ; integer ;= 0; --this is the lap counter
type laptimeone is array (integer range <>) of integer;
type laptimeten is array (integer range <>) of integer;
type laptimehundred is array (integer range <>) of integer;
where laptimeone, ten and hundred is each of the digits I want to save in my array. and n is just there to help me find my way back to that array with another process.
begin
if (StopState = '0') then
--counter, in seconds. with pause.
if(second_clk'event and secondclk='1') then
bcd0 <= one;
bcd1 <= ten;
bcd2 <= hundred;
one <= one + 1;
if (one = 9) then
one <= 0;
ten <= ten +1;
end if;
if (ten = 9) and (one = 9) then
ten <= 0;
hundred <= hundred + 1;
end if;
if (hundred= 9) and (ten= 9) and (one= 9) then
hundred <= 0;
end if;
end if;
elsif (StopState ='1')
laptimeone(n)<= one
laptimeten(n) <= ten
laptimehundred(n) <= hundred
Now I am using some logic I know from other programming languages, but my endgame is simply that when stopstate is 1 , the timer stops, and the last numbers for one,ten and hundred are stored in my array depending on N which is a lap that I will change on another process.
How would I declare and initialize the arrays that could help me ? and am I able to do what I want to do in here in VHDL where I move my way around an array when storing and reading data by simply using that N ?

Finding the maximum value of an array in log2 time in Verilog?

I have designed a 'sorter' that finds the maximum value of its input, which is 16 31-bit words. In simulation, it works, but I am not sure if it will work in hardware (as it doesn't seem to be working on the FPGA as planned). Can someone please let me know if this will work? I am trying to save on resources, that is why I am trying to reuse the same register. Thank you...
module para_sort(clk, ready, array_in, out_max)
input clk, ready;
input [16*31-1:0] array_in;
output reg [30:0] out_max;
reg [30:0] temp_reg [0:15]
integer i, j;
always # (posedge clk)
begin
if(ready)
begin
for(j=0; j<16; j=j+1)
begin
temp_reg[j] <= array_in[31*(j+1)-1 -: 31];
end
i<=0;
done<=0;
end
else
begin
if(i<4)
begin
for(j=0; j<16; j=j+1)
if(temp_reg[j+1] > temp_reg[j]
temp_reg[((j+2)>>1)-1] <= temp_reg[j+1]
else
temp_reg[((j+2)>>1)-1] <= temp_reg[j]
i<=i+1;
end
end
if(i == 4)
begin
out_max <= temp_reg[0];
done <=1;
i <= i + 1;
end
if(i == 5)
done <=0;
end
endmodule
Sorry for the long code. If you have any questions about the code, please let me know.
Before answering the question, I assume that you do not have any problem with code syntax and semantics, and the module is part of the design so that you do not have problem with number of I/O pins, as it seems to be the case.
First of all, the algorithm that has been used in this posted code is incorrect. Maybe you meant something different, but this one is incorrect. The following code worked for me:
//The same code as you posted, but slight changes are made
//Maybe you have tried compiling this code and missed some points while posting
module para_sort(clk, ready, array_in, out_max, done);
input clk, ready;
input [16*31-1:0] array_in;
output reg [30:0] out_max;
output reg done;
reg [30:0] temp_reg [0:16];
integer i, j;
always # (posedge clk)
begin
if(ready)
begin
for(j=0; j<16; j=j+1)
begin
temp_reg[j] <= array_in[31*(j+1)-1 -: 31];
end
i<=0;
done<=0;
end
else
begin
if(i<4)
begin
for(j=0; j<16; j=j+2)
begin
if(temp_reg[j+1] > temp_reg[j])
temp_reg[((j+2)>>1)-1] <= temp_reg[j+1];
else
temp_reg[((j+2)>>1)-1] <= temp_reg[j];
end // end of the for loop
i<=i+1;
end
end
if(i == 4)
begin
out_max <= temp_reg[0];
done <=1;
i <= i + 1;
end
if(i == 5)
done <=0;
end
endmodule
If the above code does not solve the problem, then:
The problem might be with timing. In Quartus Prime software, there are netlist viewer tools (The same is true for Vivado). When you check the generated circuit, you can see paths with many combinational blocks and feedback (caused mostly by the second for loop). If the second for loop does not have enough time to complete execution in a single clock, you will loose synchronization and the results will be unpredictable.
So,
Try the above code first
If the code does not solve your problem, then try FSM (with case and if - else - if statements ) even the code becomes longer or looks uglier (not user friendly), it is more FPGA hardware friendly.

Vhdl Snake - how to automate tail implementation

I've been currently implementing the snake game in vhdl for Spartan3e.
I have already written a part that draws a cell square on VGA screen and makes it possible to move it around the square.
The problem is with tail implementation - as far I have manually added another cell segment to my snake but I would like to automate it (as for example in java simply making the queue with the cells and setting the positiong of the next cell as the cell before). I do not know how to write such a complex function in vhdl.
Here is my code:
begin
process (clk, reset, endOfGame)
begin
if reset='1' or endOfGame=true then
ball_y_reg <= to_unsigned(231,10);
ball_x_reg <= to_unsigned(311,10);
ball_x_reg_cell<=to_unsigned(231,10);
ball_y_reg_cell<=to_unsigned(311,10);
-- velocity after reset schould be none
x_delta_reg <= ("0000000000");
y_delta_reg <= ("0000000000");
elsif (clk'event and clk='1') then
ball_x_reg_cell<=ball_x_next_cell;
ball_y_reg_cell<=ball_y_next_cell;
ball_x_reg <= ball_x_next;
ball_y_reg <= ball_y_next;
x_delta_reg <= x_delta_next;
y_delta_reg <= y_delta_next;
end if;
end process;
pix_x <= unsigned(pixel_x);
pix_y <= unsigned(pixel_y);
-- refr_tick: 1-clock tick asserted at start of v-sync
-- i.e., when the screen is refreshed (60 Hz)
refr_tick <= '1' when (pix_y=481) and (pix_x=0) else
'0';
----------------------------------------------
-- pixel within wall
wall_on <=
'1' when ((WALL_X_LEFTSIDE_L<=pix_x) and (pix_x<=WALL_X_LEFTSIDE_R)) or ((WALL_X_RIGHTSIDE_L<=pix_x) and (pix_x<=WALL_X_RIGHTSIDE_R)) or ((WALL_Y_UPSIDE_U<=pix_y) and (pix_y<=WALL_Y_UPSIDE_D)) or ((WALL_Y_DOWNSIDE_U<=pix_y) and (pix_y<=WALL_Y_DOWNSIDE_D)) else
'0';
-- wall rgb output
wall_rgb <= "001"; -- blue
----------------------------------------------
-- square ball
ball_x_l <= ball_x_reg;
ball_y_t <= ball_y_reg;
ball_x_r <= ball_x_l + BALL_SIZE - 1;
ball_y_b <= ball_y_t + BALL_SIZE - 1;
ball_x_l_cell <= ball_x_reg_cell;
ball_y_t_cell <= ball_y_reg_cell;
ball_x_r_cell <= ball_x_l_cell + BALL_SIZE - 1;
ball_y_b_cell <= ball_y_t_cell + BALL_SIZE - 1;
--tail
-- pixel within squared ball
sq_ball_on <=
'1' when ((ball_x_l<=pix_x) and (pix_x<=ball_x_r) and
(ball_y_t<=pix_y) and (pix_y<=ball_y_b))
or
((ball_x_l_cell<=pix_x) and (pix_x<=ball_x_r_cell) and
(ball_y_t_cell<=pix_y) and (pix_y<=ball_y_b_cell))
else
'0';
ball_x_next <= ball_x_reg + x_delta_reg
when refr_tick='1' else
ball_x_reg ;
ball_y_next <= ball_y_reg + y_delta_reg
when refr_tick='1' else
ball_y_reg ;
ball_x_next_cell <= ball_x_reg - BALL_SIZE when refr_tick='1' and CURRENT_DIRECTION = DIR_RIGHT
else ball_x_reg + BALL_SIZE when refr_tick='1' and CURRENT_DIRECTION = DIR_LEFT
else ball_x_reg when refr_tick='1'
else ball_x_reg_cell;
ball_y_next_cell <= ball_y_reg - BALL_SIZE when refr_tick='1' and CURRENT_DIRECTION = DIR_UP
else ball_y_reg + BALL_SIZE when refr_tick='1' and CURRENT_DIRECTION = DIR_DOWN
else ball_y_reg when refr_tick='1'
else ball_y_reg_cell;
-- new bar y-position
process(ball_y_reg, ball_y_b, ball_y_t, refr_tick, btn, ball_x_reg ,ball_x_r, ball_x_l, x_delta_reg, y_delta_reg)
begin
x_delta_next <= x_delta_reg;
y_delta_next <= y_delta_reg;
if refr_tick='1' then
if btn(1)='1' and ball_y_b<(MAX_Y-1-BALL_SIZE) then
if CURRENT_DIRECTION /= DIR_UP then
CURRENT_DIRECTION <= DIR_DOWN;
y_delta_next <= BALL_V_P; -- move down
x_delta_next <= (others=>'0');
end if;
elsif btn(0)='1' and ball_y_t > BALL_SIZE then
if CURRENT_DIRECTION /= DIR_DOWN then
CURRENT_DIRECTION <= DIR_UP;
y_delta_next <= BALL_V_N; -- move up
x_delta_next <= (others=>'0');
end if;
elsif btn(2)='1' and ball_x_r<(MAX_X-1-BALL_SIZE) then
if CURRENT_DIRECTION /= DIR_LEFT then
CURRENT_DIRECTION <= DIR_RIGHT;
x_delta_next <= BALL_V_P;
y_delta_next <= (others=>'0');
end if;
elsif btn(3)='1' and ball_x_l > BALL_SIZE then
if CURRENT_DIRECTION /= DIR_RIGHT then
CURRENT_DIRECTION <= DIR_LEFT;
x_delta_next <= BALL_V_N;
y_delta_next <= (others=>'0');
end if;
end if;
if ball_x_l < WALL_X_LEFTSIDE_R or ball_y_t < WALL_Y_UPSIDE_D or ball_y_b > WALL_Y_DOWNSIDE_U or ball_x_r > WALL_X_RIGHTSIDE_L then
endOfGame <= true;
CURRENT_DIRECTION <= IDLE;
else
endOfGame <= false;
end if;
end if;
end process;
"Ball x next cell " parts is manually added second cell.
I have been searching through topics containing similiar problem but it is not covering it in vhdl.
Thanks for help!
The problem isn't VHDL - don't get lost in the language differences between VHDL and Java - these are trivial here.
The problem is synthesisability - you need a conceptual design that can be represented in hardware.
You say your Java implementation uses a queue - this will be based on a linked list, with nodes (segments) dynamically allocated, and referenced via pointers. And in fact you could straightforwardly translate that into VHDL, using access types, new and deallocate, and so on. You'd have to implement the details yourself, while there might be a convenient library, i.e. class, in Java. But that's mere detail.
Don't go down that road - access types and especially dynamic allocation aren't synthesisable - you can't normally generate and free chunks of hardware to a running system...
(But you might do that if you wanted to run an existing Snake in a simulator, in parallel with the synthesisable version, to compare their results and verify the synthesisable one matches the already proven software version. If you need a high-reliability Snake designed to military, aerospace or safety critical requirements, you'll need this step.)
You need a different mindset for hardware design, based on knowing what is physically realisable, and how to translate concepts into that.
So, instead you need to consider how you might implement a snake segment before the system starts, and only turn it on when you need it. Then consider how to create as many as you'll ever need before the system starts.
For example a segment might need to know its colour and its X/Y coordinates and some other stuff, like, is it on/visible yet. How might you represent all that?
You might decide, having played the game and reached 50 segments, that 100 is enough to win the game.
Now, records and fixed size arrays are absolutely synthesisable.
That might get you started...

vhdl code (for loop)

Description:
I want to write vhdl code that finds the largest integer in the array A which is an array of 20 integers.
Question:
what should my algorithm look like, to input where the sequential statements are?
my vhdl code:
highnum: for i in 0 to 19 loop
i = 0;
i < 20;
i<= i + 1;
end loop highnum;
This does not need to be synthesizable but I dont know how to form this for loop a detailed example explaining how to would be appreciated.
Simply translating the C loop to VHDL, inside a VHDL clocked process, will work AND be synthesisable. It will generate a LOT of hardware because it has to generate the output in a single clock cycle, but that doesn't matter if you are just simulating it.
If that is too much hardware, then you have to implement it as a state machine with at least two states, Idle and Calculating, so that it performs only one loop iteration per clock cycle while Calculating, and returns to the Idle state when done.
First of all you should know how have you defined the array in vhdl.
Let me define an array for you.
type array_of_integer array(19 downto 0) of integer;
signal A : array_of_integer :=(others => 0);
signal max : integer;
-- Now above is the array in vhdl of integers all are initialized to value 0.
A(0) <= 1;
A(1) <= 2;
--
--
A(19)<= 19;
-- Now the for loop for calculating maximum
max <= A(0);
for i in 0 to 19 loop
if (A(i) > max) then
max <= A(i);
end if;
end loop;
-- Now If you have problems in understating that where to put which part of code .. in a ----vhdl entity format .. i.e process, ports, etc... you can reply !

Resources