mubase

Tutorials of Hamster FPGA. Splitting 7 seg into 2 groups via switches.

Recommended Posts

HI again.I have to say I am enjoying Hamsters Introduction to FPGA. Very good guidelines , tutorials and you have to think for yourself. Thanks again for being so supportive.

 

 I've just finished my program for displaying 0-F on all 4 seven segment displays via the switches.:

architecture Behavioral of segments_switches issignal counter : STD_LOGIC_vector(1 downto 0) ;beginprocess (clk,counter)beginif rising_edge(clk) thencounter <= counter-1;case (counter) iswhen "00" => anodes (3 downto 0) <= "1110";when "01" => anodes <= "1101";when "10" => anodes <= "1011";when others => anodes <="0111";end case;end if;end process;  process (switches(3 downto 0))beginCASE (switches) ISwhen  "1111" => sevenseg(6 downto 0)<=  "0001110" ;	when "1110" => sevenseg (6 downto 0)<="0000110";	when "1101" => sevenseg(6 downto 0) <="0100001";	when "1100" => sevenseg (6 downto 0)<="1000110";	when "1011" => sevenseg (6 downto 0)<="0000011";	when "1010" => sevenseg (6 downto 0)<="0001000";	when "1001" => sevenseg(6 downto 0) <="0010000";	when "1000" => sevenseg (6 downto 0) <="0000000";	when "0111" => sevenseg (6 downto 0)<="1111000";	when "0110" => sevenseg (6 downto 0) <="0000010";	when "0101" => sevenseg(6 downto 0) <="0010010";	when "0100" => sevenseg (6 downto 0) <="0011001";	when "0011" => sevenseg (6 downto 0) <="0110000";	when "0010" => sevenseg (6 downto 0) <="0100100";when "0001" => sevenseg (6 downto 0)<="1111001";when others => sevenseg (6 downto 0) <="1000000";	end CASE;	end process;end Behavioral;

 

This seemed to work nicely but I haven't set any particular clock speed...Now, if I want to display digits on the leftmost 2 SSDs with switches 3 downto 0 and on the rightmost with switches 7 downto 4, should I use if statements? Or do I use  nested CASES and if so how? Or is there another way..?

 

Share this post


Link to post
Share on other sites

Just use another separate process, basically copy the existing one and change switches(3 downto 0) to switches (7 downto 4) throughout the new process.

In your original process, replace sevenseg with sevenseg_left, in the new process use sevenseg_right (also declare these new signals as suitable slv)

Finally in your process where you assign the anodes, add new code for cases 00 and 01 assign sevenseg<=sevenseg_right then for the other two cases assign sevenseg<=sevenseg_left

Done!

 

PS also name your processes so it's easy to refer to them, eg instead of

 

process (switches(3 downto 0))

use

 

low_digits : process (switches(3 downto 0))

Or whatever name you feel like using.

 

PPS In the case statement, don't just use switches because it is too vague, be explicit and use switches(range) where range is a "x downto y" you actually are interested in.

Share this post


Link to post
Share on other sites

If you wanted to reuse your code you could also do something like

 

  signal digit : std_logic_vector(3 downto 0);

...

 

case counter(16 downto 15) is   when "00" =>     anodes (3 downto 0) <= "1110";     digit <= switches(7 downto 4);  when "01" =>     anodes <= "1101";     digit <= switches(7 downto 4);  when "10" =>     anodes <= "1011";     digit <= switches(3 downto 0);  when others =>     anodes <="0111";     digit <= switches(3 downto 0); end case;
And then use "case digit is " when you decode the values for the 7seg.

(and as usual I haven't checked that this code meets your needs (or even VHDL syntax) ).

 

Ps. You will need to make counter big - at 32MHz bits 16 down to 15 will change digits about once every millisecond or so. If you multiplex the digits too quickly everything will be a blur as the 7segs have not been engineered to respond in 32 nanoseconds :-)

Share this post


Link to post
Share on other sites
  • Hi! Ive tried both suggestions. Here's my attempt at Alex's code example:
entity segments_switches is    Port ( anodes : out  STD_LOGIC_VECTOR (3 downto 0);				           sevenseg : out  STD_LOGIC_VECTOR (6 downto 0);          -- dp : out  STD_LOGIC;           switches : in  STD_LOGIC_VECTOR (7 downto 0);			  			  clk			: in std_logic);end segments_switches;architecture Behavioral of segments_switches issignal counter : STD_LOGIC_vector(16 downto 15) ;signal sevensegleft: std_logic_vector(6 downto 0);signal sevensegright: std_logic_vector(6 downto 0);beginprocess (clk,counter)beginif rising_edge(clk) thencounter <= counter-1;case (counter) iswhen "00" => anodes (3 downto 0) <= "1110";sevenseg<=sevensegright;when "01" => anodes <= "1101";sevenseg<=sevensegright;when "10" => anodes <= "1011";sevenseg<=sevensegleft;when others => anodes <="0111";sevenseg<=sevensegleft;end case;end if;end process;  process (switches(3 downto 0))beginCASE (switches(3 downto 0)) ISwhen  "1111" => sevensegright(6 downto 0)<=  "0001110" ;	when "1110" => sevensegright (6 downto 0)<="0000110";	when "1101" => sevensegright(6 downto 0) <="0100001";	when "1100" => sevensegright (6 downto 0)<="1000110";	when "1011" => sevensegright (6 downto 0)<="0000011";	when "1010" => sevensegright (6 downto 0)<="0001000";	when "1001" => sevensegright(6 downto 0) <="0010000";	when "1000" => sevensegright (6 downto 0) <="0000000";	when "0111" => sevensegright (6 downto 0)<="1111000";	when "0110" => sevensegright (6 downto 0) <="0000010";	when "0101" => sevensegright(6 downto 0) <="0010010";	when "0100" => sevensegright (6 downto 0) <="0011001";	when "0011" => sevensegright (6 downto 0) <="0110000";	when "0010" => sevensegright (6 downto 0) <="0100100";when "0001" => sevensegright (6 downto 0)<="1111001";when others => sevensegright (6 downto 0) <="1000000";	end CASE;	end process; process (switches(7 downto 4))beginCASE (switches(7 downto 4)) ISwhen  "1111" => sevensegleft(6 downto 0)<=  "0001110" ;	when "1110" => sevensegleft (6 downto 0)<="0000110";	when "1101" => sevensegleft(6 downto 0) <="0100001";	when "1100" => sevensegleft (6 downto 0)<="1000110";	when "1011" => sevensegleft (6 downto 0)<="0000011";	when "1010" => sevensegleft (6 downto 0)<="0001000";	when "1001" => sevensegleft(6 downto 0) <="0010000";	when "1000" => sevensegleft (6 downto 0) <="0000000";	when "0111" => sevensegleft (6 downto 0)<="1111000";	when "0110" => sevensegleft (6 downto 0) <="0000010";	when "0101" => sevensegleft(6 downto 0) <="0010010";	when "0100" => sevensegleft (6 downto 0) <="0011001";	when "0011" => sevensegleft (6 downto 0) <="0110000";	when "0010" => sevensegleft (6 downto 0) <="0100100";when "0001" => sevensegleft (6 downto 0)<="1111001";when others => sevensegleft (6 downto 0) <="1000000";	end CASE;	end process;end Behavioral;

 

All switches work but its a big mess of blurry numbers across the 4 segments. I've tried clk rates of (16 downto 15),                     (32 downto 31) and (8 downto 7) but they are all the same. The same happened for the second suggestion from Hamster...

What am I doing wrong?

Share this post


Link to post
Share on other sites

Mubase: I see that you are putting a lot of effort in this, and doing endless iterations from synthesis to FPGA uploading.
 
Here's my advice.
 
First, don't feel compelled to try the design right away on your board. I understand that it's quite exciting to upload things so to see if they work (and it is), but synthesis takes too long, and it's always hard to actually inspect signals inside the FPGA.
 
So I suggest you start using the simulator, at least to cover the initial basic operation. It's fast, and you can see al signals and they will give you a clearer clue what is happening inside.
 
Now, in order to simulate that, you will need a testbench. I won't write one for you, but I'll paste a small template here that can help you achieving that goal.
 
 
 

 -- Test bench template.library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;-- Empty TB entity.entity tb isend entity;architecture sim of tb is  -- Change this to your clock period  constant period: time := 10 ns;  signal clk: std_logic := '0';  signal rst: std_logic := '0';  -- Add here the template for your component (ie. UUT)  component MYUUTNAME is    -- generic (    -- )    port (      clk:        in std_logic;      rst:        in std_logic;      someinput:  in std_logic;      someoutput: out std_logic;    );  end component;  -- Add signals here to "feed" your UUT.  signal someinput: std_logic := '0';  signal someoutput: std_logic;begin  -- Clock flips every period/2  clk <= not clk after period/2;  -- Instantiate the UUT  uut: MYUUTNAME    -- generic map (    -- )    port map (      clk       => clk,      rst       => rst,      someinput => someinput, -- signal has same name than port      someoutput => someoutput    );  -- Reset procedure  process  begin    wait for period/2;    rst <= '1';    wait for 2*period;    rst <= '0';    wait;  end process;  -- main driver. You should somehow drive the inputpin here.  process  begin    wait;  end process;  -- Nothing elseend sim;

Follow the other examples about ISE simulation, and you should be done. When you are happy with simulation results, then synthesize and upload to FPGA.

 

Alvie

Share this post


Link to post
Share on other sites

Hi mubase,

 

hamster was only accessing the top two elements of the std_logic_vector, you should still make the thing a full 17 elements wide (16 downto 0) so that it has a 17 bit counter to prescale the clock.

 

You have been declaring a 2 element logic vector, where the valid indices are 16 & 15, 32 &31 and 8 & 7 respectively.

Share this post


Link to post
Share on other sites

Try this - works as it should, minimal (if any) ghosting, drives each digit with a 6.25% duty cycle (an average of about 10mA/LED).

Tested on three LogicStarts - so a good display is possible on them!

 

------------------------------------------------- Demo of the Logicstart seven segment display-----------------------------------------------library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity segments_switches is    Port ( anodes : out  STD_LOGIC_VECTOR (3 downto 0);           sevenseg : out  STD_LOGIC_VECTOR (6 downto 0);          -- dp : out  STD_LOGIC;           switches : in  STD_LOGIC_VECTOR (7 downto 0);           clk         : in std_logic);end segments_switches;architecture Behavioral of segments_switches is   signal counter : STD_LOGIC_vector(17 downto 0) ;   signal sevensegleft: std_logic_vector(6 downto 0);   signal sevensegright: std_logic_vector(6 downto 0);beginprocess (clk)   begin      if rising_edge(clk) then         counter <= counter-1;         case (counter(17  downto 14)) is            when "0000" =>                anodes (3 downto 0) <= "1110";               sevenseg<=sevensegright;            when "0100" =>                anodes <= "1101";               sevenseg<=sevensegright;            when "1000" =>                anodes <= "1011";               sevenseg<=sevensegleft;            when "1100" =>                anodes <="0111";               sevenseg<=sevensegleft;            when others =>                anodes <="1111";               sevenseg<=(others => '1');         end case;      end if;   end process; process (switches(3 downto 0))   begin      CASE (switches(3 downto 0)) IS         when "1111" => sevensegright <= "0001110";         when "1110" => sevensegright <= "0000110";         when "1101" => sevensegright <= "0100001";         when "1100" => sevensegright <= "1000110";         when "1011" => sevensegright <= "0000011";         when "1010" => sevensegright <= "0001000";         when "1001" => sevensegright <= "0010000";         when "1000" => sevensegright <= "0000000";         when "0111" => sevensegright <= "1111000";         when "0110" => sevensegright <= "0000010";         when "0101" => sevensegright <= "0010010";         when "0100" => sevensegright <= "0011001";         when "0011" => sevensegright <= "0110000";         when "0010" => sevensegright <= "0100100";         when "0001" => sevensegright <= "1111001";         when others => sevensegright <= "1000000";         end CASE;   end process;process (switches(7 downto 4))   begin      CASE (switches(7 downto 4)) IS         when "1111" => sevensegleft <= "0001110";         when "1110" => sevensegleft <= "0000110";         when "1101" => sevensegleft <= "0100001";         when "1100" => sevensegleft <= "1000110";         when "1011" => sevensegleft <= "0000011";         when "1010" => sevensegleft <= "0001000";         when "1001" => sevensegleft <= "0010000";         when "1000" => sevensegleft <= "0000000";         when "0111" => sevensegleft <= "1111000";         when "0110" => sevensegleft <= "0000010";         when "0101" => sevensegleft <= "0010010";         when "0100" => sevensegleft <= "0011001";         when "0011" => sevensegleft <= "0110000";         when "0010" => sevensegleft <= "0100100";         when "0001" => sevensegleft <= "1111001";         when others => sevensegleft <= "1000000";      end CASE;   end process;end Behavioral;--============================================================
-- These are the constraints required-- NET "anodes<0>"   LOC="P18" | IOSTANDARD=LVTTL; # A0-- NET "anodes<1>"   LOC="P26" | IOSTANDARD=LVTTL; # A2-- NET "anodes<2>"   LOC="P60" | IOSTANDARD=LVTTL; # A8-- NET "anodes<3>"   LOC="P67" | IOSTANDARD=LVTTL; # A11---- NET "sevenseg<6>" LOC="P62" | IOSTANDARD=LVTTL; # A9 G-- NET "sevenseg<5>" LOC="P35" | IOSTANDARD=LVTTL; # A4 F-- NET "sevenseg<4>" LOC="P33" | IOSTANDARD=LVTTL; # A3 E-- NET "sevenseg<3>" LOC="P53" | IOSTANDARD=LVTTL; # A6 D-- NET "sevenseg<2>" LOC="P40" | IOSTANDARD=LVTTL; # A5 C-- NET "sevenseg<1>" LOC="P65" | IOSTANDARD=LVTTL; # A10 B-- NET "sevenseg<0>" LOC="P57" | IOSTANDARD=LVTTL; # A7 A---- NET switches(7) LOC = "P91";-- NET switches(6) LOC = "P92";-- NET switches(5) LOC = "P94";-- NET switches(4) LOC = "P95";-- NET switches(3) LOC = "P98";-- NET switches(2) LOC = "P2";-- NET switches(1) LOC = "P3";-- NET switches(0) LOC = "P4"; ---- NET "clk" LOC="P89" | PERIOD=31.25ns | IOSTANDARD=LVTTL;

 

Share this post


Link to post
Share on other sites

Ahhhh. Thanks for making that clear. :wacko: 

So because I only had one case instance for the switch combination it showed everything at once basically.

Thanks Hamster and thanks Alvieboy for the tip on using the simulator. I tried it with the first SSD program putting different switch combinations in the instantiation file to see where I was going wrong. 

I think now I'll be able to tackle using all 4 displays to output different digits.  :) 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now