VHDL Increment 10-bit Program Counter by 1 - vhdl

I am trying to make a 32-bit CPU using a modified MIPS instruction set in VHDL. I am currently trying to get my Program Counter to increment by 1 for the next instruction, unless it is a jump instruction which then the Program Counter will equal the Jump value.
entity PC is
Port ( PC_IN : in STD_LOGIC_VECTOR (9 downto 0); --New PC in value (PC+1 or jump)
PC_OUT : out STD_LOGIC_VECTOR (9 downto 0); --PC out to instruction memory
Jump_Inst : in STD_LOGIC_VECTOR(9 downto 0); --Jump address
Jump : in STD_LOGIC; --Jump MUX
clk : in STD_LOGIC);
end PC;
architecture Behavioral of PC is
begin
PC_IN <= (PC_IN + "0000000001") when (Jump = '0')
else Jump_Inst;
process(clk)
begin
if rising_edge(clk) then --If it is the next clock cycle (i.e time for the next instruction)
PC_OUT <= PC_IN;
end if;
end process;
end Behavioral;
I am getting errors at this line PC_IN <= (PC_IN + "0000000001") when (Jump = '0'). The errors consist of cannot update 'in' object pc_in and 0 definitions of operator "+" match here, so it doesn't like me using the + operator and maybe pc_in needs to be an output?
Does anyone know how to get my program counter to increment by 1 for the next instruction? Any help would be appreciated. Thanks.

PC_IN is defined as a std_logic_vector. You don't show the libraries in use, but by default there are no defined operators for + for std_logic_vector in std_logic_1164. Note your error message:
0 definitions of operator "+" match here
This is your hing that + isn't defined in this context. In order to use the + operator, you need to include a library that has that support and use the appropriate type.
Your other error:
cannot update 'in' object pc_in
Tells you that you cannot set an in port. Notably, PC_IN is an input, yet you are trying to drive PC_IN. Perhaps you mean to drive PC_OUT?
I won't mention the alternate method, but you should probably use numeric_std in this case. For example:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
...
PC_OUT <= std_logic_vector(unsigned(PC_IN) + 1) when (Jump = '0') else Jump_Inst;

Related

signal statement must use <= to assign value to signal

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.

VHDL Counter Error (vcom-1576)

guys im trying to code a simple counter in VHDL but i always get this error:
Error: C:/Users/usrname/dir1/dir2/dir3/counter.vhd(22): near "rising_edge": (vcom-1576) expecting == or '+' or '-' or '&'.
Here is my Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter is
port (
EXT_RST : in std_logic;
EXT_CLK : in std_logic;
EXT_LED : out std_logic_vector(7 downto 0)
);
end counter;
architecture fast of counter is
signal count : std_logic_vector(7 downto 0);
begin
process(EXT_CLK, count)
begin
if (EXT_RST = '1') then
count <= "00000000";
elseif rising_edge(EXT_CLK) then
count <= count + '1';
end if;
end process;
EXT_LED <= count;
end fast;
Has anyone an idea why im getting this error?
Besides the elsif Lars Asplund suggested using in his comment use type conversions for `count:
count <= std_logic_vector(unsigned(count) + 1);
or use package numeric_std_unsigned (VHDL -2008 only) instead of numeric_std.
Notice the 1 instead of '1' and type conversions. Those aren't needed with numeric_std_unsigned which has a "+" adding operator function with this signature:
[STD_ULOGIC_VECTOR,STD_ULOGIC return STD_ULOGIC_VECTOR]
Using package numeric_std you can also make count an unsigned instead of std_logic_vector and convert for the LED assignment -
EXT_LED <= std_logic_vector(count);
Also, count doesn't need to be in the process sensitivity list:
process(EXT_CLK)
There are no assignments in the process where the value of count is used except on the clock edge.
Modifying your code with the first suggestion and indenting (which helps show the sensitivity list doesn't need count:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter is
port (
EXT_RST : in std_logic;
EXT_CLK : in std_logic;
EXT_LED : out std_logic_vector(7 downto 0)
);
end counter;
architecture fast of counter is
signal count : std_logic_vector(7 downto 0);
begin
process(EXT_CLK)
begin
if (EXT_RST = '1') then
count <= "00000000";
elsif rising_edge(EXT_CLK) then
count <= std_logic_vector(unsigned(count) + 1);
end if;
end process;
EXT_LED <= count;
end fast;
This analyzes, elaborates and will simulate.
This prompts the question of how EXT_RST and EXT_CLK are derived should you actually synthesize your design. If they are from buttons (particularly the clock), debounce could be necessary even with membrane switches which can age and later bounce.

Dynamic Arrray Size in VHDL

I want to use dynamic range of array , so using "N" for converting an incoming vector signal to integer. Using the specifc incoming port "Size" gives me an error, while fixed vector produces perfect output.
architecture EXAMPLE of Computation is
signal size :std_logic_vector (7 downto 0);
process (ACLK, SLAVE_ARESETN) is
variable N: integer:=conv_integer ("00000111") ; ---WORKING
--variable N: integer:=conv_integer (size) ; -- Not working
type memory is array (N downto 0 ) of std_logic_vector (31 downto 0 );
variable RAM :memory;
Only reason to do this type of coding is send as much data as possible to FPGA .As I need to send Data from DDR to Custom IP via DMA in vivado may be more than 100 MB. so kindly guide me if I am trying to implement in wrong way as stated above.
You can't do that in VHDL. What kind of hardware would be generated by your code? If you don't know, the synthesizer won't either.
The way to do this kind of thing is to set N to the largest value you want to support, and use size in your logic to control your logic appropriately. It's difficult to give more pointers without more information, but as an example, you could use a counter to address your ram, and have it reset when it's greater than size.
Update
Here's a counter example. You have to make sure that size doesn't change while operating or it will fall into an unknown state. A real design should have reset states to ensure correct behaviour.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity example is
port (
clk : std_logic;
rst : in std_logic;
size : in unsigned(7 downto 0);
wr : in std_logic;
din : in std_logic_vector(31 downto 0)
);
end entity;
architecture rtl of example is
signal counter : unsigned(7 downto 0);
type ram_t is array(0 to 255) of std_logic_vector(31 downto 0);
signal ram : ram_t;
begin
RAM_WR: process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
counter <= (others => '0');
else
if wr = '1' then
ram(to_integer(counter)) <= din;
if counter = size then
counter <= (others => '0');
else
counter <= counter + 1;
end if;
end if;
end if;
end if;
end process RAM_WR;
end architecture rtl;
I believe you can only have a generic an array constraint in a process. Otherwise, the compiler cannot elaborate.
In a function or procedure, you can have truly variable array bounds.

2's compliment input and using vhdl library for signed input

My input data is 2's compliment and I designed the input is signed number and the all of operation is used signed number,the library i used ieee.numeric_std.all, but when i do ‘+’ an error occurred "found '0' definitions of operator "+", cannot determine exact overloaded matching definition for "+"". So I changed another to another library ieee.std_logic_arith.all ans make the add operation as a component, it works.
when i simulate my code by using testbench, error occurred: Entity port xin does not match with type signed of component port.
I think this error is about my library.
can anyone help me ?
new
i do not use adder as a component and the below code works
adder: process(clk)
begin
if (clk'event and clk = '1')then
if enable1='1' then
add1 <= (x0(7)&x0) + (x15(8)&x15);
add2 <= (x1(7)&x1) + (x14(8)&x14);
add3 <= (x2(7)&x2) + (x13(8)&x13);
add4 <= (x3(7)&x3) + (x12(8)&x12);
add5 <= (x4(7)&x4) + (x11(8)&x11);
add6 <= (x5(7)&x5) + (x10(8)&x10);
add7 <= (x6(7)&x6) + (x9(8)&x9);
add8 <= (x7(7)&x7) + (x8(8)&x8);
end if;
end if;
end process adder;
and the library of my testbench use use ieee.numeric_std.all;
USE ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
use std.textio.all;
ENTITY tb_signedinput IS
END tb_signedinput;
ARCHITECTURE behavior OF tb_signedinput IS
-- Component Declaration
COMPONENT signedinput is
port( Clk : in std_logic;
reset : in std_logic;
enable1 : in std_logic;
Xin : in signed(7 downto 0);
Yout : out signed(19 downto 0)
);
END COMPONENT;
--Inputs
signal Clk : std_logic := '0';
signal reset : std_logic := '0';
signal Xin : signed(7 downto 0) := (others => '0');
signal enable1 : std_logic := '0';
--Outputs
signal Yout : signed(19 downto 0);
-- Array
constant MEMSIZE: integer :=99;
type testarray is array (MEMSIZE downto 0) of signed(7 DOWNTO 0);
signal testvectors: testarray;
shared variable vectornum,outnum: integer;
-- Clock period definitions
constant Clk_period : time := 10 ns;
BEGIN
-- Component Instantiation
uut: signedinput PORT MAP( Clk => Clk,
reset => reset,
Xin => Xin,
enable1 =>enable1,
Yout => Yout );
the error still occur:
Entity port xin does not match with type std_logic_vector of component port
Entity port yout does not match with type std_logic_vector of component port
therefore, I changed my adder again to
add1 <= resize(x0,9) + x15;
syntax good but same error in testbench..
Is error about my ISE type or library type?
Thank you!
Your addition expression in adder1 is invalid because you're trying to index element "8" when the range of a1 and a2 is 7 downto 0.
Assuming thet you're trying to sign extend it would look something more like this:
q <=(a1(7)&a1 + a2(7)&a2);
The "+" operator has higher precedence than "&" so you are trying to add a1 + a2(7) which is signed + std_logic. This doesn't have an overload defined in numeric_std in addition to being logically wrong.
This works:
q <=(a1(7)&a1) + (a2(7)&a2);
But it isn't the canonical way to implement sign extension when using numeric_std. You only need the left side term to have the same size as q. The signed "+" operator will take care of sign extending its right hand side automatically.
q <= resize(a1, q'length) + a2; -- Sign extend a1 and add
This gives cleaner code that says what it's doing without relying on the non-standard std_logic_arith.
The actual error about the type mismatch on xin isn't apparent from your code. It is possible that you have an older version of signedinput compiled with a different type on its port and haven't updated the library.
Kevin made it look tough, so I figured I'd show something that makes for a good explanation:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder1 is
port (
a1: in signed (7 downto 0);
a2: in signed (7 downto 0);
clk: in std_logic;
enable1: in std_logic;
q: out signed (8 downto 0)
);
end entity;
architecture behavioral of adder1 is
begin
UNLABELLED:
process(clk)
begin
if clk'event and clk ='1' then
if enable1 = '1' then
q <= a1(7) & a1 + a2 ;
end if;
end if;
end process;
end architecture;
The assignment to q looks naked so it's worth explaining.
The "+" in numeric_std for signed will sign extend the shorter operand to match the length of the longer operand.
The rest is priority magic.
"+" and "&" are the same priority, which means they're evaluated in left to right textual order, meaning the sign extension with the concatenation operator is performed first (see IEEE Std 1076-2008, 9.2 Operators).
The "+" operator sees the left operand as longer and matches the right operand to it's length, (see package numeric_std "+" for L,R: signed). It does this by using signed RESIZE on both operands after finding the MAX of the length of both, along with converting metavalues to 'X's.
It works if the right operand is longer too:
q <= a1 + (a2(7) & a2) ;
And here we need parentheses to associate the result of the concatenation operator as the right operand of the adding operator, because the two operators are the same priority and would otherwise be encountered in textual order.
There's no reason to call resize yet again, it's only a one bit sign extension by concatenation, based on knowing the sign is embodied in the left hand element (bit) of a two's compliment number.
The term canonical is not found in the VHDL standard.
As far as Xin, I'd agree with Kevin, something likely needs to be reanalyzed so that both references to signed are found in the same package.
Each declaration used in a design is unique. If say the actual in the port map depends on the type signed declaration in package std_logic_arith and the formal were to depend on the declaration of signed in package numeric_std they would be of different types.

How to declare an output with multiple zeros in VHDL

Hello i am trying to find a way to replace this command: Bus_S <= "0000000000000000000000000000000" & Ne; with something more convenient. Counting zeros one by one is not very sophisticated. The program is about an SLT unit for an ALU in mips. The SLT gets only 1 bit(MSB of an ADDSU32) and has an output of 32 bits all zeros but the first bit that depends on the Ne=MSB of ADDSU32. (plz ignore ALUop for the time being)
entity SLT_32x is
Port ( Ne : in STD_LOGIC;
ALUop : in STD_LOGIC_VECTOR (1 downto 0);
Bus_S : out STD_LOGIC_VECTOR (31 downto 0));
end SLT_32x;
architecture Behavioral of SLT_32x is
begin
Bus_S <= "0000000000000000000000000000000" & Ne;
end Behavioral;
Is there a way to use (30 downto 0)='0' or something like that? Thanks.
Try this: bus_S <= (0 => Ne, others => '0')
It means: set bit 0 to Ne, and set the other bits to '0'.
alternative to the given answers:
architecture Behavioral of SLT_32x is
begin
Bus_S <= (others => '0');
Bus_S(0) <= ne;
end Behavioral;
Always the last assignment in a combinatoric process is taken into account. This makes very readable code when having a default assignment for most of the cases and afterwards adding the special cases, i.e. feeding a wide bus (defined as record) through a hierarchical block and just modifying some of the signals.

Resources