VHDL State Machine Problems - Repeats States - vhdl
We are building a processor for our final project. The control unit is a state machine, but it seems to get stuck in states for longer than it should, and thus it repeats instructions.
We are using Vivado 2015.4 and the Nexys4 board.
So, with a single line of instructions to store a value onto the 7-segments loaded up into the instruction memory, the states go:
Fetch =>
Fetch =>
Fetch =>
L_S_D (Load/Store Decode) =>
L_S_E (Load/Store Execute) =>
S_Mem (Store Memory Access) =>
Fetch =>
L_S_D =>
L_S_E =>
S_Mem =>
Fetch =>
L_S_D =>
L_S_E =>
Fetch (forever)
On the two complete run-throughs, the seven-segments display. On the third, incomplete run-through, they do not.
I'm attaching the state machine (relevant states) and the program counter-related code, because I think that's where the problem is.
State machine:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Fred is
Port ( Inst : in STD_LOGIC_vector (31 downto 21);
clk : in std_logic;
rst : in std_logic;
Reg2Loc : out std_logic;
ALUSRC : out std_logic;
MemtoReg : out std_logic;
RegWrite : out std_logic;
Branch : out std_logic;
ALUOp : out std_logic_vector (1 downto 0);
UnconB : out std_logic;
en : out std_logic;
wea : out std_logic;
PCWrite : out std_logic;
REGCEA : out std_logic;
LEDCode : out std_logic_vector (4 downto 0));
end Fred;
architecture Behavioral of Fred is
Type type_fstate is (Fetch, L_S_D, L_S_E, L_Mem, S_Mem,
L_WB, R_I_D, I_E, R_E, I_WB, R_WB, B_E, CBZ_D, B_WB, CBZ_E,
CBZ_WB);
attribute enum_encoding : string;
attribute enum_encoding of type_fstate : type is "one-hot";
signal current_state : type_fstate;
signal next_state : type_fstate;
begin
clockprocess : process (clk, rst, current_state)
begin
if rst = '1' then
next_state <= Fetch;
elsif clk'EVENT and clk = '1' then
next_state <= current_state;
end if;
end process clockprocess;
state_logic: process (next_state)
begin
case next_state is
when Fetch => --00001
if ((Inst = "11111000010")) then --LDUR
current_state <= L_S_D;
elsif ((Inst = "11111000000")) then --STUR
current_state <= L_S_D;
--Additional State Logic Here
else
current_state <= Fetch;
end if;
when L_S_D => --00010
current_state <= L_S_E;
when L_S_E => --00011
if ((Inst = "11111000010")) then
current_state <= L_Mem;
elsif ((Inst = "11111000000")) then
current_state <= S_Mem;
end if;
when S_Mem => --00110
current_state <= Fetch;
--Additional States Here
when others =>
current_state <= Fetch;
end case;
end process state_logic;
output_logic : process (next_state)
begin
case next_state is
when Fetch =>
Reg2Loc <= '0';
ALUSRC <= '0';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '0';
REGCEA <= '1';
LEDCode <= "00001";
when L_S_D =>
Reg2Loc <= '1';
ALUSRC <= '0';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '0';
REGCEA <= '0';
LEDCode <= "00010";
when L_S_E =>
Reg2Loc <= '1';
ALUSRC <= '1';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '1';
REGCEA <= '0';
LEDCode <= "00011";
when S_Mem =>
Reg2Loc <= '1';
ALUSRC <= '1';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '1';
wea <= '1';
PCWrite <= '0';
REGCEA <= '0';
LEDCode <= "00110";
--Additional State Outputs Here
when others =>
Reg2Loc <= '0';
ALUSRC <= '0';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '0';
REGCEA <= '0';
LEDCode <= "00000";
end case;
end process output_logic;
end Behavioral;
Datapath:
entity Datapath is
Port (BTNClock : in STD_LOGIC;
clock : in STD_LOGIC;
UncondBranch : in STD_LOGIC;
CondBranch : in STD_LOGIC;
RRtwoSelect : in STD_LOGIC;
RegWriteSelect : in STD_LOGIC;
ALUSource : in STD_LOGIC;
ALUOpCode : in STD_LOGIC_VECTOR(1 downto 0);
WriteSelect : in STD_LOGIC;
MemWrite : in STD_LOGIC;
REGCEA : in STD_LOGIC;
PCWrite : in STD_LOGIC;
seg_select : out STD_LOGIC_vector(6 downto 0);
anode_select : out STD_LOGIC_vector(7 downto 0);
ins_out : out STD_LOGIC_VECTOR(31 downto 0);
RAMSelect : in STD_LOGIC;
ALUEleven : out STD_LOGIC;
REGEleven : out STD_LOGIC;
SwitchReset : in STD_LOGIC);
end Datapath;
architecture Behavioral of Datapath is
signal PC : STD_LOGIC_VECTOR(9 downto 0);
signal instruction : STD_LOGIC_VECTOR(31 downto 0);
signal BranchSelect : STD_LOGIC;
signal ZeroBranch : STD_LOGIC;
signal RRtwo : STD_LOGIC_VECTOR(4 downto 0);
signal RegDataOut1 : STD_LOGIC_VECTOR(63 downto 0);
signal RegDataOut2 : STD_LOGIC_VECTOR(63 downto 0);
signal ALUMuxOut : STD_LOGIC_VECTOR(63 downto 0);
signal SignExtendOut : STD_LOGIC_VECTOR(63 downto 0);
signal BranchExtend : STD_LOGIC_VECTOR(9 downto 0);
signal ALUOut : STD_LOGIC_VECTOR(63 downto 0);
signal ALUZero : STD_LOGIC;
signal MemoryOut : STD_LOGIC_VECTOR(63 downto 0);
signal WriteMuxOut : STD_LOGIC_VECTOR(63 downto 0);
signal Branch : STD_LOGIC_VECTOR(9 downto 0);
signal PCNext : STD_LOGIC_VECTOR(9 downto 0);
signal PCIncrement : STD_LOGIC_VECTOR(9 downto 0);
signal ALUCommand : STD_LOGIC_VECTOR(3 downto 0);
signal InstEn : STD_LOGIC := '1';
signal OnlySeven : STD_LOGIC_VECTOR(0 downto 0);
signal SevSegReset : STD_LOGIC := '0';
begin
OnlySeven(0) <= MemWrite and not ALUOut(11);
BranchSelect <= UncondBranch or ZeroBranch;
ZeroBranch <= CondBranch and ALUZero;
ins_out <= instruction;
ALUEleven <= ALUout(11);
REGEleven <= RegDataOut1(11);
--Program Counter
PCReg : PCounter port map ( clk => BTNClock,
wea => PCWrite,
newaddress => PCNext,
thisaddress => PC);
--Incremental adder
IncAddr : B_adder port map ( a => PC,
x => PCIncrement);
--Branch Adder
BranchAddr : In_adder port map ( a => PC,
b => BranchExtend,
x => Branch);
--Next Instruction Address Mux
NextPCMux : nine_mux port map ( s => BranchSelect,
in1 => PCIncrement,
in2 => Branch,
output => PCNext);
--Additional Datapath Elements Here
end Behavioral;
Program Counter:
entity PCounter is
Port ( clk : in STD_LOGIC; --clock
wea : in STD_LOGIC; --write enable
newaddress : in STD_LOGIC_VECTOR (9 downto 0); --new address coming in
thisaddress : out STD_LOGIC_VECTOR (9 downto 0) --current address to be executed
);
end PCounter;
architecture Behavioral of PCounter is
signal reg: std_logic_vector(9 downto 0); --internal register storage
begin
process(clk) --nothing happens if this register isn't selected
begin
if clk'EVENT and clk = '1' then
thisaddress <= reg; --send out currently saved address
if wea = '1' then
reg <= newaddress; --and set register to next address
end if;
else
reg <= reg; --otherwise, maintain current value
end if;
end process;
end Behavioral;
This adder just adds one to the value currently in the PC:
entity B_adder is
Port ( a : in STD_LOGIC_VECTOR (9 downto 0);
x : out STD_LOGIC_VECTOR (9 downto 0));
end B_adder;
architecture Behavioral of B_adder is
begin
x <= a + 1;
end Behavioral;
This little mux will select if the next address is coming from the branch adder (not included here) or from the incremental adder above:
entity nine_mux is
Port ( s : in STD_LOGIC;
in1 : in STD_LOGIC_VECTOR (9 downto 0);
in2 : in STD_LOGIC_VECTOR (9 downto 0);
output : out STD_LOGIC_VECTOR (9 downto 0));
end nine_mux;
architecture Behavioral of nine_mux is
begin
with s select
output <= in1 when '0',
in2 when others;
end Behavioral;
And this is how the control unit is mapped to the datapath:
entity WholeThing is
Port ( BTNClock : in STD_LOGIC;
BTNReset : in STD_LOGIC;
SwitchReset : in STD_LOGIC;
clock : in STD_Logic;
LEDs : out STD_LOGIC_VECTOR(4 downto 0);
seg : out STD_LOGIC_vector(6 downto 0);
an : out STD_LOGIC_vector(7 downto 0);
alu11 : out STD_LOGIC;
reg11 : out STD_LOGIC
);
end WholeThing;
architecture Behavioral of WholeThing is
signal instruction : STD_LOGIC_VECTOR(31 downto 0);
signal Reg2Loc : STD_LOGIC;
signal ALUSRC : std_logic;
signal MemtoReg : std_logic;
signal RegWrite : std_logic;
signal Branch : std_logic;
signal ALUOp : std_logic_vector (1 downto 0);
signal UnconB : std_logic;
signal en : std_logic;
signal wea : std_logic;
signal PCWrite : std_logic;
signal REGCEA : std_logic;
signal SwRst : STD_LOGIC;
begin
--SwitchReset <= SwRst;
--Control Unit
CU : Fred port map ( Inst => instruction(31 downto 21),
clk => BTNClock,
rst => BTNReset,
Reg2Loc => Reg2Loc,
ALUSRC => ALUSRC,
MemtoReg => MemtoReg,
RegWrite =>RegWrite,
Branch => Branch,
ALUOp => ALUOp,
UnconB => UnconB,
en => en,
wea => wea,
PCWrite => PCWrite,
REGCEA => REGCEA,
LEDCode => LEDs);
--Datapath
DP : Datapath port map (BTNClock => BTNClock,
clock => clock,
UncondBranch => UnconB,
CondBranch => Branch,
RRtwoSelect => Reg2Loc,
RegWriteSelect => RegWrite,
ALUSource => ALUSRC,
ALUOpCode => ALUOp,
WriteSelect => MemtoReg,
MemWrite => wea,
REGCEA => REGCEA,
PCWrite => PCWrite,
seg_select => seg,
anode_select => an,
ins_out => instruction,
RAMSelect => en,
ALUEleven => alu11,
REGEleven => reg11,
SwitchReset => SwitchReset
);
end Behavioral;
The FSM - the main problem
Your second process should implement default assignments to spare lots of unnecessary else branches where you define self-edged of your FSM graph. Because you missed that, your FSM creates additional latches for signal current_state! Check your synthesis report for latch warning and you might find multiple of them.
Other mistakes in the same file
You mixed up current_state and next_state. The meaning of the signals does not
reflect your code! Your case statement needs to switch on current_state.
Don't use the 3-process pattern to describe an FSM. This is a nightmare of code
readability and maintenance! One one can read and verify the behavior of this FSM form.
You're using the attribute enum_encoding in a wrong way:
to define an FSM encoding, apply fsm_encoding to the state signal
to define a user-defined encoding apply fsm_encoding with value user to your state signal and apply enum_encoding with a space separated list of binary values to your state type.
Don't use asynchronous reset. Synchronous, clocked processes have only one signal in the sensitivity list!
Combinational processes need to list all read signals in there sensitivity list!
You shouldn't use clk'EVENT and clk = '1'. Use rising_edge(clk) instead.
If you switch on the same signal multiple times, use a case statement, but no if-elsif construct!
Your eyes and probably also your LEDs will not be fast enough to see and display LEDCode.
Corrected code:
architecture Behavioral of Fred is
attribute fsm_encoding : string;
type type_fstate is (
Fetch, L_S_D, L_S_E, L_Mem, S_Mem,
L_WB, R_I_D, I_E, R_E, I_WB, R_WB, B_E, CBZ_D, B_WB, CBZ_E,
CBZ_WB);
signal current_state : type_fstate := Fetch;
signal next_state : type_fstate;
attribute fsm_encoding of current_state : signal is "one-hot";
begin
clockprocess : process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
current_state <= Fetch;
else
current_state <= next_state;
end if;
end if;
end process;
state_logic: process (current_state, Inst)
begin
next_state <= current_state;
Reg2Loc <= '0';
ALUSRC <= '0';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '0';
REGCEA <= '0';
LEDCode <= "00000";
case current_state is
when Fetch => --00001
REGCEA <= '1';
LEDCode <= "00001";
case Inst is
when "11111000010" => --LDUR
next_state <= L_S_D;
when "11111000000" => --STUR
next_state <= L_S_D;
--Additional State Logic Here
when others =>
next_state <= Fetch;
end case;
when L_S_D => --00010
Reg2Loc <= '1';
LEDCode <= "00010";
next_state <= L_S_E;
when L_S_E => --00011
Reg2Loc <= '1';
ALUSRC <= '1';
PCWrite <= '1';
LEDCode <= "00011";
case Inst is
when "11111000010" =>
next_state <= L_Mem;
when "11111000000" =>
next_state <= S_Mem;
when others =>
-- ???
end case;
when S_Mem => --00110
Reg2Loc <= '1';
ALUSRC <= '1';
en <= '1';
wea <= '1';
LEDCode <= "00110";
next_state <= Fetch;
--Additional States Here
when others =>
next_state <= Fetch;
end case;
end process;
end architecture;
Mistakes in the PC:
Never assign something like this reg <= reg in VHDL!
You're using arithmetic on type std_logic_vector. This operation is:
not defined for that type, or
you're using a non IEEE package like synopsys.std_logic_unsigned, which shouldn't be used at all. Use package ieee.numeric_std and types signed/unsigned if you need arithmetic operations.
Your program counter (PC) does not count (yet?). Based on the single responsibility principle, your PC should be able to:
load a new instruction pointer
increment an instruction pointer
output the current instruction pointer
Your PC assigns the output thisaddress with one cycle of delay. Normally, this will break any CPU functionality ...
As you're going to implement your design on an FPGA device, make sure to initialize all signals that are translated to memory (e.g. registers) with appropriate init values.
Improved Code:
architecture Behavioral of PCounter is
signal reg: unsigned(9 downto 0) := (others => '0');
begin
process(clk)
begin
if rising_edge(clk) then
if wea = '1' then
reg <= unsigned(newaddress);
end if;
end if;
end process;
thisaddress <= reg;
end architecture;
Your adder B_adder
Is is wise to implement a one-line in an entity consuming 9 lines of code?
Moreover, your code is describing an incrementer, but not an adder.
Describing a Multiplexer
A Multiplexer is not described with a with ... select statement. This will create a priority logic like a chain of if-elseif branches.
output <= in1 when (s = '0') else in2;
As this is now a size independent one-liner, screw the nine_mux entity.
Related
State machine and unsigned signal
I have a few problems with a fairly simple state machine I made. No matter what I do, the signal startS1, startS2, enS and mS always stays unsigned in simulation even when I hit the reset button and I can't figure out why. There's a component in the mix, but I did test the component and it works perfectly. I hope you can help me! library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity machine_etat is generic (N_bit : integer := 8); Port ( LOAD : in STD_LOGIC_VECTOR (N_bit-1 downto 0); RESET : in STD_LOGIC; START : in STD_LOGIC; CLK : in STD_LOGIC; OUTPUT : out STD_LOGIC_VECTOR (N_bit-1 downto 0)); end machine_etat; architecture Behavioral of machine_etat is TYPE machine is (IddleT, DepartT, LoadT, ShiftT, EndT); SIGNAL Etat1, Etat2 : machine:= IddleT; SIGNAL mS: STD_LOGIC_VECTOR (1 downto 0); SIGNAL enS : STD_LOGIC; SIGNAL outputS : STD_LOGIC_VECTOR (N_bit-1 downto 0); component Reg_decal is generic (N_bit : integer := N_bit); Port ( CLK : in STD_LOGIC; RESET : in STD_LOGIC; EN : in STD_LOGIC; M : in STD_LOGIC_VECTOR (1 downto 0); LOAD : in STD_LOGIC_VECTOR (N_bit-1 downto 0); OUTPUT : out STD_LOGIC_VECTOR (N_bit-1 downto 0)); end component; SIGNAL startS1, startS2 : STD_LOGIC; begin OUTPUT <= outputS; Reg_dec: Reg_decal generic map (N_bit => N_bit) port map (CLK => CLK, RESET => RESET, EN => enS, M => mS, LOAD => LOAD, OUTPUT => outputS); Machine1: process (CLK) begin if RESET = '1' then enS <= '0'; mS <= "00"; startS1 <= '0'; startS2 <= '0'; Etat1 <= IddleT; elsif rising_edge(CLK) then CASE Etat1 is WHEN IddleT => if startS1 = '1' OR START = '1' then Etat1 <= DepartT; else Etat1 <= IddleT; end if; WHEN DepartT => Etat1 <= LoadT; startS1 <= '0'; WHEN LoadT => mS <= "11"; enS <= '1'; Etat1 <= ShiftT; WHEN ShiftT => mS <= "00"; Etat1 <= EndT; WHEN EndT => enS <= '0'; startS2 <= '1'; Etat1 <= IddleT; WHEN Others => Etat1 <= IddleT; end CASE; end if; end process; Machine2: process (CLK) begin if RESET = '1' then Etat2 <= IddleT; elsif rising_edge(CLK) then CASE Etat2 is WHEN IddleT => if startS2 = '1' then Etat2 <= DepartT; else Etat2 <= IddleT; end if; WHEN DepartT => startS2 <= '0'; Etat2 <= LoadT; WHEN LoadT => enS <= '1'; Etat2 <= ShiftT; WHEN ShiftT => mS <= "01"; Etat2 <= EndT; WHEN EndT => Etat2 <= IddleT; startS1 <= '1'; WHEN Others => end CASE; end if; end process; end Behavioral;
Add RESET to your process sensitivity list.
VHDL - My code is synthesizable and works the way i want on simulation, but it doesn't on the fpga
My VHDL-Code is functionaly correct, in simulation it does what it's thought for. I tested in many variations and the code works correct. But when i program the fpga (Nexyx 4 ddr) everything works well except the preload of the counter. I don't know if the load enable (load_e) output from the fsm doesn't reach the counter or if the output signal that sais the counter is loaded (counter_loaded) doesn't reach the fsm but when i program the fpga it never pases from state C or D (waiting for counter loaded) to state E or F (where it makes a countdown). I tested the other parts of the code in the target and it works properly, so the only problema so far is that one and i can't find the error, i'm thinking about timming, but i have no idea of how to solve it. I leave here the counter and fsm code, as well as the TOP code, i`m new in VHDL and it might be lots of bad practice mistakes. I'm spanish, that's the reason of my bad English and also the spanish name of some signal, but i add a comment next to them. --------COUNTER--------------------------------------- entity counter is Generic (NBITS : positive := 15 ); Port (clk : in STD_LOGIC; rst : in STD_LOGIC; ce : in STD_LOGIC; load : in STD_LOGIC_VECTOR (NBITS-1 downto 0); load_e : in STD_LOGIC; unit : out STD_LOGIC_VECTOR(3 downto 0); dec : out STD_LOGIC_VECTOR(3 downto 0); zero_n : out STD_LOGIC; --true si cuenta = 0 loaded : out STD_LOGIC); end counter; architecture Behavioral of counter is signal q_i : unsigned (NBITS-1 downto 0) := (others => '1'); begin process(clk,rst) begin if rst = '1' then q_i <= (OTHERS => '1'); loaded <= '0'; elsif rising_edge(clk) then if CE = '1' then if load_e = '1' then --ONE OF MY GUESSES OF THE PROBLEM q_i <= unsigned(load); loaded <= '1'; else q_i <= q_i - 1; loaded <= '0'; end if; end if; end if; end process; dec <= std_logic_vector(to_unsigned((to_integer(q_i(14 downto 10)) / 10),dec'length)); --first 5 bits are the tens unit <= std_logic_vector(to_unsigned((to_integer(q_i(14 downto 10)) rem 10),unit'length)); --fist 5 bits are the unit zero_n <= '1' WHEN q_i < "000010000000000" ELSE '0'; --cout is zero if the first 5 bits are less tan 1 in binary end Behavioral; ------FINITE STATE MACHINE-------------------------------- entity maquina_estados is Port ( clk : in STD_LOGIC; rst : in STD_LOGIC; corto : in STD_LOGIC; largo : in STD_LOGIC; b_on : in STD_LOGIC; zero_n : in STD_LOGIC; counter_loaded : in STD_LOGIC; load_e : out STD_LOGIC; load : out STD_LOGIC_VECTOR(14 downto 0); bomba_led : out STD_LOGIC; indica_on : out STD_LOGIC); end maquina_estados; architecture Behavioral of maquina_estados is type state_type is (A, B, C, D, E, F); --define state(A = powered off, B = powered on, C = short coffee preload, D = large coffee preload, E = short coffee, F = large coffee) signal state, next_state : state_type; --type state signal begin process(clk,rst) begin if rst = '1' then state <= A; elsif rising_edge(clk) then state <= next_state; end if; end process; process(state, b_on, corto, largo, zero_n, counter_loaded) begin CASE state IS WHEN A => if b_on = '1' then next_state <= B; else next_state <= A; end if; WHEN B => if b_on = '0' then next_state <= A; elsif corto = '1' then next_state <= C; elsif largo = '1' then next_state <= D; else next_state <= B; end if; WHEN C => if counter_loaded = '1' then next_state <= E; else next_state <= C; end if; WHEN D => if counter_loaded = '1' then next_state <= F; else next_state <= D; end if; WHEN E => if zero_n = '1' then next_state <= B; else next_state <= E; end if; WHEN F => if zero_n = '1' then next_state <= B; else next_state <= F; end if; WHEN OTHERS => next_state <= A; end case; end process; process(state) begin CASE state IS WHEN A => load <= "111111111111111"; --default value of the count load_e <= '0'; bomba_led <= '0'; indica_on <= '0'; WHEN B => load <= "111111111111111"; load_e <= '0'; bomba_led <= '0'; indica_on <= '1'; WHEN C => load <= "010101111111111"; --10 second, this in addition to a 1024 hz clock made posible to use the first 5 bits as the number load_e <= '1'; bomba_led <= '0'; indica_on <= '1'; WHEN D => load <= "101001111111111"; --20 seconds load_e <= '1'; bomba_led <= '0'; indica_on <= '1'; WHEN E => load <= "111111111111111"; load_e <= '0'; bomba_led <= '1'; indica_on <= '1'; WHEN F => load <= "111111111111111"; load_e <= '0'; bomba_led <= '1'; indica_on <= '1'; end case; end process; end behavioral; ------TOP----------------------- entity TOP is Generic( FIN : positive := 100000000; FOUT : positive := 1024); Port ( clk : in STD_LOGIC; rst : in STD_LOGIC; corto : in STD_LOGIC; largo : in STD_LOGIC; b_on : in STD_LOGIC; display_number : out STD_LOGIC_VECTOR (6 downto 0); display_selection : out STD_LOGIC_VECTOR (7 downto 0); bomba_led : out STD_LOGIC; indica_on : out STD_LOGIC); end TOP; architecture Behavioral of TOP is --instancies component clk_divider is -- Port ( ); generic( FIN : positive; FOUT : positive ); port ( Clk : in STD_LOGIC; Reset : in STD_LOGIC; Clk_out : out STD_LOGIC ); end component; component maquina_estados is Port ( clk : in STD_LOGIC; rst : in STD_LOGIC; corto : in STD_LOGIC; largo : in STD_LOGIC; b_on : in STD_LOGIC; zero_n : in STD_LOGIC; counter_loaded : in STD_LOGIC; load_e : out STD_LOGIC; load : out STD_LOGIC_VECTOR(14 downto 0); bomba_led : out STD_LOGIC; indica_on : out STD_LOGIC); end component; component counter is Generic (NBITS : positive ); Port (clk : in STD_LOGIC; rst : in STD_LOGIC; ce : in STD_LOGIC; load : in STD_LOGIC_VECTOR (NBITS-1 downto 0); load_e : in STD_LOGIC; unit : out STD_LOGIC_VECTOR(3 downto 0); dec : out STD_LOGIC_VECTOR(3 downto 0); zero_n : out STD_LOGIC; loaded : out STD_LOGIC); end component; component clk_manager is generic( CLK_FREQ : positive ); Port ( clk : in STD_LOGIC; rst : in STD_LOGIC; strobe_1024Hz : out STD_LOGIC; strobe_128Hz : out STD_LOGIC ); end component; component decoder is Port ( code : in STD_LOGIC_VECTOR(3 downto 0); led : out STD_LOGIC_vector(6 downto 0) ); end component; component display_refresh is Port ( clk : in STD_LOGIC; ce : in STD_LOGIC; segment_unit : in STD_LOGIC_VECTOR (6 downto 0); segment_dec : in STD_LOGIC_VECTOR (6 downto 0); display_number : out STD_LOGIC_VECTOR (6 downto 0); display_selection : out STD_LOGIC_VECTOR (1 downto 0)); --cada elemento del vector corresponde a un 7 seg, true se ve false no end component; -- prescaler signals signal prescaler_clk_out : STD_LOGIC; --maquina estados signals signal zero_n_fsm : STD_LOGIC; signal load_e_fsm : STD_LOGIC; signal load_fsm : STD_LOGIC_VECTOR(14 downto 0); signal bomba_led_fsm: STD_LOGIC; --counter signals signal unit : STD_LOGIC_VECTOR(3 downto 0); signal dec : STD_LOGIC_VECTOR(3 downto 0); signal zero_n_cntr : STD_LOGIC; signal load_e_cntr : STD_LOGIC; signal load_cntr : STD_LOGIC_VECTOR(14 downto 0); signal counter_loaded : STD_LOGIC; --clk_manager signals signal strobe_1024Hz : STD_LOGIC; signal strobe_128Hz : STD_LOGIC; signal ce_clkm : STD_LOGIC; signal rst_clkm : STD_LOGIC; --decoders signals signal unit_code : STD_LOGIC_VECTOR(6 downto 0); signal dec_code : STD_LOGIC_VECTOR(6 downto 0); --display refresh signals signal display_refresh_number : STD_LOGIC_VECTOR(6 downto 0); signal display_refresh_selection : STD_LOGIC_VECTOR(1 downto 0); begin prescaler: clk_divider generic map( FIN => FIN, FOUT => FOUT ) port map( Clk => clk, Reset => rst, Clk_out => prescaler_clk_out ); sm: maquina_estados Port map( clk => prescaler_clk_out, rst => rst, corto => corto, largo => largo, b_on => b_on, zero_n => zero_n_fsm, counter_loaded => counter_loaded, load_e => load_e_fsm, load => load_fsm, bomba_led => bomba_led_fsm, indica_on => indica_on); cntr: counter Generic map(NBITS => 15 ) Port map(clk => clk, rst => rst, ce => strobe_1024Hz, load => load_cntr, load_e => load_e_fsm, unit => unit, dec => dec, zero_n => zero_n_cntr, loaded => counter_loaded); clk_m: clk_manager generic map( CLK_FREQ => FIN ) Port map( clk => clk, rst => rst, strobe_1024Hz => strobe_1024Hz, strobe_128Hz => strobe_128Hz ); unit_dcd: decoder Port map( code => unit, led => unit_code ); dec_dcd: decoder Port map( code => dec, led => dec_code ); dr: display_refresh Port map( clk => clk, ce => strobe_128Hz, segment_unit => unit_code, segment_dec => dec_code, display_number => display_refresh_number, display_selection => display_refresh_selection); display_number <= display_refresh_number WHEN bomba_led_fsm = '1' ELSE "1111111"; display_selection <= ("111111" & display_refresh_selection) WHEN bomba_led_fsm = '1' ELSE "11111111"; zero_n_fsm <= zero_n_cntr; bomba_led <= bomba_led_fsm; load_cntr <= load_fsm; end Behavioral; Here are all the reports that the implementation ans sythesis gave me: Synthesis reports implementation reports 1/6 implementation reports 2/6 implementation reports 3/6 implementation reports 4/6 implementation reports 5/6 implementation reports 6/6 I hope someone could find the problema and give me a solution or a way of how to debug this problem. Thanks.
Your FSM is clocked on prescaler_clk_out, and your counter is clocked on clk, which is a red flag. This could easily lead to an implementation failure. Draw a timing diagram showing all your clocks and resets, and your lower-frequency enables (in particular, strobe_1024Hz) Try to clock all the logic on the same clock, presumably clk, and make sure that everything is synchronous to this clock (in other words, inputs have sufficient setup and hold times relative to this clock) Make sure you are actually resetting the chip Once you've done the timing diagram, write a constraints file that tells the synthesiser what your clocks are. clk_manager and clk_divider may be an issue here, but hopefully everything will be clocked on just 'clk', and the contstraints file will contain only the clock name and frequency. If you still can't get it to work, ask a new question, showing your timing diagram, and your attempt at a constraints file.
counter not incrementing for RAM with built-in counter
I am new to vhdl and trying create a RAM in which I first write data then I read that data. The task is supposed to be created using a FSM. I have created the behavioral code as follows along with its test bench but the counters are not incrementing and I dont get it. library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity sorting is port ( clk : in std_logic; en : in std_logic; data_in : in std_logic_vector(23 downto 0); data_out : out std_logic_vector(23 downto 0)); end entity; architecture bhv of sorting is type internal_ram is array(1 downto 0) of std_logic_vector(23 downto 0); signal int_ram_in : internal_ram; signal int_ram_out : internal_ram; type state_type is (s0, s1, s2); --stages is fsm signal state, nxt_state : state_type; signal cntr_in : integer range 0 to 3;--unsigned(1 downto 0); --read counter signal cntr_out : integer range 0 to 3;-- unsigned(1 downto 0); --write counter begin -- fsm_loop : process(clk) -- begin -- if rising_edge(clk) then -- if (en = '1') then -- state <= s0; -- else -- state <= nxt_state; -- end if; -- end if; -- end process; comp_loop : process(clk, state, en, data_in) begin if rising_edge(clk) then case(state) is when s0 => if (en = '1') then cntr_in <= 0; cntr_out<= 0; else nxt_state <= s1; end if; when s1 => --writing in internal_ram if (cntr_in = 3) then cntr_in <= 0;--(others => '0'); nxt_state <= s2; else cntr_in <= cntr_in + 1; int_ram_in(cntr_in) <= data_in; end if; when s2 => --using data_in if (cntr_out = 3) then cntr_out <= 0;--(others => '0'); nxt_state<= s0; else cntr_out <= cntr_out + 1; data_out <= int_ram_in(cntr_out); end if; end case; end if; end process; end bhv; The test bench used is: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity sorting_tb is end entity sorting_tb; architecture tb of sorting_tb is component sorting port ( clk : in std_logic; en : in std_logic; data_in : in std_logic_vector(23 downto 0); data_out : out std_logic_vector(23 downto 0) ); end component; signal clk : std_logic := '0'; signal en : std_logic := '1'; signal data_in : std_logic_vector(23 downto 0); signal data_out : std_logic_vector(23 downto 0); begin mapping: sorting port map( clk => clk, en => en, data_in => data_in, data_out => data_out); clock: process begin clk <= '1'; wait for 10 ns;--50MHz clk clk <= '0'; wait for 10 ns; end process; stimuli: process begin --1st run wait for 10ns; en <= '0'; data_in <= "111100001111000011110000"; wait for 20ns; data_in <= "111100001111000011110001"; wait for 20ns; data_in <= "111100001111000011110010"; wait for 20ns; data_in <= "111100001111000011110011"; -- en <= '1'; wait for 200ns; en <= '1'; --2nd run wait for 20ns; en <= '0'; data_in <= "001100001111000011110000"; wait for 20ns; data_in <= "011100001111000011110001"; wait for 20ns; data_in <= "101100001111000011110010"; wait for 20ns; data_in <= "111100001111000011110011"; -- en <= '1'; wait for 200ns; en <= '1'; end process; end tb; And the simulation that I get is this:
issue with inout parameter in procedure
I am writing a bus functional model for a testbench, I am using a procedure to handle the read and write operations, ideally i would like to use one bus declared as an inout. I am using a record type to instantiate my bus, but when i declare it as an inout parameter in my procedure call it appears to work for signals that are outputs from the procedure, but does not recognize inputs into the procedure. Any signal inputs are uninitialized "U". I know for synthesis this method does not work, but for a testbench i thought it was possible to instantiate a bus as an inout. My record type and procedure are instantiated as follows: type t_apbp_intf is record -- APB-pipe Interface paddr : std_logic_vector(31 downto 0); psel : std_logic; penable : std_logic; pwrite : std_logic; pwdata : std_logic_vector(31 downto 0); pstrb : std_logic_vector(3 downto 0); prdata : std_logic_vector(31 downto 0); pready : std_logic; pslverr : std_logic; prdvld : std_logic; end record t_apbp_intf; procedure nai_bus_cyc( wr_rd_n : in std_logic; addr_in : in std_logic_vector(31 downto 0); -- Address data_in : in std_logic_vector(31 downto 0); -- Data to be written signal tb_m_apbp : inout t_apbp_intf) is begin if wr_rd_n = C_BUS_WR then wait until rising_edge(tb_clk); tb_m_apbp.paddr <= addr_in; tb_m_apbp.psel <= '1'; tb_m_apbp.penable <= '1'; tb_m_apbp.pwrite <= '1'; tb_m_apbp.pwdata <= data_in; tb_m_apbp.pstrb <= "1111"; wait until rising_edge(tb_clk) and (tb_m_apbp.pready = '1'); tb_m_apbp.paddr <= (others => '0'); tb_m_apbp.psel <= '0'; tb_m_apbp.penable <= '0'; tb_m_apbp.pwrite <= '0'; tb_m_apbp.pwdata <= (others => '0'); tb_m_apbp.pstrb <= "0000"; else wait until rising_edge(tb_clk); tb_m_apbp.paddr <= addr_in; tb_m_apbp.psel <= '1'; tb_m_apbp.penable <= '1'; tb_m_apbp.pwrite <= '0'; tb_m_apbp.pwdata <= (others => '0'); tb_m_apbp.pstrb <= "0000"; wait until rising_edge(tb_clk) and (tb_sprvalid_bus = '1'); tb_m_apbp.paddr <= (others => '0'); tb_m_apbp.psel <= '0'; tb_m_apbp.penable <= '0'; tb_m_apbp.pwrite <= '0'; tb_m_apbp.pwdata <= (others => '0'); tb_m_apbp.pstrb <= "0000"; end if; end procedure;
State_Machine VHDL Code, can you please check why it doesn't work ! it synthesises ok
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.