Everything works but the increment function. It can increment from 0 to 1, 1 to 2, and then from 2 it goes to "1111111111". I'm stumped.
Variables:
D_IN: Data in
PC_OE: Active high. Drives PC_TRI output.
PC_LD: Active high synchronously loads D_IN into PC.
PC_INC: Active high synchronously increments value in PC.
RST: Active high asyncronous reset.
PC_COUNT: Current value in PC. Address.
PC_TRI: Current value in the PC under tri-state control. When PC_OE = '1', PC_TRI <=
PC_COUNT, else high impedance.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
entity ProgramCounter is
Port ( D_IN : in STD_LOGIC_VECTOR (9 downto 0);
PC_OE : in STD_LOGIC;
PC_LD : in STD_LOGIC;
PC_INC : in STD_LOGIC;
RST : in STD_LOGIC;
CLK : in STD_LOGIC;
PC_COUNT : out STD_LOGIC_VECTOR (9 downto 0);
PC_TRI : out STD_LOGIC_VECTOR (9 downto 0));
end ProgramCounter;
architecture Behavioral of ProgramCounter is
signal s_COUNT : STD_LOGIC_VECTOR (9 downto 0);
begin
s_COUNT <= "0000000000";
proc: process(RST, CLK, PC_LD, D_IN, s_COUNT, PC_INC, PC_OE)
begin
if (RST = '1') then
s_COUNT <= "0000000000";
elsif (rising_edge(CLK)) then
if (PC_LD = '1') then
s_COUNT <= D_IN;
elsif (PC_INC = '1') then
s_COUNT <= s_COUNT + 1;
else
end if;
else
end if;
if (PC_OE = '1') then
PC_TRI <= s_COUNT;
else
PC_TRI <= "ZZZZZZZZZZ";
end if;
PC_COUNT <= s_COUNT;
end process proc;
end Behavioral;
The comment of QuantumRipple is very useful
begin
--s_COUNT <= "0000000000";
...
I tried to comment such line and it worked.
Try to do this, and make RST before start to count
Please try this way and let me know, i corrected your code but I can't try it :
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
entity ProgramCounter is
Port ( D_IN : in STD_LOGIC_VECTOR (9 downto 0);
PC_OE : in STD_LOGIC;
PC_LD : in STD_LOGIC;
PC_INC : in STD_LOGIC;
RST : in STD_LOGIC;
CLK : in STD_LOGIC;
PC_COUNT : out STD_LOGIC_VECTOR (9 downto 0);
PC_TRI : out STD_LOGIC_VECTOR (9 downto 0));
end ProgramCounter;
architecture Behavioral of ProgramCounter is
signal s_COUNT : STD_LOGIC_VECTOR (9 downto 0);
begin
proc: process(RST, CLK)
begin
if (RST = '1') then
s_COUNT <= "0000000000";
elsif (rising_edge(CLK)) then
if (PC_LD = '1') then
s_COUNT <= D_IN;
elsif (PC_INC = '1') then
s_COUNT <= s_COUNT + 1;
else
end if;
else
end if;
end process;
PC_TRI <= s_COUNT when (PC_OE = '1') else (others => 'Z');
PC_COUNT <= s_COUNT;
end Behavioral;
Related
I have a simple program. I am trying to input the counter output into a memory address register and output the data that is in the memory address register.
Memory Address Register Code:
library ieee;
use ieee.std_logic_1164.all;
entity mar is
port(
mar_clk, mar_clr, mar_en : in std_logic;
mar_datain : in std_logic_vector(3 downto 0);
mar_dataout : out std_logic_vector(3 downto 0)
);
end entity;
architecture behavioral of mar is
begin
process(mar_clk, mar_clr, mar_en, mar_datain)
begin
if(mar_clr = '1') then
mar_dataout <= (others => '0');
elsif(mar_clk'event and mar_clk = '1') then
if(mar_en = '0') then
mar_dataout <= mar_datain;
end if;
end if;
end process;
end behavioral;
Buffer4 Code:
library ieee;
use ieee.std_logic_1164.all;
entity buffer4 is
port(
buff4_en : in std_logic;
datain : in std_logic_vector( 3 downto 0 );
dataout : out std_logic_vector( 3 downto 0 )
);
end entity;
architecture behavioral of buffer4 is
begin
process(buff4_en, datain)
begin
if(buff4_en = '1') then
dataout <= datain;
else
dataout <= (others => 'Z');
end if;
end process;
end behavioral;
Program Counter Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity pc is
port(
pc_ld, pc_en, pc_clk, pc_rst : in std_logic;
pc_datain : in std_logic_vector(3 downto 0);
pc_dataout : out std_logic_vector(3 downto 0)
);
end entity;
architecture behave of pc is
signal count : std_logic_vector(3 downto 0) := "0001";
signal temp : integer;
begin
process(pc_clk, pc_rst)
begin
if(pc_rst = '1') then
count <= (others => '0');
elsif(pc_clk'event and pc_clk = '1') then
if(pc_ld = '1') then
count <= pc_datain;
elsif(pc_en = '1') then
count <= count;
temp <= conv_integer(count);
if(temp = 16) then
count <= (others => '0');
end if;
count <= count + 1;
end if;
end if;
end process;
pc_dataout <= count;
end behave;
Test Program Code:
library ieee;
use ieee.std_logic_1164.all;
entity test is
end entity;
architecture behave of test is
component mar
port(
mar_clk, mar_clr, mar_en : in std_logic;
mar_datain : in std_logic_vector( 3 downto 0 );
mar_dataout : out std_logic_vector( 3 downto 0 )
);
end component;
component pc
port(
pc_ld, pc_en, pc_clk, pc_rst : in std_logic;
pc_datain : in std_logic_vector(3 downto 0);
pc_dataout : out std_logic_vector(3 downto 0)
);
end component;
component buffer4
port(
buff4_en : in std_logic;
datain : in std_logic_vector( 3 downto 0 );
dataout : out std_logic_vector( 3 downto 0 )
);
end component;
signal databus : std_logic_vector(7 downto 0);
signal addressbus : std_logic_vector(3 downto 0);
signal gclk : std_logic;
signal mar_clr, mar_en : std_logic;
signal pc_ld, pc_en, pc_rst : std_logic;
signal buff4_en : std_logic;
signal dataout : std_logic_vector(3 downto 0);
signal mar_datain, mar_dataout : std_logic_vector(3 downto 0);
signal pc_dataout : std_logic_vector(3 downto 0);
begin
U1 : pc port map(pc_ld, pc_en, gclk, pc_rst, databus(3 downto 0), pc_dataout);
U2 : buffer4 port map(buff4_en, pc_dataout, databus(3 downto 0));
U3 : mar port map(gclk, mar_clr, mar_en, databus(3 downto 0), addressbus);
stim_process : process
begin
gclk <= '0';
wait for 10 ns;
pc_ld <= '0';
pc_en <= '1';
pc_rst <= '0';
buff4_en <= '1';
mar_clr <= '0';
mar_en <= '0';
gclk <= '1';
wait for 10 ns;
gclk <= '0';
wait for 10 ns;
assert false report "Reached end of test. Start GTKWave";
wait;
end process;
end behave;
This is the output when I run the program
As seen the Memory Address Registers takes the input and doesn't output it on the address bus. How can I make the Memory Address Register output the data on the address bus?
This is the logic for writing to your memory address output register inside your 'MAR' component:
if(mar_clr = '1') then
mar_dataout <= (others => '0');
elsif(mar_clk'event and mar_clk = '1') then
if(mar_en = '0') then
mar_dataout <= mar_datain;
end if;
end if;
If appears that at your rising edge of clock (mar_clk'event and mar_clk = '1') in the waveforms that mar_clr and mar_en are both undefined U's. They have not got their values yet when the rising edge occurs.
You need to redo your testbench to make sure input signals are stable+defined before the rising edge so they are sampled correctly. Then mar_dataout <= mar_datain; should take correctly.
Could try moving initial wait statement like so:
gclk <= '0';
pc_ld <= '0';
pc_en <= '1';
pc_rst <= '0';
buff4_en <= '1';
mar_clr <= '0';
mar_en <= '0';
wait for 10 ns;
gclk <= '1';
wait for 10 ns;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity sqwaveGen is
port (
clk : in std_logic;
clk_out : out std_logic;
fall : in unsigned(7 downto 0);
reset : in std_logic;
rise : in unsigned(7 downto 0)
);
end entity;
architecture from_verilog of sqwaveGen is
signal count : unsigned(7 downto 0); -- Declared at design.sv:7
signal count_off : unsigned(7 downto 0); -- Declared at design.sv:7
signal count_on : unsigned(7 downto 0); -- Declared at design.sv:7
signal pos_or_neg : std_logic; -- Declared at design.sv:8
begin
clk_out <= pos_or_neg;
process (clk, reset) is
begin
if (not reset) = '1' then
count <= X"00";
count <= X"00";
pos_or_neg <= '1';
elsif rising_edge(clk) then
if (unsigned'("0000000000000000000000000000000") & pos_or_neg) = X"00000001" then
if Resize(count, 32) = (Resize(count_on, 32) - X"00000001") then
count <= X"00";
pos_or_neg <= '0';
else
count <= count + X"01";
end if;
else
if (unsigned'("0000000000000000000000000000000") & pos_or_neg) = X"00000000" then
if Resize(count, 32) = (Resize(count_off, 32) - X"00000001") then
count <= X"00";
pos_or_neg <= '1';
else
count <= count + X"01";
end if;
end if;
end if;
end if;
end process;
process (fall, rise) is
begin
count_on <= rise;
count_off <= fall;
end process;
end architecture;
You're trying to simulate a VHDL design with Icarus (iverilog) simulator, which is a Verilog simulator and does not support VHDL!
Use should use a simulator which supports VHDL, such as GHDL or Xilinx Vivado. Also save the file with ".vhd" or ".vhdl" extension.
I'm trying to write register vhdl code in modelSim,My code is here:
Library ieee;
use ieee.std_logic_1164.all;
------------------------------
entity reg_8Bit is
Generic(N:integer := 8);
port(clk,reset:in std_logic;
ctrl:in std_logic_vector(1 downto 0);
d:in std_logic_vector(n-1 downto 0);
q:out std_logic_vector(n-1 downto 0);
d2:out std_logic
);
end reg_8Bit;
-------------------------------
Architecture arch_8bit of reg_8Bit is
signal r_reg,r_next:std_logic_vector(n-1 downto 0);
begin
process(clk,reset)
begin
if(reset = '1') then
q <= (others => '0');
elsif(clk='1' and clk 'event) then
r_reg <= r_next;
end if;
end process;
with ctrl select
r_next <= r_reg when "00",
r_reg(n-2 downto 0) & d(i) when "10",
d(7) & r_reg(n-1 downto 1) when "01",
d when others;
q <= r_reg;
end arch_8bit;
I Want to create shift to right when ctrl = "01" and shift to left when
ctrl = "10" But I get just d(0) or d(7),How I can fixed it?
Problems with your code:
Signal q is multiple driven.
Your are resetting q but not r_reg
Improved code:
library ieee;
use ieee.std_logic_1164.all;
------------------------------
entity reg_8Bit is
generic(
N:integer := 8
);
port(
clk : in std_logic;
reset : in std_logic;
ctrl : in std_logic_vector(1 downto 0);
d : in std_logic_vector(n-1 downto 0);
q : out std_logic_vector(n-1 downto 0);
d2 : out std_logic
);
end entity;
-------------------------------
architecture arch_8bit of reg_8Bit is
signal r_reg : std_logic_vector(n-1 downto 0) := (others => '0');
begin
process(clk,reset)
begin
if(reset = '1') then
r_reg <= (others => '0');
elsif rising_edge(clk) then
if ctrl = "11" then
r_reg <= d;
elsif ctrl = "10" then
r_reg <= r_reg(r_reg'high - 1 downto r_reg'low) & d(0);
elsif ctrl = "01" then
r_reg <= d(7) & r_reg(r_reg'high downto r_reg'low + 1);
end if;
end if;
end process;
q <= r_reg;
end arch_8bit;
Other hints:
Don't use asynchronous resets.
Use rising_edge(clk) instead of clk'event ....
You can avoid the additional signal r_reg if you enabled VHDL-2008 in your tool.
In VHDL-2008, you can read back values from out ports.
i have an assignment to write a state machine in VHDL to take control of a small built MC ( consists of 4 flip-flops,2 MUX4to1, MUX1to4, ROM, ALU,Inport ).
i have written different codes and tried several methods however simulating it shows no results, i get 'U' for results.
Code below, please check for obvious errors which I've probably missed.
i think the problem is that the stjatemachine doesn't transition through the states or doesn't execute the code inside each state.
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 07:48:47 10/26/2014
-- Design Name:
-- Module Name: STATE_MACHINE - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.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;
entity STATE_MACHINE is
port (
--General Ports
CLK : in STD_LOGIC;
Re_Run_Programme : in STD_LOGIC;
--Process A parts
Programme_Start : in STD_LOGIC;
Data_From_ROM : in STD_LOGIC_VECTOR(7 downto 0);
ADDR_To_ROM : out STD_LOGIC_VECTOR (5 downto 0);
Programme_Status: out STD_LOGIC;
EN_OUT : out STD_LOGIC;
--Process B Part
--Process C Parts
MUX_FF_Select : out STD_LOGIC_VECTOR (1 downto 0);
MUX1_Select : out STD_LOGIC_VECTOR(1 downto 0);
MUX2_Select : out STD_LOGIC_VECTOR(1 downto 0);
ALU_Select : out STD_LOGIC_VECTOR(1 downto 0);
EN_A_Ports : out STD_LOGIC;
EN_B_Ports : out STD_LOGIC;
BUS_Select : out STD_LOGIC_VECTOR (1 downto 0);
Reset : out STD_LOGIC
);
end STATE_MACHINE;
architecture Behavioral of STATE_MACHINE is
type State_Type is (State_A,State_B,State_C,State_D);
signal State,Next_State : State_Type;
signal Counter : STD_LOGIC_VECTOR(5 downto 0);
--signal MO_A : STD_LOGIC;
--signal MO_B : STD_LOGIC;
--signal MO_C : STD_LOGIC;
--signal MO_D : STD_LOGIC;
signal FF_Instruction : STD_LOGIC_VECTOR (7 downto 0); -- 00
signal MUX_ALU_Instruction : STD_LOGIC_VECTOR (7 downto 0); -- 01
signal BUS_A_B_Ports_Instruction : STD_LOGIC_VECTOR (7 downto 0); -- 10
signal Reset_Instruction : STD_LOGIC_VECTOR (7 downto 0);
signal FF_Path : STD_LOGIC;
signal MUX_ALU_Path : STD_LOGIC;
signal BUS_A_B_Ports_Path : STD_LOGIC;
signal Reset_Path : STD_LOGIC;
signal EN_OUT_reg : STD_LOGIC;
--signal Next_Call : STD_LOGIC_VECTOR (7 downto 0);
signal Instruction_Finder : STD_LOGIC_VECTOR (7 downto 0);
signal Instruction_Identifier : STD_LOGIC_VECTOR(7 downto 0);
signal Instruction : STD_LOGIC_VECTOR(7 downto 0);
signal Call_Next_Instruction : STD_LOGIC_VECTOR(5 downto 0);
begin
FF_Instruction <= "00000000";
MUX_ALU_Instruction <= "01000000";
BUS_A_B_Ports_Instruction <= "10000000";
Reset_Instruction <= "11000000";
Instruction_Finder <= "11000000";
Counter <= "000000";
Call_Next_Instruction <= "000000";
--Re Run the programme
Process(CLK)
begin
if rising_edge(CLK) then
if (Re_Run_Programme = '1') then
State <= State_A;
-- MO_A <= '0';
else
State <= Next_State;
end if;
end if;
end Process;
--next state
Process(CLK,State)
begin
Next_State <= State;
case State is
--#### STATE A #####
when State_A =>
--if falling_edge(CLK) then
ADDR_To_ROM <= Call_Next_Instruction;
--EN_OUT <= '1';
--if falling_edge (CLK) then
--Instruction <= DATA_From_ROM;
--end if;
Next_State <= State_B;
--end if;
--#### STATE B #####
when State_B =>
EN_OUT <= '1';
Instruction <= DATA_From_ROM;
Instruction_Identifier <= (Instruction and Instruction_Finder);
case (Instruction_Identifier) is
when "00000000" => FF_Path <= '1';
when "01000000" => MUX_ALU_Path <= '1';
when "10000000" => BUS_A_B_Ports_Path <= '1';
when "11000000" => Reset_Path <= '1';
when others => null;
end case;
Next_State <= State_C after 40ns;
--#### STATE C #####
when State_C =>
--########
if ((FF_Path = '1') and (Counter = 2)) then
MUX_FF_Select <= "00";
end if;
if ((FF_Path = '1') and (Counter = 4)) then
MUX_FF_Select <= "00" after 20ns;
end if;
--########
if (falling_edge(CLK) and (MUX_ALU_Path = '1')) then
MUX1_Select <= "00";
MUX2_Select <= "00";
end if;
--########
if ( rising_edge(CLK) and BUS_A_B_Ports_Path = '1') then
if Counter = 1 then
BUS_Select <= "01";
end if;
if Counter = 3 then
BUS_Select <= "10";
end if;
EN_A_Ports <= '1';
EN_B_Ports <= '1';
end if;
--########
if ( rising_edge(CLK) and Reset_Path = '1') then
Reset <= '1';
end if;
Next_State <= State_D after 60ns;
--#### STATE D #####
when State_D =>
EN_OUT <= '0';
Counter <= Counter + 1;
if Counter > 5 then
Next_State <= State_D;
end if;
Call_Next_Instruction <= Counter;
Next_State <= State_A;
end case;
end process;
end Behavioral;
github link to code: https://github.com/quasarMind/StateMachine.git
Besides comments by Bill Lynch and Brian Drummond addressing synthesis eligibility a reason why the model gets all 'U's appears to revolve around multiple drivers for
Instruction_Finder, Counter and Call_Next_Instruction. One driver is initialized the other delivering all 'U's, the two resolve to all 'U's.
For purposes of simulating to see what your state machine actually does (and sidestepping the issue of synthesis), set default values for these three signals in their declarations and comment out the additional concurrent signal assignment statements, e.g.:
signal Counter : STD_LOGIC_VECTOR(5 downto 0) := (others => '0');
signal Instruction_Finder : STD_LOGIC_VECTOR (7 downto 0) := "11000000";
signal Call_Next_Instruction : STD_LOGIC_VECTOR(5 downto 0) := (others => '0');
-- Instruction_Finder <= "11000000";
-- Counter <= "000000";
-- Call_Next_Instruction <= "000000";
Most synthesis vendors will honor default values for signals for FPGA targets, otherwise you can add a reset.
I have an FPGA with four push buttons - the two left most ones should cycle up and down the 16 registers, while the two right most ones should increment and decrement the value stored in this register. Here is my attempt at the code to do this:
entity raminfr is --inferring the RAM here
port (
clk : in std_logic;
we : in std_logic;
a : in unsigned(3 downto 0);
di : in unsigned(7 downto 0);
do : out unsigned(7 downto 0)
);
end raminfr;
architecture rtl of raminfr is
type ram_type is array (0 to 15) of unsigned(7 downto 0);
signal RAM : ram_type;
signal read_a : unsigned(3 downto 0);
begin
U1: entity work.lab1 port map ( --ERROR ON THIS LINE
register_counter => a,
value_counter => di
);
process (clk)
begin
if rising_edge(clk) then
if we = '1' then
RAM(to_integer(a)) <= di;
end if;
read_a <= a;
end if;
end process;
do <= RAM(to_integer(read_a));
end rtl;
--lab1 starts here
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity lab1 is
port(
clock : in std_logic;
key : in std_logic_vector(3 downto 0);
value_counter : out unsigned(7 downto 0) ; --value to be written to register
register_counter : out unsigned(3 downto 0) --register to write value to
);
end lab1;
architecture up_and_down of lab1 is --actual button logic here
begin
process(clock)
begin
if rising_edge(clock) then
if (key(3)='0' and key(2)='0' and key(1)='1' and key(0)='0') then
value_counter <= value_counter + "1";
elsif (key(3)='0' and key(2)='0' and key(1)='0' and key(0)='1') then
value_counter <= value_counter - "1";
elsif (key(3)='1' and key(2)='0' and key(1)='0' and key(0)='0') then
register_counter<= register_counter + "1";
elsif (key(3)='0' and key(2)='1' and key(1)='0' and key(0)='0') then
register_counter<= register_counter - "1";
end if;
end if;
end process;
end architecture up_and_down;
I get the error Error (10577): VHDL error at DE2_TOP.vhd(312): actual port "a" of mode "in" cannot be associated with formal port "register_counter" of mode "out"on the line indicated above. It is obvious this is not how I would go about doing what I want to do. Can someone shed some light on this?
Change your point of view: Put the RAM under the Pushbutton-FSM. Not vice versa.
This RAM description should be synthesiable. If not take a look in the Synthesis Guide of your tool vendor.
entity raminfr is --inferring the RAM here
port (
clk : in std_logic;
we : in std_logic;
a : in unsigned(3 downto 0);
di : in unsigned(7 downto 0);
do : out unsigned(7 downto 0)
);
end entity raminfr;
architecture rtl of raminfr is
type ram_type is array (0 to 15) of unsigned(7 downto 0);
signal RAM : ram_type;
begin
process (clk)
begin
if rising_edge(clk) then
if we = '1' then
RAM(to_integer(a)) <= di;
end if;
do <= RAM(to_integer(a));
end if;
end process;
end architecture rtl;
You also forgot to activate the write enable for the RAM.
Maybe you try this code (Always do a simulation first!):
--lab1 starts here
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity lab1 is
port(
clock : in std_logic;
key : in std_logic_vector(3 downto 0);
value_counter : out unsigned(7 downto 0); --value to be written to register
ram_data : out unsigned(7 downto 0); --value from 'RAM-register'
register_counter : out unsigned(3 downto 0) --register to write value to
);
end lab1;
architecture up_and_down of lab1 is --actual button logic here
signal value : unsigned(7 downto 0) := (others => '0');
signal ram_a : unsigned(3 downto 0) := (others => '0');
signal ram_we : std_logic;
begin
-- infer your RAM
your_ram: entity work.raminfr
port map (
clk => clock, --: in std_logic;
we => ram_we, --: in std_logic;
a => ram_a, --: in unsigned(3 downto 0);
di => value, --: in unsigned(7 downto 0);
do => ram_data --: out unsigned(7 downto 0)
);
process(clock)
begin
if rising_edge(clock) then
-- default
ram_we <= '0';
-- change value
if key(1) = '1' then
value <= value + 1;
end if;
-- change value
if key(0) = '1' then
value <= value - 1;
end if;
-- change 'register'
if key(3) = '1' then
ram_a <= ram_a + 1;
end if;
-- write value to register
if key(2) = '1' then
ram_we <= '1';
end if;
end if;
end process;
value_counter <= value;
register_counter <= ram_a;
end architecture up_and_down;