Can't normally see result in wave (Modesim) - vhdl

I have code designed for Vivid software. How I can translate this code into ModelSIM? In vivado, I should get the following values, but in modelsim I get completely different ones.
This is noise generator. Successful in adding pseudorandom noise sequence to our sine wave, but now we are trying to add Gaussian noise. The code and the simulation results for ADDITION OF PSEUDORANDOM NOISE SEQUENCE TO SINE WAVE IS GIVEN BELOW:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL; --try to use this library as much as possible.
entity sine_wave is
generic ( width : integer := 4 );
port (clk :in std_logic;
random_num : out std_logic_vector (width-1 downto 0);
data_out : out STD_LOGIC_VECTOR(7 downto 0)
);
end sine_wave;
architecture Behavioral of sine_wave is
signal data_out1,rand_temp1,noisy_signal : integer;
signal noisy_signal1 : STD_LOGIC_VECTOR(7 downto 0);
signal i : integer range 0 to 29:=0;
--type memory_type is array (0 to 29) of integer;
type memory_type is array (0 to 29) of std_logic_vector(7 downto 0);
--ROM for storing the sine values generated by MATLAB.
signal sine : memory_type := ("01001101","01011101","01101100","01111010","10000111","10010000","10010111","10011010","10011010");
--hi
begin
process(clk)
variable rand_temp : std_logic_vector(width-1 downto 0):=(width-1 => '1',others => '0');
variable temp : std_logic := '0';
begin
--to check the rising edge of the clock signal
if(rising_edge(clk)) then
temp := rand_temp(width-1) xor rand_temp(width-2);
rand_temp(width-1 downto 1) := rand_temp(width-2 downto 0);
rand_temp(0) := temp;
--data_out <= sine(i);
i <= i+ 1;
if(i = 29) then
i <= 0;
end if;
end if;
data_out <= sine(i);
data_out1<=to_integer(unsigned(sine(i)));
random_num <= rand_temp;
rand_temp1<=to_integer(unsigned(rand_temp));
noisy_signal<=data_out1+rand_temp1;
noisy_signal1<= std_logic_vector(to_signed(noisy_signal,8));
end process;
end Behavioral;
Vivado
ModelSIM

Related

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 Moving average: simulation & synthesis result differ (Vivado)

For my project I need to reduce a noise of an ADC output and implemented a simple moving average filter in VHDL.
Although it works in simulation (see the picture):
it has some strange behavior if I display it on the chipscope when the system is running in FPGA (see the picture):
The VHDL code I use for the moving average is as follows:
library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
use ieee.numeric_std.all;
entity moving_avg is
generic(
SAMPLES_COUNT : integer := 32
);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
sample_i : in std_logic_vector(11 downto 0);
avg_o : out std_logic_vector(11 downto 0)
);
end;
architecture rtl of moving_avg is
type sample_buff_t is array (1 to SAMPLES_COUNT) of std_logic_vector(11 downto 0);
signal sample_buffer : sample_buff_t;
signal sum : std_logic_vector(31 downto 0);
constant wid_shift : integer := integer(ceil(log2(real(SAMPLES_COUNT))));
signal avg_interm_s : std_logic_vector(31 downto 0);
begin
process (clk_i, rst_n_i) begin
if rst_n_i='1' then
sample_buffer <= (others => sample_i);
sum <= std_logic_vector(unsigned(resize(unsigned(sample_i), sum'length)) sll wid_shift) ;
elsif rising_edge(clk_i) then
sample_buffer <= sample_i & sample_buffer(1 to SAMPLES_COUNT-1);
sum <= std_logic_vector(unsigned(sum) + unsigned(sample_i) - unsigned(sample_buffer(SAMPLES_COUNT)));
end if;
end process;
avg_interm_s <= std_logic_vector((unsigned(sum) srl wid_shift));
avg_o <= avg_interm_s(11 downto 0);
end;
I use Xilinx Vivado tool 2015.2 running on Ubuntu 14.04 x64.
Could you please help me to identify the problem, such
that results in simulation correspond to results after synthesis?

VHDL code to find square root of number?

Is there is any in built function or any library that can be included in the design to find square root of a number?
Restoring square root algorithm is easy to implement on fpga, wikipedia has an example.
FPGA vendors should have cores available, it hides inside the general purpose CORDIC core on Xilinx. They also have square root cores for floating points, if that's what you need.
For non-synthesizable (simulation/test-bench only) operation, square root for real can be done with:
y := math_real.sqrt(x)
For synthesizable operation, see answer from Jonathan Drolet.
This one worked for me.
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_unsigned.ALL;
entity squart is port(
clock : in std_logic;
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(3 downto 0)); end squart;
architecture behaviour of squart is
signal part_done : std_logic := '0';
signal part_count : integer := 3;
signal result : std_logic_vector(4 downto 0) := "00000";
signal partialq : std_logic_vector(5 downto 0) := "000000";
begin
part_done_1: process(clock, data_in, part_done)
begin
if(clock'event and clock='1')then
if(part_done='0')then
if(part_count>=0)then
partialq(1 downto 0) <= data_in((part_count*2)+ 1 downto part_count*2);
part_done <= '1'; else
data_out <= result(3 downto 0);
end if;
part_count <= part_count - 1;
elsif(part_done='1')then
if((result(3 downto 0) & "01") <= partialq)then
result <= result(3 downto 0) & '1';
partialq(5 downto 2) <= partialq(3 downto 0) - (result(1 downto 0)&"01");
else
result <= result(3 downto 0) & '0';
partialq(5 downto 2) <= partialq(3 downto 0);
end if;
part_done <= '0';
end if;
end if;
end process;
end behaviour;
Check this one:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity SQRT is
Generic ( b : natural range 4 to 32 := 16 );
Port ( value : in STD_LOGIC_VECTOR (15 downto 0);
result : out STD_LOGIC_VECTOR (7 downto 0));
end SQRT;
architecture Behave of SQRT is
begin
process (value)
variable vop : unsigned(b-1 downto 0);
variable vres : unsigned(b-1 downto 0);
variable vone : unsigned(b-1 downto 0);
begin
vone := to_unsigned(2**(b-2),b);
vop := unsigned(value);
vres := (others=>'0');
while (vone /= 0) loop
if (vop >= vres+vone) then
vop := vop - (vres+vone);
vres := vres/2 + vone;
else
vres := vres/2;
end if;
vone := vone/4;
end loop;
result <= std_logic_vector(vres(result'range));
end process;
end;

Using array of std_logic_vector as a port type, with both ranges using a generic

Is it possible to create an entity with a port that is an array of std_logic_vectors, with both the size of the array and the std_logic_vector coming from generics? Ie. is it possible to create eg. a bus multiplexer with both the bus width and bus count configurable?
entity bus_multiplexer is
generic (bus_width : positive := 8;
sel_width : positive := 2);
port ( i : in array(integer range 2**sel_width - 1 downto 0) of std_logic_vector(bus_width - 1 downto 0);
sel : in std_logic_vector(sel_width - 1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer;
architecture dataflow of bus_multiplexer is
begin
o <= i(to_integer(unsigned(sel)));
end dataflow;
The above doesn't seem to work because the array type needs to be defined separately.
Defining the type before the port also does not work, as then it expects the entity definition to end after it. Defining it after the port definition doesn't work since it'd be used before that. Defining it in a package doesn't work because the type definition doesn't seem to like having an unconstrained range in the "base type".
Is it possible to somehow do this in VHDL-93? (What about VHDL-2008?)
Defining the type as array(natural range <>, natural range <>) of std_logic in the package works - as in the port definition doesn't give an error - but actually using it if it's defined that way seems to be quite unwieldy.
Is there some sane way to use it like this? Is there some simple way to map N separate std_logic_vectors to a port defined like that, and likewise for the actual output logic?
I tried the original and o <= i(to_integer(unsigned(sel)), bus_width - 1 downto 0), but neither worked. I know I could do it one bit at a time, but I'd prefer something simpler. And while the bit-by-bit -approach might be okay for the internal implementation, I certainly wouldn't want to have to do that for the port mapping every time I use the component...
Is there some sane(-ish) way to do this?
(Addendum: I know there are some similar questions, but most of them don't deal with the case of both ranges coming from generics, and were solved using a type definition in a package. The one that did talk about two generic dimensions apparently didn't need the input to come from distinct std_logic_vectors and ended up using the "2d-array of std_logic" method, which doesn't work for me (at least without further clarification about how to use it without losing one's sanity))
This works with VHDL2008:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package bus_multiplexer_pkg is
type bus_array is array(natural range <>) of std_logic_vector;
end package;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.bus_multiplexer_pkg.all;
entity bus_multiplexer is
generic (bus_width : positive := 8;
sel_width : positive := 2);
port ( i : in bus_array(2**sel_width - 1 downto 0)(bus_width - 1 downto 0);
sel : in std_logic_vector(sel_width - 1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer;
architecture dataflow of bus_multiplexer is
begin
o <= i(to_integer(unsigned(sel)));
end dataflow;
And it can be used like this:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.all;
use work.bus_multiplexer_pkg.all;
entity bus_multiplexer_4 is
generic (bus_width : positive := 8);
port ( bus0, bus1, bus2, bus3 : in std_logic_vector(bus_width - 1 downto 0);
sel : in std_logic_vector(1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer_4;
architecture structural of bus_multiplexer_4 is
signal i : bus_array(3 downto 0)(bus_width - 1 downto 0);
begin
i <= (0 => bus0, 1 => bus1, 2 => bus2, 3 => bus3);
u: entity bus_multiplexer generic map (bus_width => bus_width, sel_width => 2) port map (i => i, sel => sel, o => o);
end;
It doesn't work with VHDL93, however, because you can't leave the std_logic_vector unconstrained in the type definition, as stated in the question.
Unfortunately, I don't know if there's any way to do anything similar without 2d arrays with VHDL93.
Edit: Paebbels's answer shows how to do this in VHDL93 by using 2d arrays, with custom procedures to make it manageable. Since his example is quite big, here's also a minimal example of the same concept:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package bus_multiplexer_pkg is
type bus_array is array(natural range <>, natural range <>) of std_logic;
procedure slm_row_from_slv(signal slm : out bus_array; constant row : natural; signal slv : in std_logic_vector);
procedure slv_from_slm_row(signal slv : out std_logic_vector; signal slm : in bus_array; constant row : natural);
end package;
package body bus_multiplexer_pkg is
procedure slm_row_from_slv(signal slm : out bus_array; constant row : natural; signal slv : in std_logic_vector) is
begin
for i in slv'range loop
slm(row, i) <= slv(i);
end loop;
end procedure;
procedure slv_from_slm_row(signal slv : out std_logic_vector; signal slm : in bus_array; constant row : natural) is
begin
for i in slv'range loop
slv(i) <= slm(row, i);
end loop;
end procedure;
end package body;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.bus_multiplexer_pkg.all;
entity bus_multiplexer is
generic (bus_width : positive := 8;
sel_width : positive := 2);
port ( i : in bus_array(2**sel_width - 1 downto 0, bus_width - 1 downto 0);
sel : in std_logic_vector(sel_width - 1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer;
architecture dataflow of bus_multiplexer is
begin
slv_from_slm_row(o, i, to_integer(unsigned(sel)));
end dataflow;
And it can be used like this:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.all;
use work.bus_multiplexer_pkg.all;
entity bus_multiplexer_4 is
generic (bus_width : positive := 8);
port ( bus0, bus1, bus2, bus3 : in std_logic_vector(bus_width - 1 downto 0);
sel : in std_logic_vector(1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer_4;
architecture structural of bus_multiplexer_4 is
signal i : bus_array(3 downto 0, bus_width - 1 downto 0);
begin
slm_row_from_slv(i, 0, bus0);
slm_row_from_slv(i, 1, bus1);
slm_row_from_slv(i, 2, bus2);
slm_row_from_slv(i, 3, bus3);
u: entity bus_multiplexer generic map (bus_width => bus_width, sel_width => 2) port map (i => i, sel => sel, o => o);
end;
Yes, it's possible.
Your attempt with a two dimensional array is good, because nested 1 dimensional array need a fixed size in the inner dimensions. So the way to handle such a 2D array is to write some functions and procedures, which convert the 2D array into nested 1D vectors.
I answered a similar question here:
- Fill one row in 2D array outside the process (VHDL) and
- Creating a generic array whose elements have increasing width in VHDL
Here is my vectors package.
And here is an example of an multiplexer for a FIFO interface, which is variable in data width as well as in input count. It uses a round robin arbiter to select the inputs.
Entity 'PoC.bus.Stream.Mux':
-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
-- vim: tabstop=2:shiftwidth=2:noexpandtab
-- kate: tab-width 2; replace-tabs off; indent-width 2;
--
-- ============================================================================
-- Authors: Patrick Lehmann
--
-- License:
-- ============================================================================
-- Copyright 2007-2015 Technische Universitaet Dresden - Germany
-- Chair for VLSI-Design, Diagnostics and Architecture
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- ============================================================================
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
library PoC;
use PoC.config.all;
use PoC.utils.all;
use PoC.vectors.all;
entity Stream_Mux is
generic (
PORTS : POSITIVE := 2;
DATA_BITS : POSITIVE := 8;
META_BITS : NATURAL := 8;
META_REV_BITS : NATURAL := 2
);
port (
Clock : IN STD_LOGIC;
Reset : IN STD_LOGIC;
-- IN Ports
In_Valid : IN STD_LOGIC_VECTOR(PORTS - 1 downto 0);
In_Data : IN T_SLM(PORTS - 1 downto 0, DATA_BITS - 1 downto 0);
In_Meta : IN T_SLM(PORTS - 1 downto 0, META_BITS - 1 downto 0);
In_Meta_rev : OUT T_SLM(PORTS - 1 downto 0, META_REV_BITS - 1 downto 0);
In_SOF : IN STD_LOGIC_VECTOR(PORTS - 1 downto 0);
In_EOF : IN STD_LOGIC_VECTOR(PORTS - 1 downto 0);
In_Ack : OUT STD_LOGIC_VECTOR(PORTS - 1 downto 0);
-- OUT Port
Out_Valid : OUT STD_LOGIC;
Out_Data : OUT STD_LOGIC_VECTOR(DATA_BITS - 1 downto 0);
Out_Meta : OUT STD_LOGIC_VECTOR(META_BITS - 1 downto 0);
Out_Meta_rev : IN STD_LOGIC_VECTOR(META_REV_BITS - 1 downto 0);
Out_SOF : OUT STD_LOGIC;
Out_EOF : OUT STD_LOGIC;
Out_Ack : IN STD_LOGIC
);
end;
architecture rtl OF Stream_Mux is
attribute KEEP : BOOLEAN;
attribute FSM_ENCODING : STRING;
subtype T_CHANNEL_INDEX is NATURAL range 0 to PORTS - 1;
type T_STATE is (ST_IDLE, ST_DATAFLOW);
signal State : T_STATE := ST_IDLE;
signal NextState : T_STATE;
signal FSM_Dataflow_en : STD_LOGIC;
signal RequestVector : STD_LOGIC_VECTOR(PORTS - 1 downto 0);
signal RequestWithSelf : STD_LOGIC;
signal RequestWithoutSelf : STD_LOGIC;
signal RequestLeft : UNSIGNED(PORTS - 1 downto 0);
signal SelectLeft : UNSIGNED(PORTS - 1 downto 0);
signal SelectRight : UNSIGNED(PORTS - 1 downto 0);
signal ChannelPointer_en : STD_LOGIC;
signal ChannelPointer : STD_LOGIC_VECTOR(PORTS - 1 downto 0);
signal ChannelPointer_d : STD_LOGIC_VECTOR(PORTS - 1 downto 0) := to_slv(2 ** (PORTS - 1), PORTS);
signal ChannelPointer_nxt : STD_LOGIC_VECTOR(PORTS - 1 downto 0);
signal ChannelPointer_bin : UNSIGNED(log2ceilnz(PORTS) - 1 downto 0);
signal idx : T_CHANNEL_INDEX;
signal Out_EOF_i : STD_LOGIC;
begin
RequestVector <= In_Valid AND In_SOF;
RequestWithSelf <= slv_or(RequestVector);
RequestWithoutSelf <= slv_or(RequestVector AND NOT ChannelPointer_d);
process(Clock)
begin
if rising_edge(Clock) then
if (Reset = '1') then
State <= ST_IDLE;
else
State <= NextState;
end if;
end if;
end process;
process(State, RequestWithSelf, RequestWithoutSelf, Out_Ack, Out_EOF_i, ChannelPointer_d, ChannelPointer_nxt)
begin
NextState <= State;
FSM_Dataflow_en <= '0';
ChannelPointer_en <= '0';
ChannelPointer <= ChannelPointer_d;
case State is
when ST_IDLE =>
if (RequestWithSelf = '1') then
ChannelPointer_en <= '1';
NextState <= ST_DATAFLOW;
end if;
when ST_DATAFLOW =>
FSM_Dataflow_en <= '1';
if ((Out_Ack AND Out_EOF_i) = '1') then
if (RequestWithoutSelf = '0') then
NextState <= ST_IDLE;
else
ChannelPointer_en <= '1';
end if;
end if;
end case;
end process;
process(Clock)
begin
if rising_edge(Clock) then
if (Reset = '1') then
ChannelPointer_d <= to_slv(2 ** (PORTS - 1), PORTS);
elsif (ChannelPointer_en = '1') then
ChannelPointer_d <= ChannelPointer_nxt;
end if;
end if;
end process;
RequestLeft <= (NOT ((unsigned(ChannelPointer_d) - 1) OR unsigned(ChannelPointer_d))) AND unsigned(RequestVector);
SelectLeft <= (unsigned(NOT RequestLeft) + 1) AND RequestLeft;
SelectRight <= (unsigned(NOT RequestVector) + 1) AND unsigned(RequestVector);
ChannelPointer_nxt <= std_logic_vector(ite((RequestLeft = (RequestLeft'range => '0')), SelectRight, SelectLeft));
ChannelPointer_bin <= onehot2bin(ChannelPointer);
idx <= to_integer(ChannelPointer_bin);
Out_Data <= get_row(In_Data, idx);
Out_Meta <= get_row(In_Meta, idx);
Out_SOF <= In_SOF(to_integer(ChannelPointer_bin));
Out_EOF_i <= In_EOF(to_integer(ChannelPointer_bin));
Out_Valid <= In_Valid(to_integer(ChannelPointer_bin)) and FSM_Dataflow_en;
Out_EOF <= Out_EOF_i;
In_Ack <= (In_Ack 'range => (Out_Ack and FSM_Dataflow_en)) AND ChannelPointer;
genMetaReverse_0 : if (META_REV_BITS = 0) generate
In_Meta_rev <= (others => (others => '0'));
end generate;
genMetaReverse_1 : if (META_REV_BITS > 0) generate
signal Temp_Meta_rev : T_SLM(PORTS - 1 downto 0, META_REV_BITS - 1 downto 0) := (others => (others => 'Z'));
begin
genAssign : for i in 0 to PORTS - 1 generate
signal row : STD_LOGIC_VECTOR(META_REV_BITS - 1 downto 0);
begin
row <= Out_Meta_rev AND (row'range => ChannelPointer(I));
assign_row(Temp_Meta_rev, row, i);
end generate;
In_Meta_rev <= Temp_Meta_rev;
end generate;
end architecture;

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.

Resources