commit 28638b6678ea5d28494b0178debf7927ca6dff46
parent d8c7f977087dfb32e0af2856c0eabe208bb7d705
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date: Fri, 17 Apr 2026 16:03:44 -0300
Add `tps/1/*`
Diffstat:
5 files changed, 246 insertions(+), 0 deletions(-)
diff --git a/tps/1/src/Makefile b/tps/1/src/Makefile
@@ -0,0 +1,24 @@
+GHDL = ghdl
+DEV_NAME = intersection_ctrl
+TOP = $(DEV_NAME)_tb
+TOP_SRC = $(TOP).vhd
+SRCS = rtc.vhd rtc_tb.vhd intersection_ctrl.vhd intersection_ctrl_tb.vhd
+WAVEFORM_FILE = $(TOP).vcd
+
+all: run
+
+analyze:
+ $(GHDL) -a $(SRCS)
+ $(GHDL) -a $(TOP_SRC)
+
+elaborate: analyze
+ $(GHDL) -e $(TOP)
+
+run: elaborate
+ $(GHDL) -r $(TOP) --vcd=$(WAVEFORM_FILE) --stop-time=100ms
+
+clean:
+ rm -f *.o *.cf $(TOP) $(TOP).vcd
+
+view: all
+ nohup surfer $(WAVEFORM_FILE) >/dev/null 2>&1 &
diff --git a/tps/1/src/intersection_ctrl.vhd b/tps/1/src/intersection_ctrl.vhd
@@ -0,0 +1,113 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity intersection_ctrl is
+
+ generic(clk_freq : integer := 1e6); -- default 1 MHz clock frequency
+ port(
+ clk : in std_logic;
+ rst : in std_logic;
+
+ red_1 : out std_logic := '1';
+ yel_1 : out std_logic := '0';
+ gre_1 : out std_logic := '0';
+ red_2 : out std_logic := '0';
+ yel_2 : out std_logic := '0';
+ gre_2 : out std_logic := '1');
+
+end entity;
+
+architecture intersection_ctrl_arq of intersection_ctrl is
+
+ constant RED_TIME_MS : integer := 30e3;
+ constant YEL_TIME_MS : integer := 3e3;
+ constant GRE_TIME_MS : integer := 30e3;
+
+ type state_t is(state_0, state_1, state_2, state_3);
+
+ signal state : state_t := state_0;
+ signal clk_ms : std_logic;
+ signal ms_tick_cnt : unsigned(31 downto 0) := (others => '0');
+
+begin
+
+ rtc : entity work.rtc(rtc_arq)
+ generic map(clk_freq => clk_freq)
+ port map(
+ clk => clk,
+ rst => rst,
+ clk_ms => clk_ms);
+
+ process(clk_ms, rst) is
+ begin
+
+ if rst = '1' then
+ state <= state_0;
+ ms_tick_cnt <= (others => '0');
+ else
+ ms_tick_cnt <= ms_tick_cnt + 1;
+ case state is
+ when state_0 =>
+ if ms_tick_cnt = RED_TIME_MS then
+
+ ms_tick_cnt <= (others => '0');
+ state <= state_1;
+
+ red_1 <= '1';
+ yel_1 <= '1';
+ gre_1 <= '0';
+ red_2 <= '0';
+ yel_2 <= '1';
+ gre_2 <= '0';
+
+
+ end if;
+ when state_1 =>
+ if ms_tick_cnt = YEL_TIME_MS then
+
+ ms_tick_cnt <= (others => '0');
+ state <= state_2;
+
+ red_1 <= '0';
+ yel_1 <= '0';
+ gre_1 <= '1';
+ red_2 <= '1';
+ yel_2 <= '0';
+ gre_2 <= '0';
+
+ end if;
+ when state_2 =>
+ if ms_tick_cnt = GRE_TIME_MS then
+
+ ms_tick_cnt <= (others => '0');
+ state <= state_3;
+
+ red_1 <= '0';
+ yel_1 <= '1';
+ gre_1 <= '0';
+ red_2 <= '1';
+ yel_2 <= '1';
+ gre_2 <= '0';
+
+ end if;
+ when state_3 =>
+ if ms_tick_cnt = YEL_TIME_MS then
+
+ ms_tick_cnt <= (others => '0');
+ state <= state_0;
+
+ red_1 <= '1';
+ yel_1 <= '0';
+ gre_1 <= '0';
+ red_2 <= '0';
+ yel_2 <= '0';
+ gre_2 <= '1';
+
+ end if;
+ end case;
+ end if;
+
+ end process;
+
+end architecture;
diff --git a/tps/1/src/intersection_ctrl_tb.vhd b/tps/1/src/intersection_ctrl_tb.vhd
@@ -0,0 +1,40 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity intersection_ctrl_tb is
+end entity;
+
+architecture intersection_ctrl_tb_arq of intersection_ctrl_tb is
+
+ constant CLK_FREQ : integer := 1e6;
+
+ signal sig_clk : std_logic := '0';
+ signal sig_rst : std_logic := '0';
+
+ signal sig_red_1 : std_logic := '0';
+ signal sig_yel_1 : std_logic := '0';
+ signal sig_gre_1 : std_logic := '0';
+
+ signal sig_red_2 : std_logic := '0';
+ signal sig_yel_2 : std_logic := '0';
+ signal sig_gre_2 : std_logic := '0';
+
+begin
+
+ intersection_ctrl : entity work.intersection_ctrl(intersection_ctrl_arq)
+ generic map(clk_freq => CLK_FREQ/1e3) -- make sim times smaller (1000 times)
+ port map(
+ clk => sig_clk,
+ rst => sig_rst,
+
+ red_1 => sig_red_1,
+ yel_1 => sig_yel_1,
+ gre_1 => sig_gre_1,
+ red_2 => sig_red_2,
+ yel_2 => sig_yel_2,
+ gre_2 => sig_gre_2);
+
+ sig_clk <= not sig_clk after 500 ns; -- one rising edge every 1 us
+
+end architecture;
diff --git a/tps/1/src/rtc.vhd b/tps/1/src/rtc.vhd
@@ -0,0 +1,42 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity rtc is
+ generic(clk_freq: integer := 500e3); -- default 1 MHz clock frequency
+ port(
+ clk : in std_logic;
+ rst : in std_logic;
+
+ clk_ms : out std_logic);
+end;
+
+architecture rtc_arq of rtc is
+
+ signal tick_cnt : unsigned(31 downto 0) := (others => '0');
+ signal clk_aux : std_logic := '0';
+
+begin
+
+ process(clk, rst)
+ begin
+
+ if rising_edge(clk) then
+ if rst = '1' then
+ tick_cnt <= (others => '0');
+ clk_aux <= '0';
+ else
+ tick_cnt <= tick_cnt + 1;
+
+ if tick_cnt = (clk_freq - 1)/2e3 then
+ tick_cnt <= (others => '0');
+ clk_aux <= not clk_aux;
+ end if;
+ end if;
+ end if;
+
+ end process;
+
+ clk_ms <= clk_aux;
+
+end architecture;
diff --git a/tps/1/src/rtc_tb.vhd b/tps/1/src/rtc_tb.vhd
@@ -0,0 +1,27 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity rtc_tb is
+end entity;
+
+architecture rtc_arq of rtc_tb is
+
+ constant CLK_FREQ : integer := 1e6; -- 1 MHz clock frecuency
+
+ signal sig_clk : std_logic := '1';
+ signal sig_rst : std_logic := '0';
+ signal sig_clk_ms : std_logic;
+
+begin
+
+ rtc : entity work.rtc(rtc_arq)
+ generic map(clk_freq => CLK_FREQ)
+ port map(
+ clk => sig_clk,
+ rst => sig_rst,
+ clk_ms => sig_clk_ms);
+
+ sig_clk <= not sig_clk after 500 ns; -- 1 MHz clock frequency
+
+end architecture;