I have a problem with VHDL, I want to rotate the signal Checked1 and save it in itself:
Checked1<=to_stdlogicvector(to_bitvector(Checked1) ROR 1);
and I get all zeros, instead of 0100->0010
I know I can't use the same signal, but I have to change Checked1 in a loop.
How can i used it?
The whole code is here:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_arith.ALL;
use IEEE.numeric_std.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Stall_control is
Port ( EP : in STD_LOGIC_VECTOR (7 downto 0);
SP : in STD_LOGIC_VECTOR (7 downto 0);
Comp : in STD_LOGIC_VECTOR (7 downto 0);
Position : out STD_LOGIC_VECTOR (7 downto 0));
end Stall_control;
architecture Behavioral of Stall_control is
type state is (LOOP_STATE, END_STATE);
signal FSM_state: state;
signal Check: STD_LOGIC_VECTOR (7 downto 0);
signal Checked: STD_LOGIC_VECTOR (7 downto 0);
signal Checked1: STD_LOGIC_VECTOR (7 downto 0):="00000000";
signal flag: STD_LOGIC:='0';
begin
Checked<= EP;
process(EP, SP, Comp, Check, CheckED, CheckED1, FLAG)
begin
Position<= "11111111";
case FSM_state is
when LOOP_STATE=>
if((Checked AND Comp)="00000000") OR ((Checked1 AND Comp)="00000000") then
Checked1<=to_stdlogicvector(to_bitvector(Checked1) ROR 1);
--Checked<=Checked1;
--Checked1(7 downto 0)<=Checked1(0)&Checked1(7 downto 1);
flag<='0';
if(CheckED1/= SP) then
FSM_state<=LOOP_STATE;
else
FSM_state<=END_STATE;
end if;
else
flag<='1';
FSM_state<=END_STATE;
end if;
when END_STATE=>
if flag='1' then
Position<= Checked1;
else
--Position<= Checked1;
Position<= "11111111";
end if;
end case;
end process;
end Behavioral;
You are never assigning anything but all '0's to checked1.
case fsm_state is
when loop_state =>
if (checked and comp) = "00000000" or
(checked1 and comp) = "00000000" then
checked1 <= to_stdlogicvector(to_bitvector(checked1) ror 1);
flag<='0';
if checked /= sp then
fsm_state<=loop_state;
else
fsm_state<=end_state;
end if;
else
flag<='1';
fsm_state<=end_state;
end if;
checked1 has a default value of (others => '0') (all zeros) and is only rotated by 1. Of course it's going to be all zeros.
-- The ror operator returns a value that is L rotated right by R index positions. That is, if R is 0 or if L is a null array, the return
value is L. Otherwise, a basic rotate operation replaces L with a
value that is the result of a concatenation whose right argument is
the leftmost (L'Length - 1) elements of L and whose left argument is
L(L'Right). If R is positive, this basic rotate operation is repeated
R times to form the result. If R is negative, then the return value is
the value of the expression L rol -R.
It sounds like you want a different default value for checked1.
You don't need the ROR operator, you can use concatenation:
checked1 <= checked1(0) & checked1 (7 downto 1);
(Because your ROR operator R value is a constant and within the length of checked1).
And none of these now commented out packages are needed in your context clause:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_arith.all;
-- use ieee.numeric_std.all;
-- use ieee.std_logic_unsigned.all;
Not a one of the three, and there can be potential conflicts from the combination.
And the way the process sensitivity list is populated, you've created an oscillation, any signal assigned in the process that is also in the sensitivity list will cause the process to resume the next simulation cycle. Put a '1' somewhere in the default value for checked1 and rotating it will cause an event (a change of value) on checkd1 causing the process to be invoked successively.
Related
I wrote a code. This should insert a "1" at a position, which is determined by the binary part of a signal E_reg_sig. The bits left to the "1" should be filled up by the fractional bits of a signal E_reg_sig.
There are some special cases:
The position is higher than the Output signals range: then all bits are set to high
There are more bits left right to the "1" than E_reg_sig has fractional bits: In this case the output should be filled up with the bits from E_reg_sig's fractional part, the rest should be "0"s
There is less space than E_reg_sig's bits widh: In this case the code should be filled up with the Bits from E_reg_sig from MSB to LSB till there are no bits from the output to fill up anymore
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.fixed_pkg.all;
use work.parameters.all;
entity log_mvm is
port (
CLK: IN std_logic;
E_reg: IN: ufixed(counter_log_mvm_WIDTH downto -(DATA_WIDTH_IN-2));
F_reg: OUT: unsigned(DATA_WIDTH_IN-2 downto 0);
);
end log_mvm;
architecture Behavioral of log_mvm is
begin
process(clk)
variable insert_position : NATURAL;
if rising_edge(CLK) then
insert_position:= to_integer(E_reg(E_reg'high downto 0));
if insert_position > F_reg'high then
F_reg<= (others=>'1');
else
F_reg(insert_position)<='1';
if insert_position>-1 then
If insert_position>=(-E_reg'low) then
F_reg(insert_position-1 downto insert_position+E_reg'low)<=unsigned(E_reg(-1 downto E_reg'low));
else
F_reg(insert_position-1 downto 0)<=unsigned(E_reg(-1 downto -insert_position));
END if;
END IF;
end if;
END IF;
END IF;
end process;
end Behavioral;
DATA_WIDTH_IN is defined as natural with the value 8
This codes works in simulation fine, but for synthezise, there is the error "[Synth 8-7138] Expecting constant slice on LHS" on part F_reg(insert_position-1 downto 0)<=unsigned(E_reg(-1 downto -insert_position));
How to avoid this
I am using VHDL 2008 with Vivad0 2021
You have to work with a loop:
for i in F_reg'range loop
if i<=insert_position-1 then
F_reg(i) <= E_reg(i-insert_position);
end if;
end loop;
I am in the process of trying to write some code that will simply just shift a 32 bit vector left or right, with a 5 bit input that will be used for the shift amount (shamt). The issue I am having is trying to convert an std_logic_vector to an integer. My code is this:
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.STD_LOGIC_ARITH.all;
entity shiftlogical is
port(x : in std_logic_vector(31 downto 0);
shamt : in std_logic_vector( 4 downto 0);
y : out std_logic_vector(31 downto 0));
end shiftlogical;
architecture beh of shiftlogical is
signal shift : integer;
signal temp : std_logic_vector(31 downto 0);
begin
shift <= conv_integer(unsigned(shamt));
temp <= x(shift downto 0);
y <= temp;
end beh;
The code is not complete I know, but to test some ideas I am trying to pass "00010" (2) into shamt, but shift comes out to be -2147483648. But I cannot figure out why it is doing this, nor can I find any resources online that shows anything different than what I am doing. I greatly appreciate any help.
-2147483648 (-2**31) is the default initial value for integers, being the leftmost, most negative value in its range. It suggests that the signal assignment to shift has not executed. Most likely because it is a continuous assignment and there hasn't been an event on shamt to cause it to update.
std_logic_arith is not an IEEE standard library. You should use to_integer() from ieee.numeric_std instead. It is also beneficial to keep numeric ports as unsigned or signed so that your intent is clear and to minimize type conversions. Also, you cannot directly assign the variable length slice of x to temp since their lengths do not match. You should use resize() (from numeric_std) to extend the length back to 32-bits or rethink your approach.
I fixed the obvious typo in the entity name, started the simulation (ModelSim) and forced the signal shamt to "00010". Then just after trying to run for 1 ps, ModelSim complains about:
Fatal: (vsim-3420) Array lengths do not match. Left is 32 (31 downto 0). Right is 0 (-2147483648 downto 0 (null array)).
Time: 0 ps Iteration: 0 Process: /shiftlogical/line__16 File: shiftlogical.vhdl
Fatal error in Architecture beh at shiftlogical.vhdl line 16
That is because all your concurrent statements are executed in parallel. The new signal values are scheduled for the next delta cycle within the simulation. Thus, the line
temp <= x(shift downto 0);
is executed with the old value of shift which is the initial value of this signal. The initial value of an integer is -2**31 as also Kevin pointed out.
Of course you can initialize the signal shift, but the only value which will not result in an error will be 31 because in this asignment the signal on the left and the expression on the right must match in array (std_logic_vector) size. The signal shamt must be forced to "11111" as well, so that shift keeps 31.
You cannot easily fix this, because for a left shift you must add zeros at the right (LSB) and for a right shift zeros or the sign at the left (MSB).
#Martin Zabel what I had really tested there was to see if shift would hold an integer value which it did until I tried to pass it in for temp <= x(shift downto 0); What I realized was that the signal needed to really be a variable to work as intended and as follows my code consists of:
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.STD_LOGIC_ARITH.all;
entity shiftlogical is
port(x: in std_logic_vector(31 downto 0);
shamt: in std_logic_vector(4 downto 0);
dir: in std_logic;
y: out std_logic_vector(31 downto 0));
end shiftlogical;
architecture beh of shiftlogical is
begin
process(dir)
variable shift : integer;
begin
shift := conv_integer(unsigned(shamt));
if(dir = '0') then --Left shift
y(31 downto shift) <= x(31-shift downto 0);
y(shift downto 0) <= (others => '0');
elsif(dir = '1') then --Right shift
y(31-shift downto 0) <= x(31 downto shift);
y(31 downto 31-shift) <= (others => '0');
else --Always left shift
y(31 downto shift) <= x(31-shift downto 0);
y(shift downto 0) <= (others => '0');
end if;
end process;
end beh;
I've got this error in the expression "individuos(x):=cout" of the following code. What I'm trying to do is assign to each array of individuos a different random "cout" input sequentially. If I change the expression to "individuos <= cout", it'll asign the same "cout" to all "individuos", the same will happen if i trie to build a sequential statement with the assert function. How do I fix this?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_TEXTIO.ALL;
use ieee.numeric_std.all;
--package genetica_type is
--type genetica is array(0 to 49) of unsigned(7 downto 0);
--type fitness is array(0 to 49) of unsigned (2 downto 0);
--end package genetica_type;
use work.genetica_type.all;
entity conexao is
Port (
clk : in bit;
cout: in unsigned (7 downto 0);
individuos: out genetica
);
end entity;
architecture Behavioral of conexao is
--type genetica is array (0 to 49) of std_logic_vector (7 downto 0);
--signal s_individuos : genetica;
--signal i: genetica;
begin
process (clk)
begin
If (clk 'event and clk = '1') then
for x in 0 to 49 loop
individuos(x) := cout;
end loop;
end if ;
end process;
end Behavioral;
I've got this error in the expression "individuos(x):=cout" of the following code.
That is a syntax error. Use <= exactly as the compiler says.
What I'm trying to do is assign to each array of individuos a different random "cout" input sequentially. If I change the expression to "individuos <= cout", it'll asign the same "cout" to all "individuos"
That is exactly what you ask it to do :
If (clk 'event and clk = '1') then
for x in 0 to 49 loop
individuos(x) <= cout;
end loop;
end if ;
On every rising clock edge, loop 50x performing 50 assignments, each of the same data, to all 50 addresses.
What I think you want to do, is, on every clock, perform ONE assignment, and increment the address to point to the next location.
signal x : natural range 0 to individuos'high;
...
if rising_edge(clk) then
individuos(x) <= cout;
x <= x + 1 mod individuos'length;
end if;
This code has several other differences from yours:
It uses the simpler rising_edge(clk) function
It will still work when you change the size of the input array.
It still has a bug : if you change the array lower bound to something other than 0, it will fail... for example:
type genetica is array(3 to 49) of ...
Easy to catch this with an assert:
Assert individuos'low = 0 report "Array Individuos bound error" severity failure;
It also runs continuously. If you want to start and stop it, or reset the address counter, or stop when it reaches 50, that takes additional logic.
im trying to create element that would make an arithmetic mean. i have one input vector in all data should be written. and one clock input to change our input value. i looked in the internet but couldnt find result to help me to solve my problem. here is my code it works very espetial - it just works for first "some" results, and i could not understand the result. i work in Quartus 9.1. please help))
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
entity serArifmet is
generic ( r: integer :=8;
b: integer :=4);
port ( w: in signed (b-1 downto 0);
clk: in STD_LOGIC;
res: out signed (2*b-1 downto 0);
qqq: out signed(4*b-1 downto 0);
a: out signed (2*b-1 downto 0) );
end serArifmet;
architecture Arch_neuron_one of serArifmet is
type weights is array (1 to r) of signed (b-1 downto 0);
begin
process (clk, w)
variable weight: weights;
variable ost:signed(4*b-1 downto 0);
variable prod, acc, zzz: signed (2*b-1 downto 0);
variable prod2: signed (b-1 downto 0);
variable k:signed(7 downto 0);
variable eee: signed (3 downto 0);
begin
k:="00000001";
if (clk'event and clk='1') then
weight :=w & weight (1 to r-1);
end if;
acc := (others => '0');
for j in 1 to r loop
acc := acc + weight(j);
zzz:= (acc)/ k;
ost:=acc-zzz*k;
k:=k+1;
end loop;
a <= acc;
res<= zzz;
qqq<= ost;
end process;
end Arch_neuron_one;
You should remove 'w' from the sensitivity list and put the accum code inside the if (clk) statement.
Since 'w' and 'clk' are in the sensitivity list, the accum code will be evaluated each time w or clk changes. So it is probably being evaluated twice.
If you are actually trying to synthesize this, realize that the loop will unroll into a potentially deep and huge adder. As for the divide, it is an expensive operation that should ideally be avoided and may not even synthesize. If you must divide, it should be limited to powers of two, or be precomputed - calculate 1/N then implement it as a multiply. That is, x/4 = .25*x. If you have a bunch of N's, precompute them all then select the one you need.
I try to write programm on vhdl in ise 14.4 for crc16 calculation but dont understand why get "parse error, unexpected FOR" in it. Tried to put it into process but it dont works too.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity crc16 is port(
clk : in STD_LOGIC:='0');
end crc16;
architecture Behavioral of crc16 is
signal data:std_logic_vector(15 downto 0):="1010101010101010";
signal ext_data:std_logic_vector(31 downto 0);
signal crc16_original:std_logic_vector(15 downto 0):="1100000000000010";
signal crc16:std_logic_vector(15 downto 0);
signal position:std_logic_vector(5 downto 0);
signal crc_out:std_logic_vector(14 downto 0);
signal i:std_logic_vector(5 downto 0);
begin
for i in 1 to 15 loop
ext_data(i+16)<=data(i);
end loop;
for i in 1 to 15 loop
ext_data(i)<='0';
end loop;
while ext_data > "111111111111111" loop
for i in 0 to 31 loop
if ext_data(i)="1" position=i;
end loop;
crc16<= crc16_original srl 31-position;
ext_data<=ext_data xor crc16;
end loop;
for i in 0 to 14 loop
crc_out(i)<=ext_data(i);
end loop;
end Behavioral;
There are several issues to point out:
The for-loop must be in a process, so that is likely to cause the “parse error, unexpected FOR” that you see.
The relation compare with > may give unexpected result for std_logic_vector, so you may take a look at the numeric_std package for casting as for example unsigned(std_logic_vector) before comparison is made.
Compare ext_data(i) = "1" is illegal, since "1" is taken as std_logic_vector, where as ext_data(i) is std_logic; instead ext_data(i) = '1' will compile.
Illegal construction around if ext_data(i) = "1" position=i;, since no then etc.
There is an signal with identifier i, which i is also used as loop variable, with the result that position <= i is taken as an integer assign to std_logic_vector; use different names for signals and loop variables.
Assign to signal is not position = i but position <= i, like elsewhere.
Expression 31-position mixes integer and std_logic_vector, which can't be done with the selected packages. Use casting with unsigned.
The ext_data<=ext_data xor crc16 uses different size arguments, since ext_data is 32 bits and crc16 is 16 bits; this does probably not yield the expected result.
srl is not defined for std_logic_vector (VHDL-2002), so consider casting with unsigned for well-defined behavior.
Assuming that that your code is "sandbox" code, since it has no outputs.
Based on the above, you may consider doing some initial experiments with smaller designs, in order to get familiar with the different VHDL constructions, and learn how this simulates and maps to hardware; remember VHDL is a "Hardware Description Language" and not a programming language.
Below is some code that compiles in ModelSim, but is unlikely to give the expected result:
library ieee;
use ieee.std_logic_1164.all;
entity crc16 is port(
clk : in std_logic := '0');
end crc16;
library ieee;
use ieee.numeric_std.all;
architecture Behavioral of crc16 is
signal data : std_logic_vector(15 downto 0) := "1010101010101010";
signal ext_data : std_logic_vector(31 downto 0);
signal crc16_original : std_logic_vector(15 downto 0) := "1100000000000010";
signal crc16 : std_logic_vector(15 downto 0);
signal position : std_logic_vector(5 downto 0);
signal crc_out : std_logic_vector(14 downto 0);
signal i_sig : std_logic_vector(5 downto 0);
begin
process (clk) is
begin
if rising_edge(clk) then
for i in 1 to 15 loop
ext_data(i+16) <= data(i);
end loop;
for i in 1 to 15 loop
ext_data(i) <= '0';
end loop;
while ext_data > "111111111111111" loop
for i in 0 to 31 loop
if ext_data(i) = '1' then
position <= i_sig; -- TBD[Probably not right code, but compiles]
end if;
end loop;
crc16 <= std_logic_vector(unsigned(crc16_original) srl (31 - to_integer(unsigned(position))));
ext_data <= ext_data xor crc16;
end loop;
for i in 0 to 14 loop
crc_out(i) <= ext_data(i);
end loop;
end if;
end process;
end Behavioral;