Hello, hardware enthusiasts and developers! Today, we’re diving into a project that blends the rigorous world of hardware design with a dash of whimsical humor. Welcome to GTN (Guess The Number), a strange VHDL project that will keep you guessing—literally! Built with VHDL, one of the most industrial and challenging Hardware Description Languages (HDLs), GTN combines seriousness with fun, resulting in a quirky system that plays mind games with you. Let’s explore this "Stranger Things" style project!
What is GTN?
GTN is a hardware system that, when initialized, displays a number and asks you to guess what that number was. But here’s the twist:
- If you guess correctly, it says, "No! It was wrong," shows you a false number (just to mess with you), and restarts.
- If you guess incorrectly, it says, "No, it was wrong," and displays the real number it originally showed, adding a bit of pressure (LOL).
It’s all in good fun, designed to poke fun at perfectionism in hardware design and bring a smile to your face. Now, let’s get into the technical details!
VHDL Source Code
We’ll provide two versions of the code: one for emulation (simulation) and one for FPGA/ASIC boards. The core logic is similar, but I/O handling differs based on the target.
Version 1: Emulation Version
This version is designed for simulation in tools like ModelSim or GHDL. It uses standard logic signals for input and output. Below is the VHDL code for the entity and architecture.
-- GTN_Emulate.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity GTN_Emulate is
Port (
clk : in STD_LOGIC;
reset : in STD_LOGIC;
guess : in STD_LOGIC_VECTOR (7 downto 0); -- 8-bit guess input
number_display : out STD_LOGIC_VECTOR (7 downto 0); -- 8-bit number display
response : out STD_LOGIC_VECTOR (1 downto 0) -- "00": init, "01": correct guess (false response), "10": incorrect guess
);
end GTN_Emulate;
architecture Behavioral of GTN_Emulate is
signal internal_number : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
signal displayed_number : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
signal state : integer range 0 to 2 := 0; -- 0: init, 1: wait for guess, 2: respond
signal fake_number : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
begin
process (clk, reset)
variable seed : integer := 123456789; -- Simple seed for pseudo-random number
begin
if reset = '1' then
internal_number <= (others => '0');
displayed_number <= (others => '0');
fake_number <= (others => '0');
state <= 0;
response <= "00";
elsif rising_edge(clk) then
case state is
when 0 =>
-- Initialize: generate a "random" number
seed := seed + 1;
internal_number <= std_logic_vector(to_unsigned(seed mod 256, 8));
displayed_number <= internal_number; -- Display real number
response <= "00"; -- Init state
state <= 1;
when 1 =>
-- Wait for guess input (assume guess is stable in simulation)
if guess = internal_number then
-- Correct guess: show fake number (real number + 1)
fake_number <= std_logic_vector(unsigned(internal_number) + 1);
displayed_number <= fake_number;
response <= "01"; -- Correct guess, but false response
else
-- Incorrect guess: show real number
displayed_number <= internal_number;
response <= "10"; -- Incorrect guess
end if;
state <= 2;
when 2 =>
-- Respond and restart after one clock cycle
state <= 0;
end case;
end if;
end process;
number_display <= displayed_number;
end Behavioral;
Testbench for Emulation
To simulate the design, here’s a simple testbench:
-- GTN_Emulate_tb.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity GTN_Emulate_tb is
end GTN_Emulate_tb;
architecture sim of GTN_Emulate_tb is
signal clk : STD_LOGIC := '0';
signal reset : STD_LOGIC := '0';
signal guess : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
signal number_display : STD_LOGIC_VECTOR (7 downto 0);
signal response : STD_LOGIC_VECTOR (1 downto 0);
constant clk_period : time := 10 ns;
begin
uut: entity work.GTN_Emulate
port map (
clk => clk,
reset => reset,
guess => guess,
number_display => number_display,
response => response
);
clk_process: process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
stimulus: process
begin
-- Reset the system
reset <= '1';
wait for 20 ns;
reset <= '0';
wait for 20 ns;
-- Let system initialize and display a number
wait until rising_edge(clk);
wait for clk_period;
-- Guess correctly (match the displayed number)
guess <= number_display;
wait for clk_period * 2;
report "No!! Your wrong! The number was = " &
integer'image(to_integer(unsigned(number_display))) &
" But you wrote = " &
integer'image(to_integer(unsigned(guess)));
-- Guess incorrectly (add 5 to the displayed number)
guess <= std_logic_vector(unsigned(number_display) + 5);
wait for clk_period * 2;
report "You wrote wrong again! The number was = " &
integer'image(to_integer(unsigned(number_display))) &
" but you wrote = " &
integer'image(to_integer(unsigned(guess)));
wait for 100 ns;
assert false report "Simulation finished. Are you really think you can win? LOL" severity failure;
end process;
end sim;
Just change the fake_number <= std_logic_vector(unsigned(internal_number) + YOUR_NUMBER_HERE); in GTN_Emulate, then you can see the result! (Because of limitions of HDL Languages (Not only VHDL, all of them), we can't input straight to user, and the users must change it from source code, but in real FPGA/ASIC Boards are easier!)
Version 2: FPGA/ASIC Board Version
This version is tailored for physical implementation, with inputs from switches and buttons, and outputs to LEDs. It includes button debouncing for reliability.
-- GTN_FPGA.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity GTN_FPGA is
Port (
clk : in STD_LOGIC; -- Board clock (e.g., 100 MHz)
reset : in STD_LOGIC; -- Reset button
guess_switches : in STD_LOGIC_VECTOR (7 downto 0); -- 8 switches for guess input
submit_button : in STD_LOGIC; -- Button to submit guess
leds : out STD_LOGIC_VECTOR (7 downto 0); -- 8 LEDs to display number
response_led : out STD_LOGIC_VECTOR (1 downto 0) -- Additional LEDs for response feedback
);
end GTN_FPGA;
architecture Behavioral of GTN_FPGA is
signal internal_number : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
signal displayed_number : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
signal state : integer range 0 to 2 := 0;
signal button_debounced : STD_LOGIC := '0';
signal fake_number : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
begin
-- Simple button debouncing circuit
process (clk)
variable count : integer := 0;
constant debounce_limit : integer := 1000000; -- Adjust based on clock frequency (e.g., 10 ms debounce)
begin
if rising_edge(clk) then
if submit_button = '1' then
if count < debounce_limit then
count := count + 1;
else
button_debounced <= '1';
end if;
else
count := 0;
button_debounced <= '0';
end if;
end if;
end process;
process (clk, reset)
variable seed : integer := 123456789;
begin
if reset = '1' then
internal_number <= (others => '0');
displayed_number <= (others => '0');
fake_number <= (others => '0');
state <= 0;
response_led <= "00";
elsif rising_edge(clk) then
case state is
when 0 =>
-- Initialize and display a number
seed := seed + 1;
internal_number <= std_logic_vector(to_unsigned(seed mod 256, 8));
displayed_number <= internal_number;
response_led <= "00"; -- Init state
state <= 1;
when 1 =>
-- Wait for guess submission
if button_debounced = '1' then
if guess_switches = internal_number then
-- Correct guess: show fake number
fake_number <= std_logic_vector(unsigned(internal_number) + 1);
displayed_number <= fake_number;
response_led <= "01"; -- Correct guess, false response
else
-- Incorrect guess: show real number
displayed_number <= internal_number;
response_led <= "10"; -- Incorrect guess
end if;
state <= 2;
end if;
when 2 =>
-- Hold response until reset or auto-restart after delay
-- For simplicity, we wait for reset. You can add a timer here.
null;
end case;
end if;
end process;
leds <= displayed_number;
end Behavioral;
Tutorial: Emulation and Synthesis
Emulation (Simulation)
- Install a VHDL simulator: Use GHDL (open-source) or ModelSim (commercial). For GHDL, download from ghdl.free.fr.
-
Save the code: Create two files:
GTN_Emulate.vhdandGTN_Emulate_tb.vhd. - Compile and run (with GHDL):
ghdl -a GTN_Emulate.vhd
ghdl -a GTN_Emulate_tb.vhd
ghdl -e GTN_Emulate_tb
ghdl -r GTN_Emulate_tb --vcd=gtn.vcd
-
View waveforms: Use GTKWave to open
gtn.vcdand analyze signals likenumber_display,guess, andresponse.
Synthesis for FPGA
- Choose your toolchain: Use Xilinx Vivado for Xilinx FPGAs or Intel Quartus for Intel FPGAs.
-
Create a new project: Add the
GTN_FPGA.vhdfile. - Assign pins: Map the ports to your board’s physical pins (e.g., clocks, buttons, switches, LEDs). Refer to your board’s schematic.
- Generate bitstream: Run synthesis, implementation, and generate the programming file.
-
Program the FPGA: Connect your board, load the bitstream, and test!
- After reset, LEDs show a number.
- Set guess using switches, press submit button.
- LEDs update based on your guess—remember the GTN twist!
Bonus Challenge
Think you can beat GTN?
If you do, we’ll hand over the keys to AWS in your name (LOL).
Spoiler: Nobody ever wins. 😉
Call to Action
Got a strange hardware project idea? Built something quirky with VHDL, Verilog, or any HDL? Share it with us! We’d love to hear about it and help broadcast it to the world. Let’s celebrate the fun side of hardware design together.
Reach out to me on Telegram: JavadInteger. Send a message with your project details, and we might feature it in our next blog post!
Thanks for reading, and happy coding! May your guesses always be wrong—or are they? 😉
Top comments (0)