You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VHDL新手求助:BASYS-3开发板0000-0099七段显示开关控制实现

Hey there! Let's walk through building this 00-99 switch-controlled counter for your Basys 3 board—you’ve already nailed the core seven-segment decoder, so we’re halfway there!

First, a quick note: you don’t need to manually pick individual logic gates (AND/OR/etc.) for this. VHDL is a behavioral description language—you describe what the circuit does, and tools like Vivado will automatically translate your code into the right logic gates and flip-flops. That takes a lot of the guesswork out!

Here's a step-by-step breakdown of the full system:

1. System Overview

Your design needs 4 core components:

  • A clock divider to turn the Basys 3’s 100MHz system clock into a slow 1Hz signal (for counting once per second)
  • A dual BCD counter (tens + units) controlled by your switches and start/stop signal
  • A 1kHz clock divider for seven-segment display multiplexing (so the two digits don’t flicker)
  • A multiplexer to toggle between displaying the tens and units digits on the seven-segment displays
2. Clock Dividers

First, we need to create slower clocks for counting and display scanning:

1Hz Clock Divider (for counting)

This takes the 100MHz clock and outputs a 1Hz signal to drive the counter:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity clk_divider_1hz is
    Port ( clk : in STD_LOGIC;
           reset : in STD_LOGIC;
           clk_1hz : out STD_LOGIC);
end clk_divider_1hz;

architecture Behavioral of clk_divider_1hz is
    signal count : unsigned(25 downto 0) := (others => '0');
    signal temp_clk : STD_LOGIC := '0';
begin
    process(clk, reset)
    begin
        if reset = '1' then
            count <= (others => '0');
            temp_clk <= '0';
        elsif rising_edge(clk) then
            -- Count to 50 million (half of 100MHz) to get a 1Hz square wave
            if count = to_unsigned(49999999, 26) then
                count <= (others => '0');
                temp_clk <= not temp_clk;
            else
                count <= count + 1;
            end if;
        end if;
    end process;
    clk_1hz <= temp_clk;
end Behavioral;

1kHz Clock Divider (for display multiplexing)

This creates a fast enough clock to switch between digits without visible flicker:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity clk_divider_1khz is
    Port ( clk : in STD_LOGIC;
           reset : in STD_LOGIC;
           clk_1khz : out STD_LOGIC);
end clk_divider_1khz;

architecture Behavioral of clk_divider_1khz is
    signal count : unsigned(16 downto 0) := (others => '0');
    signal temp_clk : STD_LOGIC := '0';
begin
    process(clk, reset)
    begin
        if reset = '1' then
            count <= (others => '0');
            temp_clk <= '0';
        elsif rising_edge(clk) then
            if count = to_unsigned(49999, 17) then
                count <= (others => '0');
                temp_clk <= not temp_clk;
            else
                count <= count + 1;
            end if;
        end if;
    end process;
    clk_1khz <= temp_clk;
end Behavioral;
3. Dual BCD Counter

This counter handles both manual switch input and automatic counting:

  • When the start/stop switch is off: the tens and units digits directly match your switch inputs
  • When the start/stop switch is on: the counter increments once per second, rolling over from 99 back to 00
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity bcd_dual_counter is
    Port ( clk_1hz : in STD_LOGIC;
           reset : in STD_LOGIC;
           start_stop : in STD_LOGIC;
           sw_tens : in STD_LOGIC_VECTOR(3 downto 0);
           sw_units : in STD_LOGIC_VECTOR(3 downto 0);
           bcd_tens : out STD_LOGIC_VECTOR(3 downto 0);
           bcd_units : out STD_LOGIC_VECTOR(3 downto 0));
end bcd_dual_counter;

architecture Behavioral of bcd_dual_counter is
    signal count_tens : unsigned(3 downto 0) := (others => '0');
    signal count_units : unsigned(3 downto 0) := (others => '0');
begin
    process(clk_1hz, reset, start_stop)
    begin
        if reset = '1' then
            count_tens <= (others => '0');
            count_units <= (others => '0');
        elsif start_stop = '0' then
            -- Manual mode: set digits directly from switches
            count_tens <= unsigned(sw_tens);
            count_units <= unsigned(sw_units);
        elsif rising_edge(clk_1hz) then
            -- Automatic counting mode
            if count_units = 9 then
                count_units <= (others => '0');
                if count_tens = 9 then
                    count_tens <= (others => '0');
                else
                    count_tens <= count_tens + 1;
                end if;
            else
                count_units <= count_units + 1;
            end if;
        end if;
    end process;
    
    bcd_tens <= std_logic_vector(count_tens);
    bcd_units <= std_logic_vector(count_units);
end Behavioral;
4. Seven-Segment Multiplexer

This uses your existing BCD decoder and toggles between tens/units digits to display both at once:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity seven_seg_mux is
    Port ( clk_1khz : in STD_LOGIC;
           bcd_tens : in STD_LOGIC_VECTOR(3 downto 0);
           bcd_units : in STD_LOGIC_VECTOR(3 downto 0);
           seg : out STD_LOGIC_VECTOR(6 downto 0);
           an : out STD_LOGIC_VECTOR(3 downto 0));
end seven_seg_mux;

architecture Behavioral of seven_seg_mux is
    signal bcd_display : STD_LOGIC_VECTOR(3 downto 0);
begin
    -- Your existing BCD-to-seven-segment decoder (works for Basys3's common anode displays)
    process(bcd_display) begin
        case bcd_display is
            when "0000" => seg <= "0000001"; -- 0
            when "0001" => seg <= "1001111"; -- 1
            when "0010" => seg <= "0010010"; -- 2
            when "0011" => seg <= "0000110"; -- 3
            when "0100" => seg <= "1001100"; -- 4
            when "0101" => seg <= "0100100"; -- 5
            when "0110" => seg <= "0100000"; -- 6
            when "0111" => seg <= "0001111"; -- 7
            when "1000" => seg <= "0000000"; -- 8
            when "1001" => seg <= "0000100"; -- 9
            when others => seg <= "1111111"; -- Turn off invalid digits
        end case;
    end process;
    
    -- Toggle between tens and units digits
    process(clk_1khz)
    begin
        if rising_edge(clk_1khz) then
            if clk_1khz = '0' then
                -- Display units digit (rightmost display, AN0)
                bcd_display <= bcd_units;
                an <= "1110"; -- Common anode: low = on
            else
                -- Display tens digit (second from right, AN1)
                bcd_display <= bcd_tens;
                an <= "1101";
            end if;
        end if;
    end process;
end Behavioral;
5. Top-Level Module

This ties all components together and maps to the Basys3's physical pins:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity top_basys3_counter is
    Port ( clk : in STD_LOGIC;
           reset : in STD_LOGIC;
           sw : in STD_LOGIC_VECTOR(15 downto 0); -- 16 Basys3 switches
           seg : out STD_LOGIC_VECTOR(6 downto 0);
           an : out STD_LOGIC_VECTOR(3 downto 0));
end top_basys3_counter;

architecture Behavioral of top_basys3_counter is
    component clk_divider_1hz
        Port ( clk : in STD_LOGIC;
               reset : in STD_LOGIC;
               clk_1hz : out STD_LOGIC);
    end component;
    
    component clk_divider_1khz
        Port ( clk : in STD_LOGIC;
               reset : in STD_LOGIC;
               clk_1khz : out STD_LOGIC);
    end component;
    
    component bcd_dual_counter
        Port ( clk_1hz : in STD_LOGIC;
               reset : in STD_LOGIC;
               start_stop : in STD_LOGIC;
               sw_tens : in STD_LOGIC_VECTOR(3 downto 0);
               sw_units : in STD_LOGIC_VECTOR(3 downto 0);
               bcd_tens : out STD_LOGIC_VECTOR(3 downto 0);
               bcd_units : out STD_LOGIC_VECTOR(3 downto 0));
    end component;
    
    component seven_seg_mux
        Port ( clk_1khz : in STD_LOGIC;
               bcd_tens : in STD_LOGIC_VECTOR(3 downto 0);
               bcd_units : in STD_LOGIC_VECTOR(3 downto 0);
               seg : out STD_LOGIC_VECTOR(6 downto 0);
               an : out STD_LOGIC_VECTOR(3 downto 0));
    end component;
    
    signal clk_1hz : STD_LOGIC;
    signal clk_1khz : STD_LOGIC;
    signal bcd_tens : STD_LOGIC_VECTOR(3 downto 0);
    signal bcd_units : STD_LOGIC_VECTOR(3 downto 0);
    
    -- Switch mapping (adjust if you prefer different positions):
    -- SW15 = Start/Stop
    -- SW11-SW8 = Tens digit input
    -- SW3-SW0 = Units digit input
begin
    u_clk_1hz : clk_divider_1hz
        port map(clk => clk, reset => reset, clk_1hz => clk_1hz);
    
    u_clk_1khz : clk_divider_1khz
        port map(clk => clk, reset => reset, clk_1khz => clk_1khz);
    
    u_counter : bcd_dual_counter
        port map(clk_1hz => clk_1hz, reset => reset,
                 start_stop => sw(15),
                 sw_tens => sw(11 downto 8),
                 sw_units => sw(3 downto 0),
                 bcd_tens => bcd_tens,
                 bcd_units => bcd_units);
    
    u_seg_mux : seven_seg_mux
        port map(clk_1khz => clk_1khz,
                 bcd_tens => bcd_tens,
                 bcd_units => bcd_units,
                 seg => seg,
                 an => an);
end Behavioral;
Quick Setup Tips
  • Connect the Basys3's BTNR (right button) to the reset pin to reset the counter to 00
  • Double-check your switch assignments in the top module if you want to use different switches
  • The seven-segment code assumes common anode displays (which the Basys3 uses), so your existing decoder is perfect as-is

内容的提问来源于stack exchange,提问作者selinoktay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:34:55