Ones counter using numeric_std inside process - vhdl

I had an error while working on ones counter inside the process.
I use numeric_std library. Here is the key part of the code.
signal one_buf : unsigned(7 downto 0);
signal out_buf : std_logic_vector(7 downto 0);
counter_one : process(out_buf1)
variable one_buf1 : unsigned(7 downto 0) := (others => '0');
begin
for i in 0 to 7 loop
one_buf1 := one_buf1 + unsigned(out_buf(i));
end loop;
one_buf <= one_buf1;
end process counter_one;
The error message is
Error(10305) cannot convert type "std_ulogic" to type "UNSIGNED".
I do not understand what is wrong here.
Thanks in advance for the answers.

Related

Input data is not being loaded into registers - issues only in post-synthesis timing simulation [VHDL][Vivado] (SOLVED)

What this is
I'm trying to create a simple FIR filter. What I'm going to present you may not exactly be a FIR filter as I'm gradually increasing complexity of my project for educational purpouses till it reaches desired functionality.
What it should be doing
Basically what it should be doing so far:
load data to registers after applying load = 1,
unload processed data (which is product of multiplication of samples with corresponding coefficients) after applying start = 1.
Where it fails
However from what I've noticed it fails to load data into registers. Seems to be working like a latch, as after load drops to 0, the last vector value at input port is being latched in the registers. But I may be wrong, it just appears to be working like this in simulation.
Pre- and post-synthesis functional simulation is working! Only the post-synthesis timing is failing to work as desired!
What I've tried
Adding DONT_TOUCH parameter to entity declaration in its .vhd file,
Adding kind of buffer (unsigned variable) after data_in port from which the data is being transfered to registers - but it did not even appear in schematic after synthesis, maybe the DONT_TOUCH did not work?
Simulations pictures
Pre-synth functional - https://imgur.com/0TaNQyn
Post-synth timing - https://imgur.com/mEOv67t
Program
I'm using Vivado 2020.2 webpack
Testbench
Testbench code here: https://pastebin.pl/view/d2f9a4ad
Main code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity fir is
Port (
clk: in std_logic;
data_in: in unsigned(7 downto 0);
data_out: out unsigned(7 downto 0);
en: in std_logic;
load: in std_logic;
start: in std_logic;
reset: in std_logic
);
end fir;
architecture Behavioral of fir is
-- type coeff_array is array (0 to 7) of integer range 0 to 255;
constant reg_size: integer := 8;
constant filter_order: integer := 7;
type samples_reg is array (0 to reg_size-1) of unsigned(7 downto 0);
type coeffs_reg is array (0 to filter_order) of unsigned(7 downto 0);
begin
process(clk, reset)
-- variable coeffs: coeff_array := (0,0,0,0,0,0,0,0);
--variable b0: unsigned(7 downto 0) := 8D"0";
variable b0: unsigned(7 downto 0) := to_unsigned(1,8);
variable b1: unsigned(7 downto 0) := to_unsigned(2,8);
variable b2: unsigned(7 downto 0) := to_unsigned(3,8);
variable b3: unsigned(7 downto 0) := to_unsigned(4,8);
variable b4: unsigned(7 downto 0) := to_unsigned(5,8);
variable b5: unsigned(7 downto 0) := to_unsigned(6,8);
variable b6: unsigned(7 downto 0) := to_unsigned(7,8);
variable b7: unsigned(7 downto 0) := to_unsigned(8,8);
variable i: integer range 0 to reg_size := 0;
variable samples: samples_reg := (others => (others => '0'));
variable coeffs: coeffs_reg := (b0,b1,b2,b3,b4,b5,b6,b7);
variable data_processed: unsigned(15 downto 0) := (others => '0');
-- variable reg_element:
-- signal s1 : signed(47 downto 0) := 48D"46137344123";
begin
if reset = '1' then
-- data_out <= (others => '0');
samples := (others => (others => '0'));
data_processed := (others => '0');
i := 0;
-- synch part
elsif rising_edge(clk) and en = '1' then
samples := samples;
-- loading data
if load = '1' then
samples(i) := data_in;
i := i+1;
else null;
end if;
-- deloading data
if start = '1' then
data_processed := samples(i)*coeffs(i);
i := i+1;
else null;
end if;
-- reset counter after overflow
if(i = reg_size) then
i := 0;
else null;
end if;
-- reset counter if no data is being transferred
if load = '0' and start = '0' then
i := 0;
data_processed := (others => '0');
else null;
end if;
end if;
data_out <= data_processed(7 downto 0);
end process;
end Behavioral;
Other info
I just noticed that I'm holding load = 1 for one excessive cycle, which is why the highest number appears first.
The coefficients are: 1, 2, 3, 4, 5, 6, 7, 8.
In post-synth simulations after peeking into UUT, I've noticed that the samples registers are not loading the data (except for the last one, as I've mentioned earlier), the i is incrementing and the rest appears to be working properly.
I'll be happy to hear about some improvements for my code in addition to the problem solution!
Turns out in timing simulation I had to give the device at least 100 ns of warm-up time.
Seems like the timing simulations takes some factors related to device start-up into consideration -- anyway, I'm not sure about the explanation but I am sure of the above solution.
I have rephrased the title so others can find this post by searching for core problem in this case.
Good luck :)

Subtracting from all element of an array: VHDL

I am receiving a data. For storing that I have declared an array:
type fifo_array is array(0 to 66) of std_logic_vector(7 downto 0);
signal ins_fifo_array: fifo_array := (others => (others => '0'));
During process, this gets filled with different words(bytes). I want to subtract an offset of x30(hex) from all the elements of this array and assign it to another array for further processing. Obviously initializing it like:
type fifo_second_array is array(0 to 66) of std_logic_vector(7 downto 0);
signal ins_fifo_second_array: fifo_second_array := (ins_fifo_array - x"30");
not working. There is another solution like:
type fifo_second_array is array(0 to 66) of std_logic_vector(7 downto 0);
signal ins_fifo_second_array: fifo_second_array := (ins_fifo_array(0) - x"30",....);
Which is also not working. Please suggest.
process(ins_fifo_array)
variable I : natural;
constant C_x30 : unsigned := x"30";
begin
for I in 0 to 66 loop
ins_fifo_second_array(I) <= std_logic_vector(unsigned(ins_fifo_array(I)) - C_x30);
end loop;
end process;

VHDL - Index out range even If I made concurrent checking using when-else

I'm implementing a register file where I wanna read asynchronously and write on the rising edge.
I made concurrent checks on the addresses and the writing occurs inside a process.
However, it always cause me a fatal error and I don't know why!
Here's my code if anyone could help and tell me how can I read asynchronously and write on rising edge
Thank you!
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity RegFile is
port(
outData1 : out std_logic_vector(15 downto 0);
outData2 : out std_logic_vector(15 downto 0);
inData : in std_logic_vector(15 downto 0);
writeEn : in std_logic;
reg1Sel : in std_logic_vector(2 downto 0);
reg2Sel : in std_logic_vector(2 downto 0);
writeRegSel : in std_logic_vector(2 downto 0);
clk : in std_logic
);
end RegFile;
architecture Register_File of RegFile is
type registerFile is array(0 to 5) of std_logic_vector(15 downto 0);
signal registers : registerFile;
signal reg1Address,reg2Address : integer;
signal reg1FinalAddressing,reg2FinalAddressing : std_logic_vector(2 downto 0);
begin
--Conversion of logic vector to unsigned integer
reg1Address <= to_integer(unsigned(reg1Sel));
reg2Address <= to_integer(unsigned(reg2Sel));
reg1FinalAddressing <= reg1Sel when (reg1Address<6 ) else
(others => '0');
reg2FinalAddressing <= reg2Sel when (reg2Address<6 ) else
(others => '0');
outData1 <= registers(to_integer(unsigned(reg1FinalAddressing)));
outData2 <= registers(to_integer(unsigned(reg2FinalAddressing)));
process (clk) is
begin
-- Reading from Registers 1 and 2
if rising_edge(clk) then
-- Writing to Register file Case Enabled
if writeEn = '1' then
registers(to_integer(unsigned(writeRegSel))) <= inData;
-- Case a value being written to register file, it will be out simultaneously if
-- the register was already selected. (The updated values are being released instantly).
if reg1Sel = writeRegSel then
outData1 <= inData;
end if;
if reg2Sel = writeRegSel then
outData2 <= inData;
end if;
end if;
end if;
end process;
end Register_File;

VHDL code runs but timing diagram shows nothing

I am trying to implement a cache memory 16 * 37 in VHDL in DesignWorks 5. The code is given below.
The code runs but when i change values from IO panel or even simulate anyway, the timing diagram shows nothing and basically the code is not running for some reason. Any suggestions would be really helpful.
Code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity Cache is
port(cs, r, clr : in std_logic;
data : in std_logic_vector(31 downto 0);
addr : in std_logic_vector(7 downto 0);
cline : out std_logic_vector(31 downto 0);
ctag: out std_logic_vector(3 downto 0);
v : out std_logic);
end Cache;
architecture behav of Cache is
type RAM is array (0 to 15) of std_logic_vector(36 downto 0);
begin
process is
variable M : RAM;
variable locn : natural;
variable temp_val : std_logic_vector(36 downto 0);
variable cline_val : std_logic_vector(31 downto 0);
variable ctag_val : std_logic_vector(3 downto 0);
variable v_val : std_logic;
begin
if cs = '1' then
locn := to_integer(addr);
if r = '1' then
temp_val := M(locn);
cline_val := temp_val(31 downto 0);
ctag_val := temp_val(35 downto 32);
v_val := temp_val(36);
else
temp_val(31 downto 0) := data;
temp_val(35 downto 32) := addr(3 downto 0);
temp_val(36) := '1';
M(locn) := temp_val;
v_val := 'Z';
ctag_val:= "ZZZZ";
cline_val:= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
end if;
end if;
if clr ='1' then
locn := 0;
while(locn<16) loop
M(locn) := X"000000000" + "0";
locn:=locn+1;
end loop;
end if;
cline <= cline_val;
ctag <= ctag_val;
v <= v_val;
wait on cs;
end process;
end behav;
This line:
M(locn) := X"000000000" + "0";
appears incorrect.
M is your ram array type with an element length of 37. A 36 bit zero added to zero is still 36 bits (it doesn't look like you reached this statement, it would be a run time error).
To make a length 37 vector of '0' values use `(others => '0').
You can also use a for loop for the ram clear, you need to not use an index of 16, it's out of range, which tells us you didn't reach the clear either.
I think you ought to show us your stimulus otherwise your problems can't be reproduced.
Your missing data and addr as sensitivity elements (and ya, you case cs surrounds, but you want to build a hardware model here).
Switch to a sensitivity list (cs, data, addr).
locn is an unconstrained natural and should have a range matching the array type ram (0 to 15). Notice your while loop reaches 16. Really, use a for loop (shown below). The reason for constraining locn is to prevent a bound error when accessing ram(locn).
Note for converting addr to a natural (locn) you need to AND mask addr with a length four run of '1's to prevent a range error for normal ram operations.
The package numeric_std is an affectation, it's easier than passing a couple of command line options to ghdl (ieee=synopsys -fexplict) during analysis and elaboration.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity cache is
port (
cs, r, clr: in std_logic;
data: in std_logic_vector(31 downto 0);
addr: in std_logic_vector(7 downto 0);
cline: out std_logic_vector(31 downto 0);
ctag: out std_logic_vector(3 downto 0);
v: out std_logic
);
end entity;
architecture behav of cache is
type ram is array (0 to 15) of std_logic_vector(36 downto 0);
begin
process (cs, data, addr)
variable m : ram;
variable locn : natural range (ram'range);
variable temp_val : std_logic_vector(36 downto 0);
variable cline_val : std_logic_vector(31 downto 0);
variable ctag_val : std_logic_vector(3 downto 0);
variable v_val : std_logic;
begin
if cs = '1' then
locn := to_integer(unsigned(addr and x"0F"));
if r = '1' then
temp_val := m(locn);
cline_val := temp_val(31 downto 0);
ctag_val := temp_val(35 downto 32);
v_val := temp_val(36);
else
temp_val(31 downto 0) := data;
temp_val(35 downto 32) := addr(3 downto 0);
temp_val(36) := '1';
m(locn) := temp_val;
v_val := 'Z';
ctag_val:= "ZZZZ";
cline_val:= (others => 'Z');
end if;
end if;
if clr ='1' then
for i in ram'range loop
m(i) := (others => '0');
end loop;
end if;
cline <= cline_val;
ctag <= ctag_val;
v <= v_val;
end process;
end architecture;
This code analyzes and elaborates, you could have an error somewhere I didn't mention, and bound (range) errors show up at run time in assignments (expressions can not care).
And one final bit:
temp_val(31 downto 0) := data;
temp_val(35 downto 32) := addr(3 downto 0);
temp_val(36) := '1';
can be expressed:
temp_val:= '1' & addr(3 downto 0) & data;
As well as:
locn := to_integer(addr);
expressed as:
locn := to_integer(addr(3 downto 0));
You can also create an AND mask with a length defined algorithmically from the ram'range should you set the ram size with a generic.
And without seeing your stimulus there are several places that could cause run time errors. Check your console output.

VHDL multiple constant drivers

I'm trying to modify a source code for do a sum (for example) and other maths function using switch and hex display.
This is the main code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.seven_segment_pkg.all;
entity Switch7Segment is
port (
SW : in std_logic_vector(9 downto 0);
HEX0 : out std_logic_vector(6 downto 0);
HEX1 : out std_logic_vector(6 downto 0);
HEX2 : out std_logic_vector(6 downto 0);
HEX3 : out std_logic_vector(6 downto 0);
KEY : in std_logic_vector(3 downto 0);
CLOCK_50 : in std_logic
);
end entity Switch7Segment;
architecture behavior of Switch7Segment is
signal segments1 : std_logic_vector(13 downto 0);
signal segments2 : std_logic_vector(13 downto 0);
signal segmentsR : std_logic_vector(13 downto 0); -- Range changed from 27 downto 0 to allow compile
signal input1 : integer;
signal input2 : integer;
signal result : unsigned(31 downto 0); -- Range added to allow compile
signal temp : integer;
begin
input1 <= to_integer(unsigned(SW(4 downto 0)));
input2 <= to_integer(unsigned(SW(9 downto 5)));
segments1 <= unsigned_to_seven_segment(value => unsigned(SW(4 downto 0)), number_of_digits => 2, value_is_bcd => false);
segments2 <= unsigned_to_seven_segment(value => unsigned(SW(9 downto 5)), number_of_digits => 2, value_is_bcd => false);
HEX1 <= segments1(13 downto 7);
HEX0 <= segments1(6 downto 0);
HEX3 <= segments2(13 downto 7);
HEX2 <= segments2(6 downto 0);
process(CLOCK_50)
begin
if (CLOCK_50' EVENT and CLOCK_50 = '1' AND KEY(0) = '1') then
temp <= input1+input2;
result <= to_unsigned(integer(temp), result'length);
segmentsR <= unsigned_to_seven_segment(value => unsigned(result), number_of_digits => 2, value_is_bcd => false);
HEX1 <= segmentsR(13 downto 7);
HEX0 <= segmentsR(6 downto 0);
end if;
end process;
end architecture;
And then there is the package:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package seven_segment_pkg is
-- Return a std_logic_vector ready for driving a number of 7-segment displays.
function unsigned_to_seven_segment(value : unsigned; number_of_digits : integer; value_is_bcd : boolean)
return std_logic_vector;
end;
package body seven_segment_pkg is
function seven_seg_from_bcd_digit(bcd_digit : std_logic_vector(3 downto 0)) return std_logic_vector is
begin
case bcd_digit is
-- abcdefg
when x"0" => return "1000000";
when x"1" => return "1111001";
when x"2" => return "0100100";
when x"3" => return "0110000";
when x"4" => return "0011001";
when x"5" => return "0010010";
when x"6" => return "0000010";
when x"7" => return "1111000";
when x"8" => return "0000000";
when x"9" => return "0010000";
when x"a" => return "0001000";
when x"b" => return "0000011";
when x"c" => return "1000110";
when x"d" => return "0100001";
when x"e" => return "0000110";
when x"f" => return "1110001";
when others => return "0000000";
end case;
end function;
-- Return a vector ready for driving a series of 7-segment displays.
function unsigned_to_seven_segment(
value : unsigned;
-- Number of 7-segment displays (determines output vector width: W = 7*N)
number_of_digits : integer;
-- When true, treat the input value as a BCD number where every 4 bits hold one
-- digit from 0 to A. When false, treat the input number as an unsigned integer.
value_is_bcd : boolean
) return std_logic_vector is
variable segments : std_logic_vector(number_of_digits*7-1 downto 0);
variable bcd_quotient : unsigned(value'range);
variable bcd_remainder : unsigned(3 downto 0);
begin
if value_is_bcd then
for i in 0 to number_of_digits-1 loop
segments(i*7+6 downto i*7) := seven_seg_from_bcd_digit(
std_logic_vector(value(i*4+3 downto i*4))
);
end loop;
else
bcd_quotient := value;
for i in 0 to number_of_digits-1 loop
bcd_remainder := resize(bcd_quotient mod 10, 4);
bcd_quotient := bcd_quotient / 10;
segments(i*7+6 downto i*7) := seven_seg_from_bcd_digit(
std_logic_vector(bcd_remainder)
);
end loop;
end if;
return segments;
end function;
end package body;
I think that there is an error that at the moment i never signed here that is the length of the result. if we compile this VHDL code Quartus will tell us that the function is for 13 element and not for 27. But i don't see an obstacle to resolve it....my problem is about outputs (HEX0.....HEX3)
If i modify the code and i insert
signal segmentsR: std_logic_vector(13 downto 0);
I resolve the problem of the length but i will see error 10028 (multiple constant drivers).
If i understood correct, i can't assign two times at the same vector two different value or something similar is correct? maybe i always think like a C++ / C programmer. I think that if i use CLOCK the problem will be resolve but is not true...
The problem is that there are drivers for HEX0 and HEX1 both before the process and in the process, but any signal/port should only be driven from one place in typical synthesized code.
If the HEX0 and HEX1 are driven from the process, then remove the drivers before the process.
Conceptually, a multiple drivers error means that your behavioral code (remember: VHDL describes how a circuit works) isn't able to be synthesized. Or, if you have really special synthesizing code, it will give you unexpected results.
In my experience, this error results when I write code with undefined behavior -- for example, if in two processes I modify the same variable (say, X) based on some condition, then the hardware could run into an undefined state where both conditions are met -- how should the variable be modified? If you are familiar to race conditions or mutual exclusion, this should look familiar. Hardware languages don't have easy support for mutex and the like, so they warn you and won't let you do the bad thing.
In your case, I think you could clarify your code and simplify things by assigning default values to your top-level ports, like so:
entity Switch7Segment is
port (
SW : in std_logic_vector(9 downto 0);
HEX0 : out std_logic_vector(6 downto 0);
HEX1 : out std_logic_vector(6 downto 0) := (others => '0');
HEX2 : out std_logic_vector(6 downto 0) := (others => '0');
HEX3 : out std_logic_vector(6 downto 0);
KEY : in std_logic_vector(3 downto 0);
CLOCK_50 : in std_logic
);
end entity Switch7Segment;
This provides a default value for an entity. Whatever creates the entity can provide a different value than the default. Read more here: http://vhdl.renerta.com/mobile/source/vhd00051.htm
It looks like your default value is more complicated (based on the inputs of the function). In this case, I would either (1) change my interface so that the caller provides the information or (2) write a function and a constant in a package and use the function/constant as the default value.
Another possible solution is using generics and default value. This would let you use the bits of the SW field in you default values. (ie: something like HEX2 : out std_logic_vector(6 downto 0) := (SW(xx downto yy), where SW is defined in the generics port)

Resources