Why the INOUT doesn't work? - hardware

I am making a circuit that handles read and write operations to some registers and uses a single bus to transfer data between registers, the problem is that when reading from bus (a register is reading from bus) it works well, but when trying to assign a value in a register it is not working. Note that if i used a signal to write to it will work !!!
My Code:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
-- Entity: Circuit
-- Description: Organizes read and write operation to the bus
-- n is the size of word in a register, default is 16
-- m is the number of selection lines in the decoder, so 2 ^ m
-- is the number of registers in the cicuit
-- data_bus: the bus used to transfer data
-- reg_read: input to a decoder determines which register to read from bus.
-- reg_write: input to a decoder determines which register to write to bus.
-- read: read signal
-- write: write signal
-- Clk: clock
-- Rst: Reset
ENTITY circuit IS
GENERIC( n : integer := 16;
m : integer := 2);
PORT(data_bus : INOUT STD_LOGIC_VECTOR(n-1 DOWNTO 0);
reg_read, reg_write : IN STD_LOGIC_VECTOR(m-1 DOWNTO 0);
read, write, Clk, Rst : IN STD_LOGIC);
END circuit;
ARCHITECTURE circuit_arch OF circuit IS
-- Tristate buffers
COMPONENT tsb IS
GENERIC ( n : integer := 16);
PORT ( E : IN STD_LOGIC;
Input : IN STD_LOGIC_VECTOR (n-1 DOWNTO 0);
Output : OUT STD_LOGIC_VECTOR (n-1 DOWNTO 0));
END COMPONENT;
-- Registers
COMPONENT ndff IS
GENERIC ( n : integer := 16);
PORT( Clk,Rst,E : in STD_LOGIC;
d : IN STD_LOGIC_VECTOR(n-1 dOWNTO 0);
output : OUT STD_LOGIC_VECTOR(n-1 dOWNTO 0));
END COMPONENT;
-- Decoders
COMPONENT nDecoder IS
GENERIC ( n : integer := 4);
PORT(E : IN std_logic;
S : IN STD_LOGIC_VECTOR( n-1 DOWNTO 0);
output : OUT std_logic_vector(2 ** n - 1 DOWNTO 0));
END COMPONENT;
TYPE output IS ARRAY (0 TO (2 ** m) - 1) OF STD_LOGIC_VECTOR (n-1 DOWNTO 0);
SIGNAL read_dec, write_dec : STD_LOGIC_VECTOR(2 ** m - 1 DOWNTO 0);
SIGNAL regs_out : output;
SIGNAL test : STD_LOGIC_VECTOR(n-1 downto 0);
BEGIN
-- Generate decoders
dec1: nDecoder GENERIC MAP(m) PORT MAP(read, reg_read, read_dec);
dec2: nDecoder GENERIC MAP(m) PORT MAP(write, reg_write, write_dec);
-- Generate registers
LOOP1: FOR i IN 0 TO (2 ** m) - 1 GENERATE
lbl1: ndff GENERIC MAP(n) PORT MAP(Clk, Rst,read_dec(i),data_bus, regs_out(i));
END GENERATE;
-- Generate tristate buffers
LOOP2: FOR j IN 0 TO (2 ** m) - 1 GENERATE
lbl2: tsb GENERIC MAP(n) PORT MAP(write_dec(j), regs_out(j), data_bus);
END GENERATE;
END circuit_arch;

If you look at lbl1 in the generate statement you'll find the portmap:
lbl1: ndff generic map(n) port map(clk, rst,read_dec(i),data_bus, regs_out(i));
is positionally associative. While the port declaration reflected in the component declaration shows the order:
port( clk,rst,e : in std_logic;
d : in std_logic_vector(n-1 downto 0);
output : out std_logic_vector(n-1 downto 0));
Showing that read_dec(i) is the register load enable.
And the read buffers:
-- generate tristate buffers
loop2: for j in 0 to integer(2 ** m) - 1 generate
lbl2: tsb generic map(n) port map(write_dec(j), regs_out(j), data_bus);
end generate;
Show write_dec(j).
And examining the decodes for generating them shows:
-- generate decoders
dec1: ndecoder generic map(m) port map(read, reg_read, read_dec);
dec2: ndecoder generic map(m) port map(write, reg_write, write_dec);
read corresponds to read_dec and write corresponds to write_dec.
It certainly looks like you have the enables reversed for the registers loads and register output buffer enables.
There could be more, but without a MVCE someone answering can't get beyond basic eyeballing and analyzing.
And the reason Paebbels asked about target implementation is that for all practical purposes tristate internal buffers are generally restricted to ASIC implementations.

Related

VHDL password program with DE2-board

Summary:
I'm trying to make a password system in VHDL with the DE2 Altera board. SW 0 to 7 is the combination lock, LEDR 0 to 7 shows the current code and signal 'code' stores the combination. When the switches match the code you have the option to change the code by holding down KEY(1).
Problem:
The code works as it should, only the starter code is not what's expected. It should be: "01010101" as shown in the signal; but it comes out as "01111111". I suspect the program enters the if-statement on startup, but I don't see how that's possible, seeing as 'code' and SW should't be equal.
What am I missing?
Here is the code:
library IEEE;
use IEEE.std_logic_1164.all;
entity pass_sys is
port(
SW : in std_logic_vector(7 downto 0);
KEY : in std_logic_vector(3 downto 0);
LEDR : out std_logic_vector(17 downto 0);
LEDG : out std_logic_vector(17 downto 0)
);
end pass_sys;
architecture func of pass_sys is
signal code : std_logic_vector(7 downto 0) := "01010101"; --start code
begin
process(SW)
begin
LEDR(7 downto 0)<=code;
if (SW = code) then
LEDG(0)<='1';
LEDG(1)<=not KEY(1);
if (KEY(1) = '0') then
code<=SW;
end if;
else
LEDG(0)<='0';
end if;
end process;
end func;
I assume your problem happens on your board, not in simulation. If I'm wrong, my answer is not the one you expect.
This initialization way is usefull only in simulation :
signal code : std_logic_vector(7 downto 0) := "01010101"; --start code
Synthesis will not consider your initialization value (That's why I discourage you to use this, except in test bench). If you want to initialize a signal, I advice to use a reset.
Notes :
You should put KEY in sensitivity list and put this line out of your process :
LEDR(7 downto 0)<=code;
Your process infers latches, it's not forbidden but you must be careful with this
EDIT : How to add a reset
library IEEE;
use IEEE.std_logic_1164.all;
entity pass_sys is
port(
RST : in std_logic;
SW : in std_logic_vector(7 downto 0);
KEY : in std_logic_vector(3 downto 0);
LEDR : out std_logic_vector(17 downto 0);
LEDG : out std_logic_vector(17 downto 0)
);
end pass_sys;
architecture func of pass_sys is
signal code : std_logic_vector(7 downto 0);
begin
LEDR(7 downto 0)<=code;
process(SW, code, KEY)
begin
if RST = '1' then
LEDG <= (others => '0');
code <= "01010101";
elsif (SW = code) then
LEDG(0)<='1';
LEDG(1)<=not KEY(1);
if (KEY(1) = '0') then
code<=SW;
end if;
else
LEDG(0)<='0';
end if;
end process;
end func;
The pin RST of your component could be connected to an analogic signal of you card (POWER_GOOD, ALIM_ON, DONE, ...) or to a pll_locked signal of a PLL if you use it.

VHDL small error when using a conditional signal assignment (when...else)

I'm currently working on a component that will perform addition or subtraction, depending on the user input. Right now, I am working on a process that handles the assignment of values to the internal signals which will be used by the internal components I am using. One problem that comes up is in the line when I'm assigning b_in with either the input b or the 2's complement of the input b. Two errors show up:
Error: COMP96_0015: addsub_16.vhd : (85, 17): ';' expected.
Error: COMP96_0046: addsub_16.vhd : (85, 41): Sequential statement expected.
The errors all reference to the line
b_in <= (b) when add_sub = '0' else (b_2scomp);
However when I placed this outside the process, no error occurred; only when it's inside the process. Can someone please help me why this is and what I can do to solve it?
In addition, I know that normally port mapping is done between the architecture declaration and the begin statement of the architecture. The reason I placed them after the process is because I needed to make sure that b_in has the right signal before the other components can use it. I don't know if this is the right way to do it, but I hope it is. This is just in case you guys are wondering why I'm dong it like this. Thanks
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use IEEE.STD_LOGIC_ARITH.all;
entity addsub_16 is
port(
c_in : in STD_LOGIC;
enable : in std_logic;
reset : in std_logic;
clk : in std_logic;
add_sub : in STD_LOGIC;
a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
c_out : out STD_LOGIC;
result : out STD_LOGIC_VECTOR(15 downto 0)
);
end addsub_16;
architecture addsub_16 of addsub_16 is
--Signal declarations to hold internal vectors a, b g, p, and carry
signal a_in : std_logic_vector(15 downto 0); --Holds input a
signal b_in : std_logic_vector(15 downto 0); --Holds input b if add_sub = 0. Otherwise, holds b_2scomp
signal b_2scomp : std_logic_vector(15 downto 0); --Holds the 2s complement of b
signal prop_in : std_logic_vector(15 downto 0); --Holds the propagate signals from CLAs
signal gen_in : std_logic_vector(15 downto 0); --Holds the generate signals from CLAs
signal carry_in : std_logic_vector(15 downto 0); --Holds the carry signal from carry_logic
signal temp_result : std_logic_vector(15 downto 0); --Holds the temporary result to be driven out
--Component declarations
component cla_4bit
port (
a, b : in std_logic_vector(3 downto 0);
gen, prop : out std_logic_vector(3 downto 0)
);
end component;
component carry_logic
port (
g, p : in std_logic_vector(15 downto 0);
c_in : in std_logic;
carry : out std_logic_vector(15 downto 0);
c_out : out std_logic
);
end component;
--Actual behavior of module
begin
--b_in <= (b) when add_sub = '0' else (b_2scomp);
process (clk, reset)
begin
if reset = '0' then --At reset, everything is 0
a_in <= (others => '0');
b_in <= (others => '0');
b_2scomp <= (others => '0');
temp_result <= (others => '0');
elsif (rising_edge(clk)) then --Read in data to components on rising edge
if enable = '1' then --Only if enable is on
a_in <= a;
b_2scomp <= ((not b) + '1');
b_in <= (b) when add_sub = '0' else (b_2scomp);
end if;
elsif (falling_edge(clk)) then --Drive out values on falling edge
for i in 0 to 15 loop
temp_result(i) <= a_in(i) xor b_in(i) xor carry_in(i);
end loop;
result <= temp_result;
end if;
end process;
--portmapping of the components here. I don't think it'd be necessary to include them, but let me know if they are needed.
The ternary operator .. when .. else .. is not allowed inside a process block prior to VHDL-2008.
Solution 1: Write an ordinary if .. then .. else .. end if statement
Solution 2: Enable VHDL-2008 support in your tool chain
Solution 3: Write a function, lets say ite (if-then-else), which performs the ternary operation.

Error with wait conditions

I am a beginner to VHDL, and I am trying to make a multiplier, but the code I have to use from the book is not compiling right with the xilinx software. The code is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity testMult is
Port ( ISwitch : in STD_LOGIC_VECTOR (3 downto 0);
IPress : in STD_LOGIC;
IRegIn : in STD_LOGIC_VECTOR (31 downto 0);
IRegOut : out STD_LOGIC_VECTOR (31 downto 0);
Iclk : in STD_LOGIC);
end testMult;
architecture Beh of testMult is
component asMult
port(ISwitch : in STD_LOGIC_VECTOR (3 downto 0);
IRegA : in STD_LOGIC_VECTOR (7 downto 0);
IRegB : in STD_LOGIC_VECTOR (7 downto 0);
IRegProd : out STD_LOGIC_VECTOR (15 downto 0);
Iclk : in STD_LOGIC;
St : in STD_LOGIC;
Done : out STD_LOGIC);
end component;
constant aValue : std_logic_vector:= IRegIn(7 downto 0);
constant bValue : std_logic_vector:= IRegIn(15 downto 8);
signal Done : std_logic;
signal St : std_logic;
signal IRegA, IRegB : std_logic_vector(7 downto 0);
signal IRegProd : std_logic_vector(15 downto 0);
signal CLK : std_logic;
begin
CLK <= not CLK after 10 ns;
process
begin
if IPress = '1' then
IRegA <= aValue;
IRegB <= bValue;
St <= '0';
wait until CLK = '1' and CLK'event;
St <= '1';
wait until Done = '0' and Done'event;
IRegOut <= IRegProd & IRegIn(15 downto 8) & IRegin(7 downto 0);
end if;
end process;
asMult1 : asMult port map (ISwitch, aValue, bValue, IRegProd, Iclk, St, Done);
end Beh;
But I keep getting this error: line 36: Same wait conditions expected in all Multiple Waits.
Are you trying to synthesize that code, or you just want to simulate it? The code won't synthesize because:
CLK <= not CLK after 10 ns is not a synthesizable statement, and
The synthesis tools are equiped to handle only simpler kinds of processes. Try to break up your code into processes that are either purely combinational, or synchronous processes sensitive to the same edge of the same clock.
If you only want to simulate the code, there are still other problems with your example, but at least it compiles ok with Modelsim ASE 10.1b. My guess would be your compiler is trying to synthesize the code.
That's simulation code - you can run a simulation in ISIM.
After you have that working, you can synthesise part of it (the asmult block), but you can't synthesise your top level block as it is full of test-bench, simulation-only, code, like waiting on events (which can only be done in very specific ways for synthesis) and after.

Declaring an array within an entity in VHDL

I'm trying to make a buffer to hold 16, 16-bit wide instructions for a small CPU design.
I need a way to load instructions into the buffer from my testbench. So I wanted to use an array of std_logic_vectors to accomplish this. However, I am getting a syntax error and I'm not sure why (or if I'm allowed to do this in VHDL for that matter).
The syntax error is at the line where I declare instructions
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity instruction_buffer is
port
(
reset : in std_logic;
instructions : in array(0 to 15) of std_logic_vector(15 downto 0);
instruction_address : in std_logic_vector(3 downto 0);
clk : in std_logic;
instruction_out : out std_logic_vector(15 downto 0)
);
end instruction_buffer;
I've tried doing like this as well, but then I get syntax errors in my entity port mapping telling me that std_logic_vector is an unknown type. I swear, VHDL's syntax errors are less meaningful than C haha
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
package instructionBuffer is
type instructionBuffer is array(0 to 15) of std_logic_vector (15 downto 0);
end package instructionBuffer;
entity instruction_buffer is
port
(
instruction_address : in std_logic_vector(3 downto 0);
clk : in std_logic;
instruction_out : out std_logic_vector(15 downto 0)
);
end instruction_buffer;
There is no need to split into two files, simply put all code into one file. You can also use generics inside your package for scalability:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
package instruction_buffer_type is
constant INSTRUCTION_BUFFER_ADDRESS : integer := 4; --bits wide
constant INSTRUCTION_BUFFER_DATA : integer := 16; --bits wide
type instructionBuffer is array(0 to 2**INSTRUCTION_BUFFER_ADDRESS -1) of std_logic_vector (INSTRUCTION_BUFFER_DATA -1 downto 0);
end package instruction_buffer_type;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.instruction_buffer_type.all;
entity instruction_buffer is
port
(
instruction_address : in std_logic_vector(INSTRUCTION_BUFFER_ADDRESS-1 downto 0);
instructions : in instructionBuffer;
clk : in std_logic;
instruction_out : out std_logic_vector(INSTRUCTION_BUFFER_DATA-1 downto 0)
);
end instruction_buffer;
I got it working:
In one file I have the following:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
package instruction_buffer_type is
type instructionBuffer is array(0 to 15) of std_logic_vector (15 downto 0);
end package instruction_buffer_type;
and then in another I have:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.instruction_buffer_type.all;
entity instruction_buffer is
port
(
instruction_address : in std_logic_vector(3 downto 0);
instructions : in instructionBuffer;
clk : in std_logic;
instruction_out : out std_logic_vector(15 downto 0)
);
end instruction_buffer;
It's so obvious that this language was a government project. It's so overly redundant.
multidimensional array
package aray is
constant aM: integer :=3;
constant vM: integer :=3;
type argay is array (1 to aM) of std_logic_vector (vM downto 0);
type arrgay is array (1 to aM) of argay;
end package aray;

FPGA BRAM Stack Implementation Xilinx 7-Series

I am creating a stack based on the artix-7 fabric on the zynq soc. To create the stack I want to use the BRAM, I'm having a problem that the BRAM read output doesn't change, I've used BRAMS many times before (not 7-series so I may be missing something subtle) and am totally perplexed as to why it is doing this.
I filled the stack with values: 1, 2 ,3
When I then call pop successively the only value it reads out is 3 for each pop and read address (even after waiting for the one clock read delay). I have also tried with dual port rams and had the same issue, i'm sticking to single port as it simpler to try and workout what is going wrong!
I have verified the logic behavior using an array based ram which has the correct behavior. For verification I also checked the logic from this source: http://vhdlguru.blogspot.co.uk/2011/01/implementation-of-stack-in-vhdl.html.
So the issue appears to be with the BRAM, either it is not reading properly or for some reason it is writing the value 3 to all previous memory address which makes no sense as each data item is synced with a write signal and correct address.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.numeric_std.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;
-- Stack implementation for 32 bit data items using BRAM componenets
entity stack_32_BRAM is
generic( ADDR : integer :=32);
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
en : in STD_LOGIC;
push_pop : in STD_LOGIC;
data_in : in STD_LOGIC_VECTOR (31 downto 0);
data_out : out STD_LOGIC_VECTOR (31 downto 0));
end stack_32_BRAM;
architecture Behavioral of stack_32_BRAM is
COMPONENT BRAM_32_1K
PORT (
clka : IN STD_LOGIC;
rsta : IN STD_LOGIC;
wea : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
addra : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
douta : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
clkb : IN STD_LOGIC;
rstb : IN STD_LOGIC;
web : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
addrb : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
dinb : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
doutb : OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
);
END COMPONENT;
COMPONENT BRAM_32_1K_SP
PORT (
clka : IN STD_LOGIC;
rsta : IN STD_LOGIC;
wea : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
addra : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
douta : OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
);
END COMPONENT;
--The read ptr is a function of the write ptr
signal stack_ptr_read, stack_ptr_write : std_logic_vector(ADDR-1 downto 0) := (others =>'0');
signal full, empty : std_logic := '0';
signal WEA : std_logic_vector(3 downto 0) :=(others=>'0'); -- 4-bit input: A port write enable
signal addra, addrb, dinb, doutb, dina, douta : std_logic_vector(31 downto 0) := (others => '0');
signal rsta, rstb :std_logic := '0' ;
type ram is array (4 downto -2) of std_logic_vector(31 downto 0) ;
signal mem : ram :=(others=>(others=>'0'));
begin
---STACK LOGIC ---
PUSH : process (clk, push_pop, en, full, empty)
begin
if(clk'event and clk='1') then
WEA <= "0000";
if(en='1' and push_pop = '1' and full = '0') then
mem(to_integer(unsigned(stack_ptr_write))) <= data_in;
WEA <= "1111";
dina <= data_in ;
ADDRA <= stack_ptr_write;
stack_ptr_write <= stack_ptr_write + 1;
elsif(en='1' and push_pop = '0' and empty = '0') then
data_out <= douta ;--
doutb <= mem(to_integer(unsigned(stack_ptr_write - 1)));
ADDRA <= stack_ptr_write - 1;
stack_ptr_write <= stack_ptr_write - 1;
end if;
end if;
end process;
BRAM_SP : BRAM_32_1K_SP
PORT MAP (
clka => clk,
rsta => rsta,
wea => wea,
addra => addra,
dina => dina,
douta => douta
);
end Behavioral;
Many thanks
Sam
The solution entails several things:
1) You have to explicitly reset the signals with the rst port in every process. Initializing them in their declaration just doesn't cut it.
The process' code with a proper reset and sensitivity list should then look like this:
PUSH : process (rst, clk)
begin
if (rst = '1') then --supposing active-high async. reset
WEA <= (others => '0');
ADDRA <= (others => '0');
dina <= (others => '0');
data_out <= (others => '0');
full <= '0';
empty <= '0';
stack_ptr_write <= (others => '0');
elsif(clk'event and clk='1') then
--your code
2) I understand you have several layers/tries of code here in the same place. This is messy to read. I see you are using a "mem" to hold your example (so that WEA, ADDRA, dina, etc are ignorable), but when you get back to BRAM_32_1K_SP remember to check it has 32 bits addresses which, coupled with 32 bits data, mean that you have a 32 * 2**32 bits ram... that is around 128 Gbits, typo I guess.
However, to make a clearer question you should leave only the code pertaining to the memory solution you're having a problem with.
3) your code does include some typos that you should fix, like assigning "doutb" in the process, whereas I guess you wanted to assign data_out instead:
data_out <= mem(to_integer(unsigned(stack_ptr_write - 1)));
And this is the reason why you don't see what you want at the output.