How can i implement byte addressable memory in VHDL? - vhdl

I want to make 4kb byte addressable memory. sorry I'm new in VHDL
I wanted my code works first write 4byte number in adress 8 (rdwr=1, addr=1000, size=10(2^2byte), idata=10001100)
then wait 8 cycles to implement writing time(ivalid=0)
Second read 4byte number from adress 8(rdwr=0, addr=1000, size=10(2^2byte))
In my purpose, the "ready" signal should be '0' while waiting for writing time
but the signal is always 'U' in simulation. I tried to figure out what is the problem but i couldn't
Can anyone help me where did a make mistake?
Here is my code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Memory is
port (
clk: in std_logic;
ready: out std_logic; -- 0: busy, 1: ready
ivalid: in std_logic; -- 0: invalid, 1: valid
rdwr: in std_logic; -- 0: read, 1: write
addr: in unsigned(11 downto 0); -- byte address
size: in std_logic_vector(1 downto 0); -- 00/01/10/11: 1/2/4/8 bytes
idata: in std_logic_vector(63 downto 0);
ovalid: out std_logic; -- 0: invalid, 1: valid
odata: out std_logic_vector(63 downto 0)
);
end entity;
architecture Behavioral of Memory is
type ram_type is array (0 to (2**12)-1) of std_logic_vector(7 downto 0);
signal RAM : ram_type;
signal state : std_logic := '1'; --if ready '1'
signal queue : std_logic := '0'; --if something to do '1'
signal timer : integer := 0; --timer
signal curr_addr : unsigned(11 downto 0);
signal curr_size : std_logic_vector(1 downto 0);
signal curr_data : std_logic_vector(63 downto 0);
signal write : std_logic := '0';
signal read : std_logic := '0';
begin
process(clk)
variable vstate : std_logic := state;
variable vqueue : std_logic := queue; --if something to do '1'
variable vtimer : integer := timer; --timer
variable vcurr_addr : unsigned(11 downto 0) := curr_addr;
variable vcurr_size : std_logic_vector(1 downto 0) := curr_size;
variable vcurr_data : std_logic_vector(63 downto 0) := curr_data;
variable vwrite : std_logic := write;
variable vread : std_logic := read;
begin
--get input
if(rising_edge(clk)) then
ovalid <= '0';
if(vstate='1') then
if(ivalid='1') then
vcurr_addr := addr;
vcurr_size := size;
if(rdwr='0') then
--read
vread := '1';
else
vwrite := '1';
vcurr_data := idata;
end if;
vqueue := '1';
vtimer := 2**(to_integer(unsigned(vcurr_size)))-1;
end if;
end if;
--process
if(vqueue = '1') then
if(vtimer > 0) then
--wait for next cycle
ready <= '0';
vstate := '0';
vtimer := vtimer - 1;
else
--ok to go
if(vwrite = '1') then
--write
for x in 0 to 2**(to_integer(unsigned(vcurr_size)))-1 loop
for y in 0 to 7 loop
RAM(to_integer(vcurr_addr) + x)(y) <= vcurr_data(y + 8*x);
end loop;
end loop;
elsif(vread = '1') then
--read
for x in 0 to 7 loop
for y in 0 to 7 loop
if(x < 2**(to_integer(unsigned(vcurr_size)))) then
odata(y + 8*x) <= RAM(to_integer(vcurr_addr) + x)(y);
else
odata(y + 8*x) <= '0';
end if;
end loop;
end loop;
ovalid <= '1';
end if;
vqueue := '0';
vstate := '1';
ready <= '1';
end if;
end if;
--save variable to signals
state <= vstate;
queue <= vqueue;
timer <= vtimer;
curr_addr <=vcurr_addr;
curr_size <=vcurr_size;
curr_data<= vcurr_data;
write <= vwrite;
read <= vread;
end if;
end process;
end architecture;

Related

Unexpected value when reading ROM in the first clock pulse

I'm trying to create a ROM where a number of values is stored and, after receiving a clock pulse, one of its values is read and then sent to the output while the counter that keeps track of the current position in the ROM is increased by 1. The problem that i found is that the ROM value is not retrieved as it should be in the first clock event.
Entity code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity memoria is
Port ( clock, reset :in STD_LOGIC;
valor : out STD_LOGIC_VECTOR(7 downto 0);
vazia : out STD_LOGIC);
end memoria;
architecture Behavioral of memoria is
type ROM is array (0 to 4) of STD_LOGIC_VECTOR(7 downto 0); --Read only memory
constant mem : ROM := (b"00000000", b"00000001", b"00000010", b"00000011", b"11111111"); --"11111111" is the stop value
signal mem_value : STD_LOGIC_VECTOR(7 downto 0);
begin
process(clock, reset)
variable counter : integer := 0;
begin
if reset = '1' then
valor <= "11111111";
vazia <= '1';
elsif clock'event and clock = '1' then
mem_value <= mem(counter); --gets the current memory value
if mem_value = "11111111" then --checks if the value read is the stop one
vazia <= '1';
else
vazia <= '0';
end if;
valor <= mem_value; --sends the memory value read to the output
if counter < 4 then
counter := counter + 1; --increases counter by one
end if;
else
valor <= "11111111";
vazia <= '0';
end if;
end process;
end Behavioral;
Test Bench
ENTITY memoria_tb IS
END memoria_tb;
ARCHITECTURE behavior OF memoria_tb IS
--Inputs
signal clock : std_logic;-- := '0';
signal reset : std_logic := '0';
--Outputs
signal valor : std_logic_vector(7 downto 0);
signal vazia : std_logic;
-- Clock period definitions
constant clock_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: entity work.memoria PORT MAP (
clock => clock,
reset => reset,
valor => valor,
vazia => vazia
);
-- Clock process definitions
clock_process :process
begin
clock <= '0';
wait for clock_period/2;
clock <= '1';
wait for clock_period/2;
end process;
END;
Image of the error
I would like to know how to get the first ROM value in the first clock pulse instead of UUUUUUUU. Thanks for the help.
The problem was that the outputs should always be assigned after the process as noted in this post https://forums.xilinx.com/t5/General-Technical-Discussion/Counter-implementation-in-vhdl/td-p/570433.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity memoria is
Port ( clock, reset :in STD_LOGIC;
valor : out STD_LOGIC_VECTOR(7 downto 0);
vazia : out STD_LOGIC);
end memoria;
architecture Behavioral of memoria is
type ROM is array (0 to 4) of STD_LOGIC_VECTOR(7 downto 0); --Read only memory
constant mem : ROM := (b"00000000", b"00000001", b"00000010", b"00000011", b"11111111"); --"11111111" is the stop value
signal mem_value : STD_LOGIC_VECTOR(7 downto 0);
signal empty : STD_LOGIC;
begin
process(clock, reset)
variable counter : integer := 0;
begin
if reset = '1' then
mem_value <= "11111111";
empty <= '1';
elsif clock'event and clock = '1' then
mem_value <= mem(counter); --gets the current memory value
if mem_value = "11111111" then --checks if the value read is the stop one
empty <= '1';
else
empty <= '0';
end if;
if counter < 4 then
counter := counter + 1; --increases counter by one
end if;
else
mem_value <= "11111111";
empty <= '0';
end if;
end process;
valor <= mem_value; --sends the memory value read to the output
vazia <= empty;
end Behavioral;

FIFO using vhdl

I am writing a VHDL for fifo , but when i simulate there is no output?i cantt view the output in behavioral simulation.its like There's no data in data_in for read to be writing to the output of fifo.In my code is to write data into the FIFO first push the data onto the DataIn bus and then strobe the WriteEn input high for one clock cycle.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use std.textio.all;
use IEEE.NUMERIC_STD.ALL;
entity fifo_mem is
port ( clk : in std_logic;
reset : in std_logic;
enr : in std_logic;
enw : in std_logic;
data_in : in std_logic_vector (15 downto 0); --input data
data_out : out std_logic_vector(15 downto 0); --output data
fifo_empty : out std_logic;
fifo_full : out std_logic );
end fifo_mem;
architecture Behavioral of fifo_mem is
type fifo_type is array(0 to 10) of bit_vector (15 downto 0);
signal memory : fifo_type :=(others => (others => '0'));
signal readptr,writeptr : integer := 0; --read and write pointers.
signal empty,full : std_logic ;
impure function InitRamFromFile (RamFileName : in string) return fifo_type is
FILE RamFile : text is in RamFileName;
variable RamFileLine : line;
variable RAM : fifo_type;
begin
for I in 0 to 10 loop
readline (RamFile, RamFileLine);
read (RamFileLine, RAM(I));
end loop;
return RAM;
end function;
signal RAM : fifo_type :=InitRamFromFile("C:\Users\hp\Desktop\file\file1.txt");
begin
fifo_empty <= empty;
fifo_full <= full;
process(Clk,reset)
--this is the number of elements stored in fifo at a time.
--this variable is used to decide whether the fifo is empty or full.
variable num_elem : integer := 0;
begin
if(reset = '1') then
data_out <= (others => '0');
empty <= '0';
full <= '0';
readptr <= 0;
writeptr <= 0;
num_elem := 0;
elsif(rising_edge(Clk)) then
if(enr = '1' and empty = '0') then --read
data_out <=to_stdlogicvector(RAM(readptr));
readptr <= readptr + 1;
num_elem := num_elem-1;
end if;
if(enw ='1' and full = '0') then --write
RAM(writeptr)<= to_bitvector(data_in);
writeptr <= writeptr +1;
num_elem := num_elem+1;
end if;
if(readptr = 10) then --resetting read pointer.
readptr <= 0;
end if;
if(writeptr = 10) then --resetting write pointer.
writeptr <= 0;
end if;
--setting empty and full flags.
if(num_elem = 0) then
empty <= '1';
else
empty <= '0';
end if;
if(num_elem = 10) then
full <= '1';
else
full <= '0';
end if;
end if;
end process;
end Behavioral;

Altera FPGA hardware (has an issue) vs ModelSim simulation (ok) - self implemented UART

I have an issue with self implemented UART in VHDL.
I wrote VHDL code which generates proper waveform when running on Altera ModelSim:
UART.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.ALL;
entity UART is
port (
clk_10mhz: in STD_LOGIC;
uart_clk: out STD_LOGIC;
txPin: out STD_LOGIC
);
end entity;
architecture Test of UART is
signal txStart: STD_LOGIC := '0';
signal txIdle: STD_LOGIC;
signal txData: STD_LOGIC_VECTOR(7 downto 0);
component TX is
port (
clk_in: in STD_LOGIC;
start: in STD_LOGIC;
data: in STD_LOGIC_VECTOR(7 downto 0);
tx: out STD_LOGIC;
txIdle: out STD_LOGIC;
debug_clk: out STD_LOGIC
);
end component TX;
begin
process (clk_10mhz)
variable clkDividerCounter : integer range 0 to 10000000;
variable textToSend : string(1 to 31) := "Hello darkness my old friend!" & LF & CR;
variable currentCharacterIndex : integer range 1 to 31 := 1;
variable startSending : std_logic := '0';
variable characterReceivedByTX : std_logic := '1';
begin
if (rising_edge(clk_10mhz)) then
if (startSending = '1') then
if (txIdle = '0') then
characterReceivedByTX := '1';
end if;
if (txIdle = '1' and characterReceivedByTX = '1') then
txData <= std_logic_vector(to_unsigned(character'pos(textToSend(currentCharacterIndex)), 8));
txStart <= '1';
if (currentCharacterIndex < 31) then
currentCharacterIndex := currentCharacterIndex + 1;
characterReceivedByTX := '0';
else
txStart <= '0';
currentCharacterIndex := 1;
startSending := '0';
end if;
end if;
else
if (clkDividerCounter < 10000000) then
clkDividerCounter := clkDividerCounter + 1;
startSending := '0';
else
clkDividerCounter := 0;
startSending := '1';
end if;
end if;
end if;
end process;
u1: TX port map (clk_10mhz, txStart, txData, txPin, txIdle, uart_clk);
end Test;
TX.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.ALL;
entity TX is
port (
clk_in: in STD_LOGIC;
start: in STD_LOGIC;
data: in STD_LOGIC_VECTOR(7 downto 0);
tx: out STD_LOGIC := '1';
txIdle: out STD_LOGIC := '1';
debug_clk: out STD_LOGIC := '0'
);
end entity;
architecture Test of TX is
signal idle: STD_LOGIC := '1';
begin
process (clk_in)
variable bitIndex : integer range 0 to 9;
variable clkDividerCounter : integer range 0 to 1042;
variable dataFrame : STD_LOGIC_VECTOR(9 downto 0);
variable dataFrameCurrentIndex : integer range 0 to 9;
begin
if (rising_edge(clk_in)) then
if (start = '1' and idle = '1') then
dataFrame(0) := '0';
dataFrame(8 downto 1) := data;
dataFrame(9) := '1';
dataFrameCurrentIndex := 0;
idle <= '0';
end if;
if (idle = '0') then
if (clkDividerCounter < 521) then
debug_clk <= '0';
else
debug_clk <= '1';
end if;
if (clkDividerCounter < 1041) then
clkDividerCounter := clkDividerCounter + 1;
else
if (dataFrameCurrentIndex < 9) then
tx <= dataFrame(dataFrameCurrentIndex);
dataFrameCurrentIndex := dataFrameCurrentIndex + 1;
else
tx <= dataFrame(dataFrameCurrentIndex);
idle <= '1';
end if;
clkDividerCounter := 0;
end if;
else
debug_clk <= '0';
end if;
end if;
end process;
txIdle <= idle;
end Test;
Unfortunately, on hardware, instead of "Hello darkness my old friend!" sent, it sends "HHello darkness my old friend!" with double H at the beginning.
I checked it on SignalTap II and waveform confirms the problem:
What can cause this problem? How may I debug such an issue?

issue related to loading modelsim simulation

I am facing a issue regarding Modelsim. I am not able to load my testbench in simulation. following is my testbench and code
Testbench
library IEEE;
use IEEE.numeric_std.all;
use IEEE.std_logic_1164.all;
library work;
use work.pack1.all;
entity test_dg is
end entity;
architecture behavior of test_dg is
component digit_ext is
generic (
add_width : integer := 12; -- length of the adress of the node
depth : integer := 15);
port (
suc_add : in std_logic_vector(add_width-1 downto 0); -- source address
des_add : in std_logic_vector(add_width-1 downto 0); -- destination address
flg2 : out std_logic;
flg3 : out std_logic;
flg4 : out std_logic;
flg5 : out std_logic;
flg6 : out std_logic);
end component;
signal sucadd_t: std_logic_vector(11 downto 0) := "000000000000";
signal desadd_t: std_logic_vector(11 downto 0) := "000000000000";
begin
logic_instance: digit_ext port map (sucadd_t,desadd_t);
source_address: process
begin
sucadd_t <= "100000000000";
wait for 20 ns;
sucadd_t <= "000000000000";
wait for 20 ns;
end process;
destination_address: process
begin
desadd_t <= "010000000000";
wait for 23 ns;
desadd_t <= "001100000000";
wait for 44 ns;
desadd_t <= "001000000001";
wait for 65 ns;
desadd_t <= "000100100000";
wait for 86 ns;
end process;
endsumulation:process
begin
wait for 150 ns;
assert false report "end simulation" severity failure;
end process;
end behavior;
configuration CFG_LOG of test_dg is
for behavior
for logic_instance: digit_ext
end for;
end for;
end CFG_LOG;
Code:
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.all;
-- =============================================================================
library work;
use work.pack1.all;
-- =============================================================================
entity digit_ext is
generic (
add_width : integer := 12; -- length of the adress of the node
depth : integer := 15);
port (
suc_add : in std_logic_vector(add_width-1 downto 0); -- source address
des_add : in std_logic_vector(add_width-1 downto 0); -- destination address
flg2 : out std_logic;
flg3 : out std_logic;
flg4 : out std_logic;
flg5 : out std_logic;
flg6 : out std_logic);
end digit_ext;
-- =============================================================================
architecture behavior of digit_ext is
type info is array (0 to depth) of integer;
signal self_info: info := (500,4,0,0,3,0,0,2,0,1,1,2,0);
signal equ_add : integer;
signal i1: integer;
signal i2: integer;
signal i3: integer;
signal flg1 : integer := 0;
signal v1 : integer;
signal v2 : std_logic := '0';
signal v3 : std_logic := '0';
signal v4 : std_logic := '0';
signal v5 : std_logic := '0';
signal v6 : std_logic := '0';
begin
-- =============================================================================
flg2 <= v2; -- assignment of signal to the output ports
flg3 <= v3;
flg4 <= v4;
flg5 <= v5;
flg6 <= v6;
-- =============================================================================
step1:process (des_add,equ_add,i1,i2,i3) -- to convert bcd address of destination to integer and to split the digits
begin
bcd_conv(des_add,equ_add,i1,i2,i3);
v1 <= (equ_add - self_info(1)); -- find distance between the current address and destination address
if (v1 < 0) then
flg1 <= 1;
elsif (v1 > 0 ) then
flg1 <= 2;
elsif (v1 = 0) then
flg1 <= 3;
end if;
end process;
-- =============================================================================
step2:process(flg1) -- process to find the up or down neighbour based on set value of flag
begin
if (flg1 = 1) then
v2 <= compare (i1,i2,i3,self_info(2),self_info(3),self_info(4));
v3 <= compare (i1,i2,i3,self_info(5),self_info(6),self_info(7));
elsif (flg1 = 2) then
v4 <= compare (i1,i2,i3,self_info(8),self_info(9),self_info(10));
v5 <= compare (i1,i2,i3,self_info(11),self_info(12),self_info(13));
elsif (flg1 = 3)then
v6 <= '1';
v2 <= '0';
v3 <= '0';
v4 <= '0';
v5 <= '0';
end if;
end process;
-- =============================================================================
end behavior;
-- =============================================================================
when I simulate the testbench , it say that no design loaded....
Thanks
Manasi.
Goto: http://www.synthworks.com/downloads/
Get the file: modelsim_tutorial.pdf and modelsim_quickref.pdf
Work through the tutorial. Compile the package (pack1). Then compile your design (digit_ext) and your testbench (test_dg). Note that you will not see the flags in the testbench unless you map them.

Rising_edge detection within clock

I am new to vhdl programming. I recently got a task to change value of std_logic_vector in a shift register sensitive to clock signal by pressing a button.
When I'm holding KEY(2) the value of shift register changes but it's not shifting unless I release the button. Is it possible to modify my code below so it would be sensitive to rising edge of KEY(2)? Or is there any other possibility to change a value of the vector by pressing the KEY(2) button and it would be shifting even if I'm holding the button?
Thank you for your answer. I would be really grateful and it would really help me a lot.
Sorry for my bad English. Have a nice time.
ENTITY hadvhdl IS PORT (
CLOCK_50 : IN STD_LOGIC;
KEY : IN STD_LOGIC_VECTOR (3 downto 0);
LEDR : OUT STD_LOGIC_VECTOR (15 downto 0)
);
END hadvhdl;
ARCHITECTURE rtl OF hadvhdl IS
shared variable register : std_logic_vector(15 downto 0) := (1 downto 0=>'1', others=>'0');
shared variable count : integer range 1 to 4 :=1;
BEGIN
changecount: process (KEY)
begin
if rising_edge(KEY(2)) then
if count<4 then
count := count + 1;
else
count := 1;
end if;
end if;
end process;
shift: process (CLOCK_50, KEY)
variable up : BOOLEAN := FALSE;
variable reg : std_logic_vector(15 downto 0) := (1 downto 0=>'1', others=>'0');
begin
if rising_edge(CLOCK_50) then
if (KEY(2)='1') then
case count is
when 1 => register := (1 downto 0=>'1', others=>'0');
when 2 => register := (2 downto 0=>'1', others=>'0');
when 3 => register := (3 downto 0=>'1', others=>'0');
when 4 => register := (4 downto 0=>'1', others=>'0');
end case;
end if;
reg := register;
LEDR <= reg;
if up then
reg := reg(0) & reg(15 downto 1);
else
reg := reg(14 downto 0) & reg(15);
end if;
register := reg;
end if;
end process;
END rtl;
Don't use variables! (at least as VHDL-beginner)
Don't use push buttons as clocks (e.g. in rising_edge)
Use only one clock in your design (seem o.k. in your case)
Keep in mind that a mechanical push button do bounces.
And here is a variant for an edge detection:
-- in entity
clk ; in std_logic;
sig_in : in std_logic;
...
signal sig_old : std_logic;
signal sig_rise : std_logic;
signal sig_fall : std_logic;
...
process
begin
wait until rising_edge( clk);
-- defaults
sig_rise <= '0';
sig_fall <= '0';
-- shift value in
sig_old <= sig_in;
-- do some real action
if sig_old = '0' and sig_in = '1' then
sig_rise <= '1';
end if;
if sig_old = '1' and sig_in = '0' then
sig_fall <= '1';
end if;
end process;

Resources