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).
Related
I am trying to increment and decrement with two push-buttons. The algorithm goes well but I have a little issue. Supposedly I am incrementing , when I try to decrement the accumulator it increments once more , and only after that it start
to decrement. Same if I try to decrement first. If it is someone to help me I will be very thankfully.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.std_logic_unsigned.all;
entity my_offset_controller is
port(clk : in std_logic;
input : in std_logic_vector(15 downto 0);
add_button : in std_logic;
sub_button : in std_logic;
output_res : out std_logic_vector(15 downto 0)
);
end my_offset_controller;
architecture Behavioral of my_offset_controller is
signal buttonState_up : std_logic:='0';
signal accumulator : std_logic_vector(15 downto 0);
signal lastButtonState_up : std_logic:='0';
signal buttonState_down : std_logic:='0';
signal lastButtonState_down : std_logic:='0';
signal buttonPushCounter : integer range 0 to 512 :=0;
process(clk)
begin
if rising_edge(clk) then
buttonState_up <= add_button;
buttonState_down <= sub_button;
if (buttonState_up /= lastButtonState_up) then
if (buttonState_up ='1') then
buttonPushCounter <= buttonPushCounter + 1;
accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
end if;
lastButtonState_up <= buttonState_up;
elsif (buttonState_down /= lastButtonState_down) then
if (buttonState_down ='1') then
buttonPushCounter <= buttonPushCounter - 1;
accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
end if;
lastButtonState_down <= buttonState_down;
end if;
end if;
end process;
output_res<= accumulator + input ;
This particularly module I use to controll the offset of an signal that I plot on an vga screen.
It's hard to help you without more information. You should provide a testbench with a chronogram to make it easier. Yet, by looking at your process I would say that the problem comes from the following lines:
buttonPushCounter <= buttonPushCounter + 1;
accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
What you did there is increment buttonPushCounterat the same time that you update accumulator. This way buttonPushCounter will always be shifted by +1 or -1 depending on the last event.
What I can recommend is to update accumulator at every clock cycle instead of every time an event occurs. For example like this:
if rising_edge(clk) then
accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
...
i am trying to do an algorithm that verify prime numbers. To do this i have to make a circuit using RTL Design method, i am using the algorithm below to get the prime number:
int prime (int x) {
int i, div;
div = 0;
for (i = 1; i <= x; i++){
if (mod(x, i) == 0)
div++;
}
if (div == 2)
return 1; // PRIME
else
return 0; // NPRIME
}
To implement this solution I created two blocks: Datapath and Control like the image below:
My datapath has 4 intern blocks:
for_reg --> register that control the loop for of the prime algorithm (have a flag to indicate when the loop ends)
buffer --> Makes the output equal the input
modulo --> Get the mod of the div from the two inputs
comp --> Compare the output from modulo (if equal 0 the output of compare goes 1 else 0).
My control works comparing the input C (input C <= output_comp), if the comparison value is equal 1 I increment the signal div, after this i verify the value of the input flag, if is equal 1 i go to the finish state of the state machine that verify if the value of signal div is equal 2, if it is the output of control gets value 1, if not gets value 0 (1 - prime , 0 - not prime).
My problem is in the output of control block that stays always in 0. I've simulated all blocks separated and it seems to work correctly.
I believe the error is in the for_reg or in the control block, because the other blocks are simple and like I said before, its working correctly.
Below the simulation of the mod block:
PS.: I've used a state machine to create this block, when it gets on the final state automatically returns to the first state, so it's because of that the output stays always 0 and 3.
Below the codes from control and for_reg:
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_unsigned.ALL;
use IEEE.std_logic_arith.ALL;
ENTITY verifica_primo_control IS
PORT (
i_CLK : IN STD_ULOGIC;
i_RST : IN STD_LOGIC;
i_C : IN STD_LOGIC;
i_FLAG : IN STD_LOGIC;
o_DOUT : OUT STD_LOGIC
);
END verifica_primo_control;
ARCHITECTURE arch_1 OF verifica_primo_control IS
TYPE state_type IS (s0, s1, s2, s3);
SIGNAL stateT : state_type;
SIGNAL w_AUX : integer;
BEGIN
PROCESS(i_CLK)
BEGIN
IF rising_edge(i_CLK) THEN
IF (i_RST = '1') THEN
stateT <= s0;
w_aux <= 0;
ELSE
CASE stateT IS
when s0 => IF (i_C = '1') THEN
stateT <= s1;
ELSE
stateT <= s3;
END IF;
when s1 => w_AUX <= w_AUX +1;
if (i_FLAG = '1') then
stateT <= s2;
else
stateT <= s0;
end if;
when s2 => IF (w_AUX = 2) THEN
o_DOUT <= '1';
ELSE
o_DOUT <= '0';
END IF;
when s3 =>
if (i_FLAG = '1') then
stateT <= s2;
else
stateT <= s0;
end if;
END CASE;
END IF;
END IF;
END PROCESS;
END arch_1;
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_unsigned.ALL;
use IEEE.std_logic_arith.ALL;
ENTITY for_reg IS
PORT (
i_CLR : IN STD_LOGIC;
i_CLK : IN STD_ULOGIC;
i_X : IN UNSIGNED (7 downto 0); -- number input to verify if its prime
i_I : IN UNSIGNED (7 downto 0) ;
o_FLAG : OUT STD_LOGIC;
o_II : OUT UNSIGNED (7 downto 0)
);
END for_reg;
ARCHITECTURE arch_1 OF for_reg IS
signal w_AUX : unsigned (7 downto 0);
BEGIN
PROCESS(i_CLK)
BEGIN
IF rising_edge(i_CLK) THEN
IF (i_CLR = '1') THEN
o_II <= "00000000";
w_AUX <= "00000000";
o_FLAG <='0';
ELSIF (i_CLR ='0' AND i_I < i_X) THEN
w_AUX <= i_I;
o_II <= w_AUX + "00000001";
o_FLAG <='0';
ELSIF (i_CLR = '0' AND i_I = i_X) THEN
o_II <= i_I;
o_FLAG <= '1';
END IF;
END IF;
END PROCESS;
END arch_1;
Like i said before, i believe the error is in one of this two blocks, i believe with that codes is possible verify where is the error. If this is not enough to have the MCVE warn me that i will update the post with the the other codes that is necessary to verify the error.
I am using the quartus II simulator, so I don't have a testbanch for this, I put all the test signals manually.
After some advice on this site I've decided to use one clock FIFO. I've simulated it without errors before synthesizing it, after synthesize I've simulated code and I get this error:
** Warning: Read and Write to same address at same time. RD is unpredictable, driving RD to X
Time: 200877700 ps Iteration: 1 Instance: /testbench/FIFO/memory_tile_I_1
But simulations works like expected. After compiling I simulated again the code and I didn't get this error and simulation worked like expected.
My code is:
library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
entity FIFO is
Generic (
constant DATA_WIDTH : positive := 8;
constant FIFO_DEPTH : positive := 500
);
Port (
Clock : in STD_LOGIC;
WriteEn : in STD_LOGIC;
DataIn : in STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
ReadEn : in STD_LOGIC;
DataOut : out STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
Empty : out STD_LOGIC;
Full : out STD_LOGIC;
ModuleRESET : in STD_LOGIC
);
end FIFO;
architecture FIFO_archi of FIFO is
type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
signal Memory : FIFO_Memory;
signal Head : natural range 0 to FIFO_DEPTH - 1;
signal Tail : natural range 0 to FIFO_DEPTH - 1;
begin
-- Memory Pointer Process
process (Clock, ModuleRESET)
variable Looped : boolean;
begin
if ModuleRESET = '0' then
Head <= 0;
Tail <= 0;
Looped := false;
Full <= '0';
Empty <= '1';
DataOut <= (others => '0');
elsif rising_edge(Clock) then
if ReadEn = '1' then
if ((Looped = true) or (Head /= Tail)) then
-- Update data output
DataOut <= Memory(Tail);
-- Update Tail pointer as needed
if (Tail = FIFO_DEPTH - 1) then
Tail <= 0;
Looped := false;
else
Tail <= Tail + 1;
end if;
end if;
elsif WriteEn = '1' then
if ((Looped = false) or (Head /= Tail)) then
-- Write Data to Memory
Memory(Head) <= DataIn;
-- Increment Head pointer as needed
if (Head = FIFO_DEPTH - 1) then
Head <= 0;
Looped := true;
else
Head <= Head + 1;
end if;
end if;
end if;
-- Update Empty and Full flags
if (Head = Tail) then
if Looped then
Full <= '1';
else
Empty <= '1';
end if;
else
Empty <= '0';
Full <= '0';
end if;
end if;
end process;
end FIFO_archi;
I get this error every time I write the first data in simulation after synthesize(with synplify pro):
When I initialize the code and write first data
Every time I empty FIFO buffer and write first data
Of course I have Tail and Head at position 0 when my buffer is empty, but since I have two flags with an if-elseif istance, how it's possible I get an error on Read and Write same address?
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;
I have searched about this problem but it all seemed Greek to me so I came here as last effort.I have the following VHDL code that I want to be implemented on an fpga.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;
use work.conversions.all;
entity counter is
port ( clk_in: in std_logic; --new clock
target : in std_logic_vector(7 downto 1); --Set the target with the switches (SW7-SW1)
start : in std_logic; --Start/pause (SW0)
rst : in std_logic; --Reset (BT0)
LD : out std_logic_vector(7 downto 1); --Leds show the target at binary (LD7-LD1)
LD0 : out std_logic; --LD0 indicates thw the limit has been reached
seg : out std_logic_vector(7 downto 0); --7 segment display
digit : out std_logic_vector(3 downto 0)
);
end counter;
architecture Behavioral of counter is
begin
process(clk_in,target,rst)
variable timer : natural := 0;
variable counter : natural := 0;
variable display_counter : natural range 0 to 4 := 0;
begin
LD0 <= '0';
LD <= target; --Show the target at the leds
digit <= "1110"; --Last digit active
seg <= "00000011"; --Show zero
<--->if(rst='1') then --Reset counter
counter := 0;
timer := 0;
digit <= "1110"; --Last digit active
seg <= "00000011"; --Show zero
LD0 <= '0';
elsif rising_edge(clk_in) then
if(start = '0') then --Pause
--counter := counter;
elsif(counter = conv_integer(unsigned(target))) then --timer limit has been reached
LD0 <= '1';
else
counter := counter + 1;
display_counter := display_counter + 1;
if(counter rem 10 = 0) then --one second has elapsed (10Hz cycle)
timer := timer + 1; --increase timer
end if;
case display_counter is --Select which digits are gonna be activated and with what
when 1 =>
seg <= int2led(timer/1000);
if(int2led(timer/1000) = "00000000") then
digit(3) <= '1';
else
digit(3) <= '0';
end if;
when 2 =>
seg <= int2led((timer/100) mod 10);
if(int2led((timer/100) mod 10) = "00000000") then
digit(2) <= '1';
else
digit(2) <= '0';
end if;
when 3 =>
seg <= int2led((timer/10) mod 10);
if(int2led((timer/10) mod 10) = "00000000") then
digit(1) <= '1';
else
digit(1) <= '0';
end if;
when others =>
seg <= int2led(timer/10);
if(int2led(timer/10) = "00000000") then
digit(1) <= '1';
else
digit(1) <= '0';
end if;
end case;
if (display_counter = 4) then --reset the display counter from time to time
display_counter := 0;
else
display_counter := display_counter;
end if;
end if;
end if;
end process;
end Behavioral;
The problem is at if(rst='1') then. Can anyone explain to me in plain English why is this happening and a solution to it so I won't have the same kind problems again? Thanks in advance
You have default signal assignments before the if rst='1' then clause.
That means, when rst returns to 0 (in simulation) these default assignments will execute, and delete the reset values of those signals.
XST is telling you that the hardware can't actually do that.
The solution is to delete those default assignments, which will restore this process to a standard form. Then think carefully about what they were for and how to keep their functionality if you need to.
The traditional place for such assignments is immediately after the elsif rising_edge(clk) then clause, where they will be executed on every clock edge (provided Rst is low) then overridden by any other assignments that are executed yb the process.