VHDL explanation in words - vhdl

I started with VHDL course for beginners a few days ago.
I’ve got a code (under) and I’m trying to understand what kind of circuit it shows and how the different steps are functioning.
I’ve been looking around fore a while now in the Internet but can’t really understand what it does? So I thought someone who now this might give me some explanations’? :.-)
I`m not sure but I think it is a type of an “adder” with a buffer? And the buffer is working with 2 bits (Cs-1 downto 0) however I don’t know what Cs means….in fact there is a lot of things in this code I don’t understand.
I would really appreciate if some one would take some time to help me understand the code in words.
entity asc is
generic (CS : integer := 8)
port (k, ars, srs, e, u: in std_logic;
r: buffer std_logic_vector(Cs-1 downto 0));
end asc;
architecture arch of asc is
begin
p1: process (ars, k) begin
if ars = ‘1’ then
r <= (others => ‘0’);
elsif (k’event and k=’1’) then
if srs=’1’ then
r <= (others) => ‘0’);
elsif (e = ‘1’ and u = ‘1’) then
r <= r + 1;
elsif (e = ‘1’ and u = ‘0’) then
r <= r - 1;
else
r <= r;
end if;
end if;
end process;
end arch;

I renamed the inputs and outputs of your entity with Sigasi HDT (and corrected some syntax errors) which should make a lot more clear your entity does. I did following renames:
k -> clock
ars -> asynchronous_reset
srs -> synchronous_reset
e -> enable
u -> count_up
r-> result
If enable is asserted and count_up is true, the result (r) will be incremented on a rising clock edge. If count_up is false, the result will be decremented if enable is true on a rising clock edge.
entity asc is
generic (resultWidth : integer := 8);
port (clock, asynchronous_reset, synchronous_reset, enable, count_up: in std_logic;
result: buffer std_logic_vector(resultWidth-1 downto 0)
);
end asc;
architecture arch of asc is
begin
p1: process (asynchronous_reset, clock) begin
if asynchronous_reset = '1' then
result <= (others => '0');
elsif (rising_edge(clock)) then
if synchronous_reset='1' then
result <= (others => '0');
elsif (enable = '1' and count_up = '1') then
result <= result + 1;
elsif (enable = '1' and count_up = '0') then
result <= result - 1;
else
result <= result;
end if;
end if;
end process;
end arch;
Be careful when using this code snippet:
This architecture seems to be using deprecated libraries: what does adding 1 to a std_logic_vector mean? Please use the signed datatype instead. This way it is predictable what will happen if you decrement zero.
This entity will not warn you for overflow

Related

Delay in Simulation of Output with regard to Input

I am making a MultiLevel Car Parking system module with consist of common entry and exit, The idea is that, when I get input stimulus from signal car entry or car exit, It will check the car's Type and then the output should display the level reserved for the particular type where, the car should go, If the slots reserves for particular type is full then the display should output as such. The code gets stimulated through the output gets displayed only after the next clock cycle after the input stimulus is given.
I have tried using a different if-else block for counting operations and also with different process using a flag, and tried to change it to different if-else blocks, but it's still the same. I am beginner to vhdl the execution of statements is quite confusing, and online search is of little help, please help me where did I go wrong?
library ieee;
use ieee.std_logic_1164.all;
use ieee.Numeric_std.all;
use work.Parking_Package.all;
entity CarPark is
port( clk :in std_logic;
rst : in std_logic;
car_in : in std_logic;
Car_out : in std_logic;
Ent_car_type : car_type;
Ext_car_type : car_type;
Status : out level
);
end CarPark;
architecture behave of CarPark is
signal count : counter;
begin
SLOT_CHECKING: process(rst,clk)
begin
if(rst= '1')then
count <= (others => 0);
Status <= FULL;
elsif(rising_edge(clk))then
if(car_in )then
case(Ent_car_type)is
when Admin =>
if(count(Admin) < 5) then
Status <= L1;
count(Admin) <= count(Admin) +1;
else
Status <= FULL;
end if;
when Staff =>
if(count(Staff) < 5) then
Status <= L2;
count(Staff) <= count(Staff) + 1;
else
Status <= FULL;
end case;
end if;
elsif(car_out)then
case(Ext_car_type)is
when Admin =>
if(count(Admin) >0) then
Status <= L1a;
count(Admin) <= count(Admin) - 1;
else
count(Admin)<= 0;
end if;
when Staff =>
if(count(Staff) >0) then
Status <= L2a;
count(Staff) <= count(Staff) - 1;
else
count(Staff) <= 0;
end if;
end process;
end behave;
The user defined packages is given below
library ieee;
use ieee.std_logic_1164.all;
use ieee.Numeric_std.all;
package Parking_Package is
type car_type is (Admin, Staff);
type level is (L1, L2a, FULL);
type counter is array (Staff downto Admin) of integer range 0 to 22;
end Parking_Package;
package body Parking_Package is
end Parking_Package;
After initializing using reset, I give input of car_in as 1 and
car_type as Admin, The output gets displayed as L1 in the Next Clock
and if I force the value of car_type as staff, The corresponding output is simulated in the next clock cycle.
![ScreenShot Simulation] https://imgur.com/a/B6cqADn
Firstly, some comments :
Your application (MultiLevel Car Parking) is not very adapted to VHDL language. It's too high level. Your coding style is a bit object oriented (type and variable names).
There are syntax errors in your code (I assume you already know it because You achieve to have a simulation screen).
The behavior that you expect on the first clock cycle implies that your output will be the product of combinational logic. It's better to have outputs directly from flip flops.
Then the code that you can use to have the expected behavior with 2 process (One purely sequential, the other purely combinational) :
signal current_count : counter;
signal next_count : counter;
signal current_status : level;
signal next_status : level;
begin
SEQ : process(rst_tb, clk_tb)
begin
if (rst_tb = '1') then
current_count <= (others => 0);
current_status <= FULL;
elsif (rising_edge(clk_tb)) then
current_count <= next_count;
current_status <= next_status;
end if;
end process;
SLOT_CHECKING : process(current_count, current_status, car_in, car_out, Ent_car_type, Ext_car_type)
begin
next_count <= current_count;
next_status <= current_status;
if (car_in = '1') then
case (Ent_car_type) is
when Admin =>
if (current_count(Admin) < 5) then
next_status <= L1;
next_count(Admin) <= current_count(Admin) + 1;
else
next_status <= FULL;
end if;
when Staff =>
if (current_count(Staff) < 5) then
next_status <= L2;
next_count(Staff) <= current_count(Staff) + 1;
else
next_status <= FULL;
end if;
end case;
elsif (car_out = '1') then
case (Ext_car_type) is
when Admin =>
if (current_count(Admin) > 0) thenremarques
next_status <= L1a;
next_count(Admin) <= current_count(Admin) - 1;
else
next_count(Admin) <= 0;
end if;
when Staff =>
if (current_count(Staff) > 0) then
next_status <= L2a;
next_count(Staff) <= current_count(Staff) - 1;
else
next_count(Staff) <= 0;
end if;
end case;
end if;
end process;
count <= next_count ;
Status <= next_status ;
Warning, with this code the outputs are directly from combinational logic : It's not recommended but it is the only way to get the behavior you expect.
If this application is only a practise, I advice you too to take another example more adapted to VHDL : filter, SPI communication, processing unit, ...

VHDL frequency divider code

I have this code:
architecture Behavioral of BlockName is
signal t: std_logic;
signal c : std_logic_vector (1 downto 0);
begin
process (reset, clk) begin
if (reset = '1') then
t <= '0';
c <= (others=>'0');
elsif clk'event and clk='l' then
if (c = din) then
t <= NOT(t);
c <= (others=>'0');
else
c <= c + 1;
end if;
end if;
end process;
dout <= t;
end Behavioral;
This code's role is to divide the frequency when it gets input (clock + value) and outputs a divided frequency.
Now my questions:
What does this c <= (others=>'0'); mean ?
What value does t get here t <= NOT(t); ? the last t value? does the <= work as = ?
c <= (others=>'0'); is equivalent to c <= "00";
t <= not(t); assigns to t the opposite of the current value in t.
= is an equality comparison in VHDL.
<= is signal assignment in VHDL.
since 'C' is taken as a vector and to store every bit of it with zero 'c <= (others=>'0');' was used and the concept of blocking and non blocking signals is not present in VHDL. here '=' is used to compare and '<=' is used to assign the signal.
In the your code 't' is declared as a signal and a signal will be updated at the end of the every iteration of the process block. so in the statement 't <= NOT(t);' the value of the t is still the old value and will be updated at the end of the current simulation tick.

Cannot create latch and counter with 2 clock signals in VHDL

I am completely new to programming CPLDs and I want to program a latch + counter in Xilinx ISE Project Navigator using VHDL language. This is how it must work and it MUST be only this way: this kind of device gets 2 clock signals. When one of them gets from HIGH to LOW state, data input bits get transferred to outputs and they get latched. When the 2nd clock gets from LOW to HIGH state, the output bits get incremented by 1. Unfortunately my code doesn't want to work....
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity counter8bit is
port(CLKDA, CLKLD : in std_logic;
D : in std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0));
end counter8bit;
architecture archi of counter8bit is
signal tmp: std_logic_vector(7 downto 0);
begin
process (CLKDA, CLKLD, D)
begin
if (CLKLD'event and CLKLD='0') then
tmp <= D;
elsif (CLKDA'event and CLKDA='1') then
tmp <= tmp + 1;
end if;
end process;
Q <= tmp;
end archi;
Is there any other way around to achieve this?? Please for replies. Any kind of help/suggestions will be strongly appreciated. Many thanks in advance!!
Based on the added comments on what the counter is for, I came up with the following idea. Whether it would work in reality is hard to decide, because I would need a proper timing diagram for the EPROM interface. Importantly, there could be clock domain crossing issues depending on what restrictions there are on how the two clock signals are asserted; if there can be a falling edge of CLKLD close to a rising edge of CLKDA, the design may not work reliably.
signal new_start_address : std_logic := '0';
signal start_address : std_logic_vector(D'range) := (others => '0');
...
process (CLKLD, CLKDA)
begin
if (CLKDA = '1') then
new_start_address <= '0';
elsif (falling_edge(CLKLD)) then
start_address <= D;
new_start_address <= '1';
end if;
end process;
process (CLKDA)
begin
if (rising_edge(CLKDA)) then
if (new_start_address = '1') then
tmp <= start_address;
else
tmp <= tmp + 1;
end if;
end if;
end process;
I'm not completely clear on the interface, but it could be that the line tmp <= start_address; should become tmp <= start_address + 1;
You may also need to replace your assignment of Q with:
Q <= start_address when new_start_address = '1' else tmp;
Again, it's hard to know for sure without a timing diagram.

Error(10820) and (10822) VHDL

i am trying to write a code but i get error, i dont understand that, i am new to vhdl, any help would be appreciated.
code:
entity counter is
port
(
upp_down : in std_logic;
rst : in std_logic;
pressed : in std_logic;
count : out std_logic_vector(3 downto 0)
);
end entity;
architecture rtl of counter is
signal count_value: std_logic_vector(3 downto 0);
begin
process (rst,pressed,upp_down)
begin
if(rst'event and rst = '0') then
count <= "0000";
else
if(pressed'event and pressed = '0' ) then
if(upp_down = '1') then
count_value <= count_value + 1;
elsif(upp_down = '0') then
count_value <= count_value - 1;
end if;
end if;
end if;
end process;
count <= count_value;
end rtl;
Errors:
Error (10820): Netlist error at counter.vhd(28): can't infer register for count_value[1] because its behavior depends on the edges of multiple distinct clocks
Error (10822): HDL error at counter.vhd(28): couldn't implement registers for assignments on this clock edge
The first problem is that you're trying to use the edge of two different 'clocks' in one process. A particular process can only respond to one clock.
The second problem is that your code does not translate into any real-world hardware. There's nothing in the FPGA that can respond to there not being an edge of a clock, which is what you have described with your if(rst'event and rst = '0') then else structure.
Nicolas pointed out another problem (which your compiler didn't get as far as), which is that you're assigning count both inside and outside a process; this is not allowed, as signals can only be assigned in one process.
Generally the type of reset it looks like you're trying to implement would be written as in the example below:
process (rst,pressed,upp_down)
begin
if(rst = '0') then
count_value <= "0000";
elsif(pressed'event and pressed = '0' ) then
if(upp_down = '1') then
count_value <= count_value + 1;
elsif(upp_down = '0') then
count_value <= count_value - 1;
end if;
end if;
end process;
count <= count_value;
The reason for changing the reset to affect count_value, is that without this, the effect of your reset would only last one clock cycle, after which the count would resume from where it left off (Thanks #Jim Lewis for this suggestion).
In addition to your compile errors, you should try to use the rising_edge() or falling_edge() functions for edge detection, as they behave better than the 'event style.
The reset can be more easily implemented using count_value <= (others => '0'); this makes all elements '0', no matter how long count is.
Lastly, it looks like you're using the std_logic_arith package. There are many other answers discouraging the use of this package. Instead, you should use the numeric_std package, and have your counter of type unsigned. If your output must be of type std_logic_vector, you can convert to this using a cast: count <= std_logic_vector(count_value);.
One more thing, I just noticed that your counter is not initialised; this can be done in the same way as I suggested for the reset function, using the others syntax.
"count" can't be assigned inside and outside a process.
count <= "0000"; <-- inside process
count <= count_value; <-- outside process.
You should do "count <= count_value;" inside your process :
entity counter is
port
(
upp_down : in std_logic;
rst : in std_logic;
pressed : in std_logic;
count : out std_logic_vector(3 downto 0)
);
end entity;
architecture rtl of counter is
signal count_value: std_logic_vector(3 downto 0);
begin
process (rst,pressed,upp_down)
begin
if(rst'event and rst = '0') then
count <= "0000";
else
if(pressed'event and pressed = '0' ) then
if(upp_down = '1') then
count_value <= count_value + 1;
elsif(upp_down = '0') then
count_value <= count_value - 1;
end if;
count <= count_value;
end if;
end if;
end process;
end rtl;

LIFO memory vhdl code understanding

I have this code for a lifo memory and I don't understand why on 27 line (if(last = n-2) then full <= '1'; end if;) the last signal it's not equal to n-1.
If anyone could explain it to me I would really appreciate.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity lifo is
generic(n : natural := 4);
port(Din : in std_logic_vector(3 downto 0);
Dout : out std_logic_vector(3 downto 0);
wr : in std_logic;
rd : in std_logic;
empty, full : out std_logic;
clk : in std_logic);
end entity lifo;
architecture arh of lifo is
type memorie is array(0 to n-1) of std_logic_vector(3 downto 0);
signal mem : memorie := (others => (others => '0'));
signal last : integer range -1 to n-1;
begin
process(clk)
begin
if (rising_edge(clk)) and (wr = '1') then
if (last = n-1) then null;
else
if(last = n-2) then full <= '1'; end if;
if(last = -1) then empty <= '0'; end if;
mem(last + 1) <= Din;
last <= last + 1;
end if;
elsif (rising_edge(clk)) and (rd = '1') then
if(last = -1) then null;
else
Dout <= mem(last);
last <= last - 1; full <= '0';
if(last = -1) then empty <= '1'; end if;
end if;
end if;
end process;
end architecture arh;
The last is in range -1 to n-1, and when last is n-1 then it indicates full LIFO, and full must be high ('1').
When a write is accepted, then last is incremented by 1 with last <= last + 1. On the same rising clk edge it is determined if full should go high, which is the case if this write will make the LIFO full. After the write, then last has the value last+1 (the +1 when write is accepted) and LIFO is full if is equals n-1 (with n-1 indicating full). So the condition for full after this write is last+1=n-1, which is then written as last = n-2.
In addition, it is possible to improve the code in several ways if it does not work right away, e.g. single rising_edge(clk), add reset, skip the null statements through negated condition, add handling of write and read operation in same cycle, remove dead code (the final if).

Resources