counter not incrementing for RAM with built-in counter - vhdl

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:

Related

Unable to output data entered into a register

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;

VHDL Parametric Division Circuit - Book: FPGA Prototyping by VHDL Examples, Pong Chu

I'm trying to follow an example on my VHDL book. Its name is FPGA Prototyping by VHDL Examples, Pong Chu. It has a Divider Circuit example in Chapter 6, Listing 5. I understood the general idea of a division operation. To verify the module I wrote a testbench and I saw that it doesn't work properly. If anyone could explain to me where the problem is, I would be very appreciated.
Here are the codes of module and testbench.
Module:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Divider is
generic(W: integer := 8;
CBIT: integer := 4 );
Port ( clk, reset : in STD_LOGIC;
start : in STD_LOGIC;
dvsr, dvnd : in STD_LOGIC_VECTOR (W-1 downto 0);
ready, done_tick : out STD_LOGIC;
quo, rmd : out STD_LOGIC_VECTOR (W-1 downto 0));
end Divider;
architecture Behavioral of Divider is
type state_type is (idle, op, last, done);
signal state_reg, state_next: state_type;
signal rh_reg, rh_next: UNSIGNED(W-1 downto 0) := (others => '0');
signal rl_reg, rl_next: STD_LOGIC_VECTOR(W-1 downto 0) := (others => '0');
signal rh_temp: UNSIGNED(W-1 downto 0) := (others => '0');
signal d_reg, d_next: UNSIGNED(W-1 downto 0) := (others => '0');
signal n_reg, n_next: UNSIGNED(CBIT-1 downto 0) := (others => '0');
signal q_bit: STD_LOGIC;
begin
-- FSMD State and Data Registers
process(clk, reset)
begin
if reset = '1' then
state_reg <= idle;
rh_reg <= (others => '0');
rl_reg <= (others => '0');
d_reg <= (others => '0');
n_reg <= (others => '0');
elsif rising_edge(clk) then
state_reg <= state_next;
rh_reg <= rh_next;
rl_reg <= rl_next;
d_reg <= d_next;
n_reg <= n_next;
end if;
end process;
-- FSMD Next-State Logic and Data Path Logic
process(state_reg, n_reg, rh_reg, rl_reg, d_reg, start, dvsr, dvnd, q_bit, rh_temp, n_next)
begin
ready <= '0';
done_tick <= '0';
state_next <= state_reg;
rh_next <= rh_reg;
rl_next <= rl_reg;
d_next <= d_reg;
n_next <= n_reg;
case state_reg is
when idle =>
ready <= '1';
if start = '1' then
rh_next <= (others => '0');
rl_next <= dvnd; -- Dividend
d_next <= UNSIGNED(dvsr); -- Divisor
n_next <= TO_UNSIGNED(W+1, CBIT); -- Index
state_next <= op;
end if;
when op =>
--Shift rh and rl left
rl_next <= rl_reg(W-2 downto 0) & q_bit;
rh_next <= rh_temp(W-2 downto 0) & rl_reg(W-1);
--Decrease index
n_next <= n_reg - 1;
if(n_next = 1) then
state_next <= last;
end if;
when last =>
rl_next <= rl_reg(W-2 downto 0) & q_bit;
rh_next <= rh_temp;
state_next <= done;
when done =>
state_next <= idle;
done_tick <= '1';
end case;
end process;
-- Compare and Subtract
process(rh_reg, d_reg)
begin
if rh_reg <= d_reg then
rh_temp <= rh_Reg - d_reg;
q_bit <= '1';
else
rh_temp <= rh_reg;
q_bit <= '0';
end if;
end process;
-- Output
quo <= rl_reg;
rmd <= STD_LOGIC_VECTOR(rh_reg);
end Behavioral;
Testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity tb_Divider is
-- Port ( );
end tb_Divider;
architecture Behavioral of tb_Divider is
signal clk, reset, start, ready, done: STD_LOGIC;
signal dvsr, dvnd: STD_LOGIC_VECTOR(7 downto 0);
signal quo, rmd: STD_LOGIC_VECTOR(7 downto 0);
component Divider is
port( clk, reset : in STD_LOGIC;
start : in STD_LOGIC;
dvsr, dvnd : in STD_LOGIC_VECTOR (7 downto 0);
ready, done_tick : out STD_LOGIC;
quo, rmd : out STD_LOGIC_VECTOR (7 downto 0));
end component Divider;
begin
UUT: Divider port map( clk => clk, reset => reset, start => start, dvsr => dvsr, dvnd => dvnd,
ready => ready, done_tick => done, quo => quo, rmd => rmd);
process
begin
clk <= '0';
wait for 10 ns;
clk <= '1';
wait for 10 ns;
end process;
process
begin
start <= '0';
dvnd <= x"00";
dvsr <= x"00";
wait for 100 ns;
start <= '1';
dvnd <= x"C8";
dvsr <= x"0A";
wait for 10 us;
end process;
end Behavioral;
Result of Testbench:

VHDL State Machine Problems - Repeats States

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.

Modelsim Altera VHDL MEMORY ROM

I am confused on to why my VHDL design is not working. I am to create a top.vhd file that will program an FPGA board to display addresses 0 through 15 and the corresponding values to each address. When I simulate my design, all the clocks and resets work. The problem I am having is my FSM processes and Address process. I know there is a lot going on here, so if you need clarification I can answer your questions.
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.all;
entity top is
port(Clock : in std_logic;
Reset : in std_logic;
SW : in std_logic_vector (1 downto 0);
HEX2, HEX4: out std_logic_vector ( 6 downto 0);
KEY0: in std_logic);
end entity;
architecture top_arch of top is
component char_decoder is
port(BIN_IN : in std_logic_vector (3 downto 0);
HEX_OUT : out std_logic_vector (6 downto 0));
end component;
component rom_16x4_sync is
port (clock: in std_logic;
address: in std_logic_vector (3 downto 0);
rom_en: in std_logic;
data_out: out std_logic_vector(3 downto 0));
end component;
type state_type is (start, read_rom, clear_addr, done);
signal current_state, next_state : state_type;
signal Rom_en, addr_count_clr, addr_count_en : std_logic;
signal address_counter : integer range 0 to 15;
signal address_uns : unsigned (3 downto 0);
signal clock_slow : std_logic;
signal rom_out : std_logic_vector (3 downto 0);
begin
char : char_decoder port map (BIN_IN => rom_out, HEX_OUT => HEX2);
char1 : char_decoder port map (BIN_IN => std_logic_vector(address_uns), HEX_OUT => HEX4);
clock_slow <= Clock;
rom : rom_16x4_sync port map (clock => clock_slow, address => std_logic_vector(address_uns), rom_en => Rom_en, data_out => rom_out);
State_Memory : process (clock_slow, Reset)
begin
if (Reset = '0') then
current_state <= start;
elsif (clock_slow'event and clock_slow = '1') then
current_state <= next_state;
end if;
end process;
NEXT_STATE_LOGIC : process (current_state)
begin
case (current_state) is
when start => if (KEY0 = '0') then
next_state <= read_rom;
else next_state <= start;
end if;
when read_rom => if (address_counter = 15) then
next_state <= clear_addr;
else
address_counter <= address_counter + 1;
end if;
when clear_addr => next_state <= done;
address_counter <= 0;
when done => next_state <= done;
end case;
end process;
OUTPUT_LOGIC : process (current_state)
begin
case (current_state) is
when start => Rom_en <= '0';
addr_count_en <= '0';
addr_count_clr <= '0';
when read_rom => Rom_en <= '1';
addr_count_en <= '1';
addr_count_clr <= '0';
when clear_addr => Rom_en <= '0';
addr_count_en <= '1';
addr_count_clr <= '1';
when done => Rom_en <= '0';
addr_count_en <= '0';
addr_count_clr <= '0';
end case;
end process;
Address_Count : process (addr_count_en, addr_count_clr, clock_slow)
begin
if (clock_slow'event and clock_slow = '1') then
if (addr_count_en = '1') then
if (addr_count_clr = '1') then
address_uns <= "0000";
else
address_uns <= address_uns + 1;
end if;
end if;
end if;
end process;
address_uns <= to_unsigned(address_counter,4);
end architecture;
I commented on what I could see wrong with your code:
address_counter isn't clocked and is redundant. Remove the assignments and change the comparison to address_uns (which should also go into the sensitivity list) in process NEXT_STATE_LOGIC. Remove the concurrent signal assignment to address_uns following process Address_Counter. If processes Address_Count and OUTPUT_LOGIC are correct as well as rom_16x4_sync you should have something that works.
Well I had most the bits and pieces sitting around from other questions to gen a complete MCVE together with little effort mostly by copying and pasting and that gave:
As you can see that didn't work, and the reason why is that address_uns needs to be reset (it's default value is all 'U's).
Adding a reset gives:
So the gist of this is that your state machine was almost correct, it was missing the address counter in it's sensitivity list and had two address counters. Limiting that to one and resetting it so you weren't adding 1 to all 'U's shows your state machine is working.
And the code with all the fixes:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity char_decoder is
port (
bin_in: in std_logic_vector (3 downto 0);
hex_out: out std_logic_vector (6 downto 0)
);
end entity;
architecture dummy of char_decoder is
-- seven segment display
--
-- a
-- f b
-- g
-- e c
-- d
--
-- SEGMENT is defined (g downto a)
--
type segment7 is array (integer range 0 to 15) of
std_logic_vector (6 downto 0);
constant hex_to_segment: segment7 := (
"1000000", -- 0
"1111001", -- 1
"0100100", -- 2
"0110000", -- 3
"0011001", -- 4
"0010010", -- 5
"0000010", -- 6
"1111000", -- 7
"0000000", -- 8
"0011000", -- 9
"0001000", -- A
"0000011", -- b
"0111001", -- C
"0100001", -- d
"0000110", -- E
"0001110" -- F
);
begin
process (bin_in)
variable seg7_val: integer range 0 to 15;
begin
seg7_val := to_integer(unsigned(bin_in));
hex_out <= hex_to_segment(seg7_val);
end process;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity rom_16x4_sync is
port (
clock: in std_logic;
address: in std_logic_vector (3 downto 0);
rom_en: in std_logic;
data_out: out std_logic_vector(3 downto 0)
);
end entity;
architecture dummy of rom_16x4_sync is
type rom_array is array (0 to 15) of std_logic_vector(3 downto 0);
function fill_rom return rom_array is
variable ret_val: rom_array;
begin
for i in rom_array'reverse_range loop -- backward to i
ret_val(i) := std_logic_vector(to_unsigned(i,4));
end loop;
return ret_val;
end function;
constant rom: rom_array := fill_rom;
begin
process (clock)
begin
if rising_edge(clock) and rom_en = '1' then -- NO RESET
data_out <= rom(to_integer(unsigned(address)));
end if;
end process;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity top is
port (
clock: in std_logic;
reset: in std_logic;
sw: in std_logic_vector (1 downto 0); -- not used?
hex2, hex4: out std_logic_vector ( 6 downto 0);
key0: in std_logic
);
end entity;
architecture top_arch of top is
component char_decoder is
port (
bin_in: in std_logic_vector (3 downto 0);
hex_out: out std_logic_vector (6 downto 0)
);
end component;
component rom_16x4_sync is
port (
clock: in std_logic;
address: in std_logic_vector (3 downto 0);
rom_en: in std_logic;
data_out: out std_logic_vector(3 downto 0)
);
end component;
type state_type is (start, read_rom, clear_addr, done);
signal current_state,
next_state: state_type;
signal rom_en,
addr_count_clr,
addr_count_en: std_logic;
-- signal address_counter: integer range 0 to 15;
signal address_uns: unsigned (3 downto 0);
signal clock_slow: std_logic;
signal rom_out: std_logic_vector (3 downto 0);
begin
char:
char_decoder
port map (
bin_in => rom_out,
hex_out => hex2
);
char1:
char_decoder
port map (
bin_in => std_logic_vector(address_uns),
hex_out => hex4
);
clock_slow <= clock;
rom:
rom_16x4_sync
port map (
clock => clock_slow,
address => std_logic_vector(address_uns),
rom_en => rom_en, data_out => rom_out
);
state_memory:
process (clock_slow, reset)
begin
if reset = '0' then
current_state <= start;
elsif clock_slow'event and clock_slow = '1' then
current_state <= next_state;
end if;
end process;
next_state_logic:
-- process (current_state)
process (current_state, address_uns)
begin
case (current_state) is
when start =>
if key0 = '0' then
next_state <= read_rom;
else
next_state <= start;
end if;
when read_rom =>
if address_uns = 15 then
next_state <= clear_addr;
-- else
-- address_counter <= address_counter + 1;
end if;
when clear_addr => -- not a defined sequential logic inference
next_state <= done;
-- address_counter <= 0;
when done =>
next_state <= done;
end case;
end process;
output_logic:
process (current_state)
begin
case (current_state) is
when start =>
rom_en <= '0';
addr_count_en <= '0';
addr_count_clr <= '0';
when read_rom =>
rom_en <= '1';
addr_count_en <= '1';
addr_count_clr <= '0';
when clear_addr =>
rom_en <= '0';
addr_count_en <= '1';
addr_count_clr <= '1';
when done =>
rom_en <= '0';
addr_count_en <= '0';
addr_count_clr <= '0';
end case;
end process;
address_count:
process (addr_count_en, addr_count_clr, clock_slow)
begin
if reset = '0' then -- added reset
address_uns <= (others =>'0');
elsif clock_slow'event and clock_slow = '1' then
if addr_count_en = '1' then
if addr_count_clr = '1' then
address_uns <= "0000";
else
address_uns <= address_uns + 1;
end if;
end if;
end if;
end process;
-- address_uns <= to_unsigned(address_counter, 4);
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity top_tb is
end entity;
architecture foo of top_tb is
signal clock: std_logic := '0';
signal reset: std_logic := '1';
signal sw: std_logic_vector (1 downto 0) := "00";
signal hex2, hex4: std_logic_vector ( 6 downto 0);
signal key0: std_logic := '0';
begin
DUT:
entity work.top
port map (
clock => clock,
reset => reset,
sw => sw,
hex2 => hex2,
hex4 => hex4,
key0 => key0
);
CLK:
process
begin
wait for 5 ns;
clock <= not clock;
if now > 200 ns then
wait;
end if;
end process;
STIMULIS:
process
begin
wait for 1 ns;
reset <= '0';
wait for 10 ns;
reset <= '1';
wait for 10 ns;
wait;
end process;
end architecture;
The char_decoder I used should be fully functional. The ROM contents are simply dummied up.

When an output should go to 1, it goes to unknown

So for a school assignment we have to make a clock using different modules and I have an up-down counter and a finite state machine. I should be able to press a button so the counter goes up by one or down by one and this for the hours, minutes and seconds.
The problem is in the testbench of my fsm. When you add a number the up_down signal should go to 1 so the counter knows it has to count up, but when this happens the signal goes to unknown and when I want decrease it the signal goes back to 0 as it should.
I have looked for why it could do this but have no clue whatsoever, does anybody know why? I'll ad my code and a screenshot of the testbench.
a) The finite state machine
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity tijd_FSM is
Port ( clk_1ms : in std_logic;
BTU : in std_logic;
BTD : in STD_LOGIC;
BTR : in std_logic;
mo_tijd : in std_logic;
EupH : out std_logic;
EdownH : out std_logic;
EupM : out std_logic;
EdownM : out std_logic;
EupS : out std_logic;
EdownS : out std_logic;
up_down : out std_logic;
blink_tijd: out std_logic_vector (1 downto 0)
);
end tijd_FSM;
architecture Behavioral of tijd_FSM is
type state is (s0, s1, s2, s3);
signal present_state, next_state : state;
begin
state_reg: process (clk_1ms)
begin
if rising_edge(clk_1ms) then
if(BTR = '1' and mo_tijd = '1') then
present_state <= next_state;
else
present_state <= present_state;
end if;
end if;
end process;
--state machine process.
outputs: process (present_state, BTU, BTD)
begin
case present_state is
when s0 => --Gewone weergave
blink_tijd <= "00";
up_down <= '0';
when s1 => --Instellen UU
if(BTU ='1') then
up_down <= '1';
EupH <= '1';
elsif(BTD='1') then
up_down <= '0';
EdownH <= '1';
else
EupH <= '0';
EdownH <= '0';
end if;
blink_tijd <= "10";
when s2 => --Instellen MM
if(BTU ='1') then
up_down <= '1';
EupM <= '1';
elsif(BTD='1') then
up_down <= '0';
EdownM <= '1';
else
EupM <= '0';
EdownM <= '0';
end if;
blink_tijd <= "10";
when s3 => --Instellen SS
if(BTU ='1') then
up_down <= '1';
EupS <= '1';
elsif(BTD='1') then
up_down <= '0';
EdownS <= '1';
else
EupS <= '0';
EdownS <= '0';
end if;
blink_tijd <= "01";
when others => null;
end case;
end process;
nxt_state: process (BTR, present_state)
begin
case present_state is
when s0 =>
if BTR = '1' then next_state <= s1;
else next_state <= s0;
end if;
when s1 =>
if BTR = '1' then next_state <= s2;
else next_state <= s1;
end if;
when s2 =>
if BTR = '1' then next_state <= s3;
else next_state <= s2;
end if;
when s3 =>
if BTR = '1' then next_state <= s0;
else next_state <= s3;
end if;
when others => next_state <= s0;
end case;
end process;
end Behavioral;
b) The testbench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY tb_tijd_FSM IS
END tb_tijd_FSM;
ARCHITECTURE behavior OF tb_tijd_FSM IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT tijd_FSM
PORT(
clk_1ms : IN std_logic;
BTU : IN std_logic;
BTD : IN std_logic;
BTR : IN std_logic;
mo_tijd : IN std_logic;
EupH : OUT std_logic;
EdownH : OUT std_logic;
EupM : OUT std_logic;
EdownM : OUT std_logic;
EupS : OUT std_logic;
EdownS : OUT std_logic;
up_down : OUT std_logic;
blink_tijd : OUT std_logic_vector(1 downto 0)
);
END COMPONENT;
--Inputs
signal clk_1ms : std_logic := '0';
signal BTU : std_logic := '0';
signal BTD : std_logic := '0';
signal BTR : std_logic := '0';
signal mo_tijd : std_logic := '0';
--Outputs
signal EupH : std_logic;
signal EdownH : std_logic;
signal EupM : std_logic;
signal EdownM : std_logic;
signal EupS : std_logic;
signal EdownS : std_logic;
signal up_down : std_logic;
signal blink_tijd : std_logic_vector(1 downto 0);
-- Clock period definitions
constant clk_1ms_period : time := 1 ms;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: tijd_FSM PORT MAP (
clk_1ms => clk_1ms,
BTU => BTU,
BTD => BTD,
BTR => BTR,
mo_tijd => mo_tijd,
EupH => EupH,
EdownH => EdownH,
EupM => EupM,
EdownM => EdownM,
EupS => EupS,
EdownS => EdownS,
up_down => up_down,
blink_tijd => blink_tijd
);
-- Clock process definitions
clk_1ms_process :process
begin
clk_1ms <= '0';
wait for clk_1ms_period/2;
clk_1ms <= '1';
wait for clk_1ms_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
up_down <= '0';
mo_tijd <= '1';
--Hij begint in state s0
wait for 1 ms;
BTR <= '1'; --s1
wait for 1 ms;
BTR <= '0';
wait for 1 ms;
BTU <= '1';
wait for 1 ms;
BTU <= '0';
wait for 1 ms;
BTD <= '1';
wait for 1 ms;
BTD <= '0';
wait for 1 ms;
BTR <= '1'; --s2
wait for 1 ms;
BTR <= '0';
wait for 1 ms;
BTU <= '1';
wait for 1 ms;
BTU <= '0';
wait for 1 ms;
BTD <= '1';
wait for 1 ms;
BTD <= '0';
wait for 1 ms;
BTR <= '1'; -- s3
wait for 1 ms;
BTR <= '0';
wait for 1 ms;
BTU <= '1';
wait for 1 ms;
BTU <= '0';
wait for 1 ms;
BTD <= '1';
wait for 1 ms;
BTD <= '0';
wait;
end process;
END;
c) The waveform image
In stim_proc you have up_down <= '0', which drives 0 on the same signal that the output of your state machine is connected.
As long as the state machine also drives 0 everything is fine as the combination resolves to 0. When the state machine drives 1 however, the resolution is X, undefined.
As far as I can see, there is no reason for stim_proc to drive this signal, so removing that line should give you what you want.

Resources