I want to take num as as an 8 bit input and then shift it on every rising edge of clock and out it on output "res". Code is shown below. But when simulated it does not give expected results.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity shiftreg is
port (
num : in std_logic_vector (7 downto 0);
clk : in std_logic;
res : out std_logic_vector (7 downto 0)
);
end entity;
architecture behav of shiftreg is
signal temp_num : std_logic_vector (7 downto 0):= "00000000";
begin
process(num)
begin
if(num' event) then
temp_num <= num;
res<=temp_num;
end if;
end process;
process(clk)
begin
if(rising_edge(clk)) then
temp_num <= shr(temp_num,"01");
res<=temp_num;
end if;
end process;
end behav;
The output res and signal temp_num are both driven from both of the
processes, thus the simulator will do resolution, which is likely to result in
X values for some or all bits.
In general, then signals and output is design modules should be driven from
only a single process, since that is also what synthesis tools expect. For
test benches, then there may be multiple drivers.
So if the intention is that any change in the num input should be reflected
immediately to the res output, and any later rising edge of clk should
result in right shift, then the two processes may be combined in a single
process and assign to res like:
process (num, clk) is
begin
if (num'event) then
temp_num <= num;
elsif (rising_edge(clk)) then
temp_num <= shr(temp_num, "01");
end if;
end process;
res <= temp_num;
This will work in simulation, but the 'event wont work in synthesis, since
there is typically no hardware that can sense value changes like 'event, so
the construction can't be mapped to hardware by synthesis.
So for a synthesizeable design, you may consider adding a load input:
load : in std_logic;
And use this for load of the internal temp_num with a process like:
process (clk) is
begin
if (rising_edge(clk)) then
if load = '1' then
temp_num <= num;
else
temp_num <= shr(temp_num, "01");
end if;
end if;
end process;
res <= temp_num;
Finally, you should consider removing the use ieee.std_logic_arith.all; and
use ieee.std_logic_unsigned.all;, since these two packages are not standard
VHDL packages, despite location in the IEEE library. Simply remove the two
lines, and then use the shift_right function from the std_logic_unsigned
like:
temp_num <= std_logic_vector(shift_right(unsigned(temp_num), 1));
Related
I am a novice coder and don't know if what I did was correct so I would appreciate if someone could double check it for me.
So im trying to make an 8-bit up counter with an active-low count enable control signal. The counter should advance to the next count if cten = 0 and stops at the current count if cten = 1. The counter resets into a state that outputs binary 0 and progresses upward on each clock edge when counting is enabled until it reaches 255. It locks in the state producing output 255. I also tried to change the clock to 1Hz clock from a 50MHz clock the is on a FPGA board that will be used to run some instructions (with there being no more than 255 instructions, hence wanting to lock at that number) based off the count value of int_q.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity counter is
port(
clk, rst, cten: in std_logic;
q: out std_logic_vector(7 downto 0)
);
end entity counter;
architecture moore of counter is
signal d,int_q: std_logic_vector(7 downto 0);
signal cnt: integer range 0 to 25000;
signal clk1Hz: std_logic;
begin
-- drive internal Q signal to output signal
q <= int_q;
-- next-state logic: add 1 unless 255, lock at 255
d <= int_q+1 when int_q < 255;
d <= int_q when int_q = 255;
process(clk)
begin
if rising_edge(clk) then
cnt <= cnt+1;
if cnt = 25000 then
clk1Hz <= not clk1Hz;
cnt <= 0;
end if;
end if;
end process;
-- register process
process(all)
begin
if rising_edge(clk1Hz) then
if rst ='1' then int_q <= "00000000";
elsif cten = '0' then int_q <= int_q+1;
else int_q <= int_q;
end if;
end if;
end process;
end architecture moore;
Several issues:
If rst is unasserted on the rising edge of clk1Hz, then int_q will remain in an unknown state.
clk1Hz is never initialized, so the not operation does nothing.
cnt is never initialized, so incrementing it does nothing.
int_q is being driven in 2 places: both inside and outside a process.
signal d is unused, did you want to connect it to q?
You're only counting to 25_000, but if your source clock is 50 MHz, you need to count to 25_000_000.
If you want a synchronous reset, (which given the name "Moore", I bet this is homework), it's good practice to create a new process specifically to internally synchronize that async reset signal to the system clock, maybe through a 2FF synchronizer for one idea.
If I understood the question correctly, this should get you in the ballpark:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity counter is
port(
clk, rst, cten: in std_logic;
q: out std_logic_vector(7 downto 0)
);
end entity counter;
architecture moore of counter is
signal int_q: std_logic_vector(7 downto 0);
signal cnt: integer range 0 to 25_000_000;
signal clk1Hz: std_logic;
begin
-- indicate when at 255
q <= '1' when int_q = 255 else '0';
process(rst, clk)
begin
if rst = '1' then
-- need to assign initial values
clk1Hz <= '0';
cnt <= 0;
elsif rising_edge(clk) then
if cnt = 25_000_000 then
clk1Hz <= not clk1Hz;
cnt <= 0;
else
cnt <= cnt+1;
end if;
end if;
end process;
-- register process
process(rst, clk1Hz)
begin
if rst = '1' then
int_q <= (others => '0');
elsif rising_edge(clk1Hz) then
if cten = '0' then
int_q <= int_q+1; -- rolls over
end if;
end if;
end process;
end architecture moore;
If you want to map this in an FPGA you cannot generate a clock like you do. Clocks are very special signals with strict electrical requirements. If you need a 1Hz frequency clock and the frequency of your master clock is 50MHz there are basically two options:
Use a clock manager/generator hard macro of your FPGA if it has some, and configure it to generate a 1Hz clock from your master clock. Explicitly pass the output through a clock buffer if your tools don't do it automatically.
Do not generate a 1Hz clock, use an enable signal that you assert high once every 50M clock periods. Or use a rescaler and increment your counter only when the rescaler reaches a predefined value.
As the first option depends on your FPGA, your tools, etc. let's investigate the second:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter is
generic(freqHz: positive := 50000000);
port(clk, rst, cten: in std_ulogic;
q: out std_ulogic_vector(7 downto 0));
end entity counter;
architecture moore of counter is
signal rescaler: integer range 0 to freqHz - 1;
signal cnt: integer range 0 to 255;
begin
q <= std_ulogic_vector(to_unsigned(cnt, 8));
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
rescaler <= freqHz - 1;
cnt <= 0;
elsif cnt /= 255 then
if rescaler /= 0 then
rescaler <= rescaler - 1;
else
rescaler <= freqHz - 1;
cnt <= cnt + 1;
end if;
end if;
end if;
end process;
end architecture moore;
Remarks:
Use ieee.std_logic_unsigned or ieee.numeric_std but not both. And as noted by #JHBonarius, do not use ieee.std_logic_unsigned at all. It is not standard and deprecated. Use ieee.numeric_std_unsigned, instead.
I added a generic parameter (freqHz) with a default value such that you can easily adapt to different clock frequencies.
The 50Mhz to 1Hz rescaler is decremented instead of incremented because a hardware zero detector is frequently slightly smaller and faster than an arbitrary value detector.
If you do not know the difference between std_logic and std_ulogic, always use std_ulogic, never std_logic (and use std_ulogic_vector instead of std_logic_vector, u_unsigned instead of unsigned...) One day or another you will really need std_logic and this day you will understand the difference, and why you should (almost) never use it. And do not listen to people who tell you that std_logic is more standard or better supported by the tools or whatever. They are wrong. The only exception is your teacher or your boss: even if they are wrong, it might be better to obey.
in VHDL all the code lines are executed in a parallel way, since its a machine.
i want to create this RAM that reads a certain register from a ram block to the output and only 'afterwards' writes to the same register the input. my code goes like this:
architecture Behavioral of RAM is
type ram_t is array (0 to numOfRegs-1) of std_logic_vector (rLength-1 downto 0);
signal ram_s: ram_t;
signal loc : integer;
begin
process(clk)
begin
if(rising_edge(clk)) then
if(we='1') then
dataout <= ram_s(loc); -- reads the 'old' data to the output
ram_s(loc) <= datain; -- writes the 'new' data to the RAM
loc <= conv_integer(addr);
end if;
end if;
end process;
end Behavioral;
there is a similar case presented
here.
so I'd like to ask, is my code works fine or is there need for tweaking like putting a delay of half clock cycle, and if so, how to implement it.
I'm very new to VHDL thanks for your patience and help.
ive add a testbench simulation below . as can be seen the dataout isnt working at all.
Your question doesn't present a Minimal, Verifiable and Complete example, lacking the ability to replicate your results.
One of the consequences of this is that answers can be ambiguous should there be one or more causes of the problem in portions of your code not shown.
Brian's comment that you aren't reading data when we is invalid is poignant and would be responsible for 'U's in the clock cycle left of your yellow marker in your waveform.
There's also the issue with loc being a signal. Signals are scheduled for update, and no update occurs while any process that is scheduled to resume in the current simulation cycle has not been resumed and suspended.
This means the integer version of your address is delayed and won't be seen in the process until the next rising edge.
Fixing loc by making it a variable as an alternative to pipelining datain and moving the dataout assignment are accomplished in the following changes to your RAM process:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all; -- standard package
entity ram is
generic (
ADDRLENGTH: natural := 8;
RLENGTH: natural := 16;
NUMOFREGS: natural := 256
);
port (
clk: in std_logic;
we: in std_logic;
addr: in std_logic_vector (ADDRLENGTH - 1 downto 0);
datain: in std_logic_vector (RLENGTH - 1 downto 0);
dataout: out std_logic_vector (RLENGTH - 1 downto 0)
);
end entity;
architecture behavioral of ram is
type ram_t is array (0 to NUMOFREGS - 1) of
std_logic_vector (RLENGTH - 1 downto 0);
signal ram_s: ram_t;
-- signal loc: integer; -- USE VARIABLE in process instead
begin
process(clk)
variable loc: integer; -- MAKE loc variable so it's immediately available
begin
if rising_edge(clk) then
loc := to_integer(unsigned(addr)); -- MOVED so READ works
if we = '1' then
-- dataout <= ram_s(loc); -- reads the 'old' data to the output
ram_s(loc) <= datain; -- writes the 'new' data to the ram
-- loc <= conv_integer(addr);
end if;
dataout <= ram_s(loc); -- MOVED reads the 'old' data to the output
end if;
end process;
end architecture behavioral;
There's also the liberty of filling in the entity declaration and converting from conv_integer using Synopsys's package std_logic_arith to to_integer in the IEEE's numeric_std package. With a -2008 compliant tool chain you could instead use IEEE's package numeric_std_unsigned and do away with the type conversion to unsigned.
Because the ram_test testbench was also not supplied a testbench was written to replicate your waveform display image:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ram_tb is
end entity;
architecture foo of ram_tb is
constant ADDRLENGTH: natural := 8;
constant RLENGTH: natural := 16;
constant NUMOFREGS: natural := 256;
signal clk: std_logic := '0';
signal we: std_logic := '1';
signal addr: std_logic_vector (ADDRLENGTH - 1 downto 0);
signal datain: std_logic_vector (RLENGTH - 1 downto 0);
signal dataout: std_logic_vector (RLENGTH - 1 downto 0);
begin
DUT:
entity work.ram
generic map (
ADDRLENGTH => ADDRLENGTH,
RLENGTH => RLENGTH,
NUMOFREGS => NUMOFREGS
)
port map (
clk => clk,
we => we,
addr => addr,
datain => datain,
dataout => dataout
);
CLOCK:
process
begin
if now = 500 ps then
wait for 200 ps;
else
wait for 100 ps;
end if;
clk <= not clk;
if now >= 1100 ps then
wait;
end if;
end process;
STIMULI:
process
begin
for i in 0 to 2 loop
addr <= std_logic_vector(to_unsigned (i, ADDRLENGTH));
case i is
when 0 =>
datain <= x"00FF";
when 1 =>
datain <= x"FF00";
when 2 =>
datain <= x"FFFF";
end case;
wait until falling_edge(clk);
if i = 1 then
we <= '0';
end if;
end loop;
for i in 1 to 2 loop
addr <= std_logic_vector(to_unsigned (i, ADDRLENGTH));
case i is
when 1 =>
datain <= x"FF00";
when 2 =>
datain <= x"FFFF";
end case;
wait until falling_edge(clk);
end loop;
wait;
end process;
end architecture;
And this produced:
Where the one written address that is subsequently read shows the correct data.
The simulator used does not present non-signals in a waveform dump (bounds in declarations are required to be static) and rst is not found in the portion of your design specification provided.
As noted previously there is no guarantee there isn't another issue with portions of your design specification or testbench not provided in your question.
The testbench shown is by no means comprehensive.
I need to share a value (a real) between two process, but when I try to run my code, quartus gives me an error.
library IEEE;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
use IEEE.MATH_REAL.ALL;
entity de0nano is
port (
CLOCK_50 : in std_logic;
KEY : in std_logic_vector(1 downto 0);
SW : in std_logic_vector(3 downto 0);
LED : out std_logic_vector(7 downto 0);
GPIO : inout std_logic_vector(35 downto 0)
);
end de0nano;
architecture struct of de0nano is
--declarations
signal PN : real :=0.0 ;
signal PR : real :=0.0 ;
signal RC : integer :=1;
signal NC : integer :=1;
signal BET : integer :=1;
begin
count : process (CLOCK_50, GPIO)
begin
--A <= KEY(0);
GPIO(24) <= '1';
--functional coding
LED <= "00011000";
if (pn > pr) then
GPIO(26) <= '1';
LED <= "00000001";
else
GPIO(26) <= '0';
end if;
if (pn = pr) then
GPIO(26) <= '1';
LED <= "00000010";
else
GPIO(26) <= '0';
end if;
if (pn < pr) then
GPIO(26) <= '1';
LED <= "00000011";
else
GPIO(26) <= '0';
end if;
end process;
probabilityController : process (CLOCK_50, KEY)
begin
--stato iniziale
if((RC + NC + BET)=1) then
pr <= 0.5;
pn <= 0.5;
end if;
--sequenza rossi consecutivi
if(RC>0) then
pr <= (5)**RC;
pn <= 1- (5)**RC;
end if;
--sequenza neri consecutivi
if(NC>0) then
pr <= (5)**NC;
pn <= 1- (5)**NC;
end if;
end process;
betController : process (CLOCK_50)
begin
end process;
colorController : process (CLOCK_50, KEY)
begin
if(KEY(0)='1') then
NC<=0;
RC <= RC+1;
end if;
if(KEY(1)='1') then
RC<=0;
NC <= NC+1;
end if;
end process;
end str
How can I operate in the same signal/variable from two different processes?
VHDL is a hardware description language. A VHDL description can be simulated (executed a bit like you do with most programming languages) or synthesized (transformed in a network of interconnected simple hardware elements). Some tools are pure simulators (Mentor Graphics Modelsim, Cadence ncsim...), others are pure synthesizers (Mentor Graphics Precision RTL, Cadence RTL compiler...) and others can do both. Quartus pertains to the last category. So, the first thing to do is to decide whether you want to simulate, synthesize or both.
In case you want to simulate you must fix three errors:
the position of your signal declaration,
the way you assign it (:=) which is the variable assignment operator, not the signal assignment (<=)
and the fact that you drive it from two processes while it is of an unresolved type (real). See this other answer for resolved / unresolved VHDL types.
Your code could then look like this (but as I do not know what you are trying to do, it is probably not what you want):
architecture V1 of AOI is
Signal foobar : real := 0.0;
begin
OneTwo : process (clk)
Begin
Foobar <= foobar + 2.0;
End process;
end V1;
If you want to synthesize you will have to fix a few more problems:
You are using the real type which is the floating point VHDL type. This is not synthesizable by the synthesizers I know. Indeed, what would you expect the synthesizer to do? Instantiate a complete floating point unit? What brand? So, you will have to replace real by some other type (integers, bit vectors...).
You are assigning your signal on both edges of what I believe is your clock (clk). This is probably not what you want.
You are initializing the signal at declaration time. This is usually not synthesizable by the synthesizers I know. In fact this initialization time has a clear meaning for simulation: it is the beginning of the simulation. But what about hardware? What is the beginning of a piece of hardware? Manufacturing? Power up? So, if you want the signal to be initialized at some point you will have to add a hardware reset, driven by a reset input.
All in all you could have something like:
architecture V1 of AOI is
Signal foobar : natural range 0 to 255;
begin
OneTwo : process (clk)
Begin
if rising_edge(clk) then
if reset = '1' then
foobar <= 0;
else
foobar <= foobar + 2;
end if;
end if;
End process;
end V1;
Notes:
VHDL is case insensitive but you should try to be consistent, it will help you.
You should probably take a VHDL course or read a VHDL primer before trying to use the language. It is radically different from the programming languages you already know. Hardware and software are pretty different worlds, even if they are strongly connected at the end.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
-- use ieee.std_logic_arith.all;
-- use ieee.numeric_std.all;
-- entity part contain R for output of Register
entity register_16 is
port( input: in std_logic_vector(15 downto 0);
ld, inc, clk, clr: in std_logic;
R: buffer std_logic_vector(15 downto 0));
end register_16 ;
-- it have to parallel process
architecture behavioral of register_16 is
begin
reg: process (input, ld, clk, clr)
variable R_temp: std_logic_vector(15 downto 0);
begin
if (clr = '1') then
R_temp := b"0000000000000000";
elsif (clk'event and clk = '1') then
if (ld = '1') then
R_temp := input;
end if;
end if;
R <= R_temp;
end process reg;
-- my error in this step
inc_R: process (inc)
begin
R <= R + '1';
end process inc_R;
end behavioral;
Main process (reg) works correctly, but other process has error adding 1.
You will have to convert the vector to an integer an back again, here's an example:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
signal in : std_logic_vector( 7 downto 0 );
signal out : std_logic_vector( 7 downto 0 );
out <= std_logic_vector(to_unsigned(to_integer(unsigned( in )) + 1, 8));
For a good picture about type conversion take a look here:
http://www.bitweenie.com/listings/vhdl-type-conversion/
Sorry to say, but there are quite a lot of things wrong with your code...
You are mixing combinatorial and sequential code in the same process, which is poor coding style. If coded correctly, there really is no need for the variable R_temp.
The sensitivity list is a simulation aid only, yet you are trying to use it as a conditional (when inc changes, increment R). This will not work in hardware. When starting out with VHDL, my suggestion is to use VHDL_2008 and always use process(all) as the sensitivity list. This avoids beginner errors, since it reflects what synthesis does.
You are creating a combinatorial loop in the second process. This will not show up in simulation because of 2. above, but will cause errors in synthesis.
As already mentioned by baldyHDL, you are assigning to R in multiple processes.
Prefer unsigned to std_logic_vector when dealing with numbers. Generally you should not include std_logic_arith, nor std_logic_unsigned, just std_logic_1164 and numeric_std.
Adding a std_logic value (such as '1') is not standard, or at least not supported by all tools. Simply use an integer instead: R <= R + 1;
By your code, I gather that you are trying to write a counter with increment, load and clear signals. I don't just want to give you the code (that would ruin the learning experience for you), but try to fit the entire counter into a single process, using the following template:
process(clk) begin
if(rising_edge(clk)) then
-- Your code here vvv
if(clr = '1') then
elsif(ld = '1') then
elsif(inc = '1') then
end if;
-- Your code here ^^^
end if;
end process;
you write R in both of your processes. this leads to a multi-driver situation that is not possible to synthesise. to solve it, combine the processes, e.g.:
reg: process (clk, clr)
variable R_temp : std_logic_vector(15 downto 0);
begin
if (clr='1') then
R_temp := b"0000000000000000";
elsif (clk'event and clk='1') then
if (ld='1') then
R_temp := input;
elsif (inc='1') then
R_temp := R_temp + '1';
end if;
end if;
R <= R_temp;
end process reg;
You should be able to add a vector containing the value 1 as this, as you are using the numeric_std library:
R <= R + x"0001";
I used the following libraries and it was able to do something similar
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
...
signal cnt : std_logic_vector(3 downto 0);
begin
process(clk, reset, ce, cnt)
begin
if(reset = '1') then
cnt <= "0000";
elsif(clk'event and clk='1') then
if(ce='1') then
if(cnt = "1001") then
cnt <= "0000";
else
cnt <= cnt + 1;
I want to swap the value of input0 and input1, and output the smaller one. When I simulate my project in Modelsim, the waveform of signal output is red line. What is my mistake?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity MF is
port (clk : in std_logic;
input0: in std_logic_vector(2 downto 0);
input1: in std_logic_vector(2 downto 0));
end MF;
architecture Behavioral of MF is
signal bubble0: std_logic_vector(2 downto 0);
signal bubble1: std_logic_vector(2 downto 0);
begin
bubble0 <= input0;
bubble1 <= input1;
output <= bubble0; -- my output
process(clk)
begin
if rising_edge(clk) then
if bubble0 > bubble1 then -- swap
bubble1 <= bubble0;
bubble0 <= bubble1;
end if;
end if;
end process;
end Behavioral;
I see several issues:
1) You are assigning values to bubble0 and bubble1 both asynchronously and inside a process (this is a "bus fight" with more than one driver on each signal, which IS legal in VHDL, but you have to be aware of what you're doing...typically this is used to make tri-state buses, but both of your assignments are driving the signal constantly which likely results in the 'undefined' state when resolving the signal).
2) You are not assigning values to bubble0 and bubble1 in all cases of your if statement inside the process.
3) You cannot directly compare two std_logic_vector values for numeric magnitude, you first need to cast them to an appropriate numeric type (such as signed or unsigned).
It is unclear exactly how you want your output to behave, but perhaps something like the following will get you farther along...this updates the bubble signals as appropriate at each rising edge of the clock:
begin
output <= bubble0; -- my output
process(clk)
begin
if rising_edge(clk) then
if unsigned(input0) > unsigned(input1) then -- swap
bubble1 <= input0;
bubble0 <= input1;
else
bubble0 <= input0;
bubble1 <= input1;
end if;
end if;
end process;
end Behavioral;