S3E Lesson7

Talk about the fifth PyroEDU course here.
Bingo600
Newbie Pyro
Posts: 75
Joined: Sat Jun 28, 2014 7:22 am

S3E Lesson7

Postby Bingo600 » Sat Aug 09, 2014 2:46 pm

Chris here is my implementation on the S3E Starterboard.

ISE wasn't really happy , i got two warnings

WARNING:Pack:249 - The following adjacent carry multiplexers occupy different
slice components. The resulting carry chain will have suboptimal timing.
Mcompar_ticks_cmp_ge0000_cy<12>
Mcount_ticks_cy<0>

WARNING:Route:455 - CLK Net:hz_10 may have excessive skew because



File : lesson7-bad.vhd

Code: Select all

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity lesson7 is
   Generic ( osc_freq: natural := 50000000);
   port(
      RESET: in std_logic; --"btn_south" LOC = "K17"
      clk: in std_logic; --50Mhz Clock
      BUTTON: in std_logic; --"btn_west"  LOC = "D18"
      LED_BTN: out std_logic; --LED7
      SEG7: out std_logic_vector(6 downto 0) --LED 6..0
   );
end lesson7;

architecture rtl of lesson7 is
   signal data: std_logic;
   signal bcd_value: std_logic_vector(3 downto 0);
   signal hz_25m: std_logic :='0';
   signal hz_10: std_logic :='0';   
   begin
   
   --First Process
   DATA_REGISTER_0: process(RESET,hz_10,BUTTON)
   begin
      if RESET = '1' then
      data <= '0';
      elsif rising_edge(hz_10) then
      data <= BUTTON;
      end if;
   end process DATA_REGISTER_0;

   LED_BTN <= data;
   
--Second Process
   TIMER_0: process(RESET,hz_10)
   begin
      if RESET = '1' then
      bcd_value <= "0000";
      elsif rising_edge(hz_10) then
      bcd_value <= bcd_value + 1;
      end if;
   end process TIMER_0;
   
-- 50Mhz to 25Mhz predivide
   CLOCK_DIV2: process(clk,RESET)
   begin
   if RESET = '1' then
      hz_25m <= '0';
   elsif rising_edge(clk) then
      hz_25m = not hz_25m;
      end if;
   end if;
   end process CLOCK_DIV2;   
   
-- 10HZ Clock   Process
   CLOCK_10HZ: process(hz_25m,RESET)
   VARIABLE ticks:integer range 0 to ((osc_freq/10)/2)-1;
   begin
   if RESET = '1' then
      ticks:=0;
   elsif rising_edge(clk) then
      ticks:=ticks+1;
      if ticks >=(((osc_freq/10)/2)/2)-1 then
         hz_10 <= not hz_10;
         ticks:=0;
      end if;
   end if;
   end process CLOCK_10HZ;

-- HC4511 Process   (bcd to 7seg driver)
-- http://www.ti.com/lit/ds/symlink/cd74hc4511.pdf
-- Inspired by http://vhdlguru.blogspot.se/2010/03/vhdl-code-for-bcd-to-7-segment-display.html
-- But changed to "active high" led segments.
--
   HC4511: process(hz_10,bcd_value,RESET)
   begin
      if RESET = '1' then
      SEG7 <= "1111110";  -- '0'
      elsif rising_edge(hz_10) then
      case  bcd_value is
      when "0000"=> SEG7 <="1111110";  -- '0'
      when "0001"=> SEG7 <="0110000";  -- '1'
      when "0010"=> SEG7 <="1101101";  -- '2'
      when "0011"=> SEG7 <="1111001";  -- '3'
      when "0100"=> SEG7 <="0110011";  -- '4'
      when "0101"=> SEG7 <="1011011";  -- '5'
      when "0110"=> SEG7 <="1011111";  -- '6'
      when "0111"=> SEG7 <="1110000";  -- '7'
      when "1000"=> SEG7 <="1111111";  -- '8'
      when "1001"=> SEG7 <="1111011";  -- '9'
       --nothing is displayed when a number more than 9 is given as input.
      when others=> SEG7 <="0000000";
      end case;
      end if;      
   end process HC4511;
   
end rtl;


/Bingo

Bingo600
Newbie Pyro
Posts: 75
Joined: Sat Jun 28, 2014 7:22 am

Re: S3E Lesson7

Postby Bingo600 » Sat Aug 09, 2014 3:03 pm

I got stubborn , and wanted it to be "clean" :?

The :
WARNING:Pack:249 - The following adjacent carry multiplexers occupy different
slice components. The resulting carry chain will have suboptimal timing.
Mcompar_ticks_cmp_ge0000_cy<12>
Mcount_ticks_cy<0>


Went away by adding a FF as predivider to the 50Mhz clock .... Why ???
Does the "logic "fit" when only handling 25Mhz in the divider chain ?

The :
WARNING:Route:455 - CLK Net:hz_10 may have excessive skew because

Was solved by resyncing the 10Hz clock to the 50Mhz clock with a FF.


File: lesson7.vhd

Code: Select all

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity lesson7 is
   Generic ( osc_freq: natural := 50000000);
   port(
      RESET: in std_logic; --"btn_south" LOC = "K17"
      clk: in std_logic; --50Mhz Clock
      BUTTON: in std_logic; --"btn_west"  LOC = "D18"
      LED_BTN: out std_logic; --LED7
      SEG7: out std_logic_vector(6 downto 0) --LED 6..0
   );
end lesson7;

architecture rtl of lesson7 is
   signal data: std_logic;
   signal bcd_value: std_logic_vector(3 downto 0);
   signal hz_25m: std_logic :='0';
   signal hz_10: std_logic :='0';
   signal hz_10sync: std_logic :='0';   
   begin

---------------------- Begin 50Mhz to 10Hz Clock divide ---------------------------

-- 50Mhz to 25Mhz predivide
   CLOCK_DIV2: process(clk,RESET)
   begin
   if RESET = '1' then
      hz_25m <= '0';
   elsif rising_edge(clk) then
      hz_25m <= not hz_25m;
   end if;
   end process CLOCK_DIV2;   
   
-- 10HZ Clock   Process
   CLOCK_10HZ: process(hz_25m,RESET)
   VARIABLE ticks:integer range 0 to ((osc_freq/10)/2)-1;
   begin
   if RESET = '1' then
      ticks:=0;
   elsif rising_edge(hz_25m) then
      ticks:=ticks+1;
      if ticks >=(((osc_freq/10)/2)/2)-1 then
         hz_10 <= not hz_10;
         ticks:=0;
      end if;
   end if;
   end process CLOCK_10HZ;

-- 10Hz resync to 50Mhz
   HZ_10_sync: process(clk,hz_10,RESET)
   begin
   if RESET = '1' then
      hz_10sync <= '0';
   elsif rising_edge(clk) then
      hz_10sync <= hz_10;
   end if;
   end process HZ_10_sync;   
   
---------------------- End 50Mhz to 10Hz Clock divide ---------------------------
   
   --First Process
   DATA_REGISTER_0: process(RESET,hz_10sync,BUTTON)
   begin
      if RESET = '1' then
      data <= '0';
      elsif rising_edge(hz_10sync) then
      data <= BUTTON;
      end if;
   end process DATA_REGISTER_0;

   LED_BTN <= data;
   
--Second Process
   TIMER_0: process(RESET,hz_10sync)
   begin
      if RESET = '1' then
      bcd_value <= "0000";
      elsif rising_edge(hz_10sync) then
      bcd_value <= bcd_value + 1;
      end if;
   end process TIMER_0;
   

-- HC4511 Process   (bcd to 7seg driver)
-- http://www.ti.com/lit/ds/symlink/cd74hc4511.pdf
-- Inspired by http://vhdlguru.blogspot.se/2010/03/vhdl-code-for-bcd-to-7-segment-display.html
-- But changed to "active high" led segments.
--
   HC4511: process(hz_10sync,bcd_value,RESET)
   begin
      if RESET = '1' then
      SEG7 <= "1111110";  -- '0'
      elsif rising_edge(hz_10sync) then
         case  bcd_value is
            when "0000"=> SEG7 <="1111110";  -- '0'
            when "0001"=> SEG7 <="0110000";  -- '1'
            when "0010"=> SEG7 <="1101101";  -- '2'
            when "0011"=> SEG7 <="1111001";  -- '3'
            when "0100"=> SEG7 <="0110011";  -- '4'
            when "0101"=> SEG7 <="1011011";  -- '5'
            when "0110"=> SEG7 <="1011111";  -- '6'
            when "0111"=> SEG7 <="1110000";  -- '7'
            when "1000"=> SEG7 <="1111111";  -- '8'
            when "1001"=> SEG7 <="1111011";  -- '9'
             --nothing is displayed when a number more than 9 is given as input.
            when others=> SEG7 <="0000000";
         end case;
      end if;      
   end process HC4511;
   
end rtl;


Question:
In the HC4511: process
I assign the values to the output ping directly inside the process , without using an intermediate variable , and assign it outside the process.
Is that bad ? , because the "output" (SEG7) could toggle while the case is traversed ?
Is the correct way to use an intermediate signal vector , and then assign it outside the process ?






This is starting to be really fun , i didn't have to think much about how to write the "resync" in VHDL.
At first i "grumbled" but then i "read up inside my head what i wanted" ....
And the words "When rising edge of "master clock" , assign the 10hzsync to the 10Hz variable" ------ DONE :D :D

I have included the ISE RTL , and the whole project.

I forgot my 7-seg & some 470R resistors back in Denmark. :cry: , so i can only verify on the S3E board by looking at the 6 LEDS ... Not optimal.
But at least it shows the pattern for '0' when i press RESET , so i suppose it's ok.

/Bingo
Attachments
lesson7b-ise-rtl-print.pdf.zip
(14.44 KiB) Downloaded 442 times
lesson7b-ise.zip
(49.76 KiB) Downloaded 421 times
Last edited by Bingo600 on Sat Aug 09, 2014 3:11 pm, edited 2 times in total.

Bingo600
Newbie Pyro
Posts: 75
Joined: Sat Jun 28, 2014 7:22 am

Re: S3E Lesson7

Postby Bingo600 » Sat Aug 09, 2014 3:06 pm

I did copy the ISE (S3E) VHDL to Quartus , to see if the RTL viewer was better ...
It was so..so , i understand what you said in the previous lesson now.

The ISE RTL is as clear as the Quartus.

I have included the QII RTL & Project

Ohh: And got bitten by QII , as the logic didnt fit a 32 MC CPLD , so i switched to a 64 MC in QII

/Bingo
Attachments
lesson7b-quartus-rtl-print.pdf.zip
(24.35 KiB) Downloaded 429 times
Lesson7b-quartus.zip
(23.93 KiB) Downloaded 447 times

ThePyroElectro
PyroElectro Admin
Posts: 1181
Joined: Mon Nov 12, 2007 9:24 pm
Location: Earth
Contact:

Re: S3E Lesson7

Postby ThePyroElectro » Tue Aug 12, 2014 3:14 pm

Bingo600 wrote:Chris here is my implementation on the S3E Starterboard.

ISE wasn't really happy , i got two warnings

WARNING:Pack:249 - The following adjacent carry multiplexers occupy different
slice components. The resulting carry chain will have suboptimal timing.
Mcompar_ticks_cmp_ge0000_cy<12>
Mcount_ticks_cy<0>

WARNING:Route:455 - CLK Net:hz_10 may have excessive skew because


/Bingo


A thing about warnings and the FPGA tools. When you're first starting out with FPGAs its a good idea to try to understand what the warnings mean and how to mitigate them. But as you continue into FPGA, you'll see that many of the warnings are not relative to your design needs. As an example, some projects that I've worked on have had many hundreds of warnings. But understanding when a warning actually matters is an important part of this learning process.

Bingo600 wrote:I got stubborn , and wanted it to be "clean" :?
..
..
Went away by adding a FF as predivider to the 50Mhz clock .... Why ???
Does the "logic "fit" when only handling 25Mhz in the divider chain ?
..
..
Question:
In the HC4511: process
I assign the values to the output ping directly inside the process , without using an intermediate variable , and assign it outside the process.
Is that bad ? , because the "output" (SEG7) could toggle while the case is traversed ?
Is the correct way to use an intermediate signal vector , and then assign it outside the process ?
/Bingo


[a]
Haha, that RTL diagram looks pretty funny. The clock flip-flops are all over the place >_<. Xilinx Fail. I doubt that it is 50 MHz vs 25 MHz thing. It is far more likely that the resync flip-flop you added is acting more like a registered input for the clock, kind of like a mini-pipeline.

One thing that is very useful for meeting timing in FPGAs is by 'registering inputs/outputs'. There's a fair amount of literature on altera, xilinx, stackoverflow .. etc .. for the different methods of doing this. But the altera and xilinx tools have a little check box to register inputs and outputs during synthesis.

[b]
The way you used SEG7 is more in-line with how a d-flip-flop would be specified in VHDL. However, since the output is only defined on one clock transition, the tools can get confused as the design gets more complex and things might not work---but as you have written it, I'm sure it works fine because things are still simple. Using a signal inside of the process and assigning it to the output as a concurrent (combinatorial) statement will create a register as VHDL understands it, so the output will never be questioned. That's how you should do it.

Bingo600 wrote:I did copy the ISE (S3E) VHDL to Quartus , to see if the RTL viewer was better ...
It was so..so , i understand what you said in the previous lesson now.

The ISE RTL is as clear as the Quartus.

I have included the QII RTL & Project

Ohh: And got bitten by QII , as the logic didnt fit a 32 MC CPLD , so i switched to a 64 MC in QII

/Bingo


Neat, Quartus' RTL actually serialized the clock instead of putting it all over the place like ISE. The parallel process' are actually much easier to identify as well.

I'll guess that the ticks interger was too large for the CPLD. A counter of that size (26 bits or so?) would take up a good amount of logic in a CPLD. If you haven't tried already, it might be a good exercise to look through the timing/logic summary and log files in either ISE or Quartus to find out what type of logic elements were used to build your design.

When you need to make a large design fit into a smaller part, you have to scan through the logs a lot and if you see a 20+ bit counter somewhere there, you know you need to break it down to something smaller to get the design to fit.

Bingo600
Newbie Pyro
Posts: 75
Joined: Sat Jun 28, 2014 7:22 am

Re: S3E Lesson7

Postby Bingo600 » Tue Aug 12, 2014 6:09 pm

ThePyroElectro wrote:
A thing about warnings and the FPGA tools. When you're first starting out with FPGAs its a good idea to try to understand what the warnings mean and how to mitigate them. But as you continue into FPGA, you'll see that many of the warnings are not relative to your design needs. As an example, some projects that I've worked on have had many hundreds of warnings. But understanding when a warning actually matters is an important part of this learning process.



I will prob. be able to understand that when many..many more hours of VHDL has ben made.


ThePyroElectro wrote:
[a]
Haha, that RTL diagram looks pretty funny. The clock flip-flops are all over the place >_<. Xilinx Fail. I doubt that it is 50 MHz vs 25 MHz thing. It is far more likely that the resync flip-flop you added is acting more like a registered input for the clock, kind of like a mini-pipeline.

One thing that is very useful for meeting timing in FPGAs is by 'registering inputs/outputs'. There's a fair amount of literature on altera, xilinx, stackoverflow .. etc .. for the different methods of doing this. But the altera and xilinx tools have a little check box to register inputs and outputs during synthesis.


Is that in the "pin-planner" on ISE ?
I haven't used it yet .... I prefer the UCF file directly.
But i prob. have to try it , if not for else than to see what options i can give in the ucf file.


ThePyroElectro wrote:
[b]
The way you used SEG7 is more in-line with how a d-flip-flop would be specified in VHDL. However, since the output is only defined on one clock transition, the tools can get confused as the design gets more complex and things might not work---but as you have written it, I'm sure it works fine because things are still simple. Using a signal inside of the process and assigning it to the output as a concurrent (combinatorial) statement will create a register as VHDL understands it, so the output will never be questioned. That's how you should do it.

I don't think i understand this ansver fully , besides that my code would probably work.

ThePyroElectro wrote:Neat, Quartus' RTL actually serialized the clock instead of putting it all over the place like ISE. The parallel process' are actually much easier to identify as well.

I'll guess that the ticks interger was too large for the CPLD. A counter of that size (26 bits or so?) would take up a good amount of logic in a CPLD. If you haven't tried already, it might be a good exercise to look through the timing/logic summary and log files in either ISE or Quartus to find out what type of logic elements were used to build your design.

When you need to make a large design fit into a smaller part, you have to scan through the logs a lot and if you see a 20+ bit counter somewhere there, you know you need to break it down to something smaller to get the design to fit.


Would i have saved some logic if i did eq instead of ge ? :

Code: Select all

if ticks =(((osc_freq/10)/2)/2)-1 then

Instead of

if ticks >=(((osc_freq/10)/2)/2)-1 then


I will try to look through the logs , to see if i can find the things you mention.

/Bingo

ThePyroElectro
PyroElectro Admin
Posts: 1181
Joined: Mon Nov 12, 2007 9:24 pm
Location: Earth
Contact:

Re: S3E Lesson7

Postby ThePyroElectro » Tue Aug 12, 2014 6:53 pm

Is that in the "pin-planner" on ISE ?
I haven't used it yet .... I prefer the UCF file directly.
But i prob. have to try it , if not for else than to see what options i can give in the ucf file.


Yea, modifying the UCF is a preferred way to do it:
http://www.xilinx.com/support/documentation/sw_manuals/xilinx11/pce_p_registers_in_iob.htm

A word of warning though. The UCF file-format will likely disappear within the next 2-3 years as the SDC format is becoming the industry standard.

Another option is called 're-timing' by allowing the tool to try and be intelligent and figure out how to realign registers for optimal timing, given your design constraints.

I don't think i understand this ansver fully , besides that my code would probably work.


I don't have the time at the moment to draw up a simulation, but if you tried to perform a test-bench for that type of process, you'd see either 'X' or 'U' outputs (undefined/unknown) during the falling edge portion of the clock. Again, that doesn't mean it won't work, just that outputs can't be guaranteed, so its best to follow the standard VHDL register format.

Would i have saved some logic if i did eq instead of ge ? :


I doubt it. My guess is it would probably synthesize almost exactly the same way. If you chop it up into multiple counters cascaded in a pipe-line, then that would definitely make a difference. Although then you might not be able to create the exact same project...but at least then a similar design could fit into the CPLD.

Bingo600
Newbie Pyro
Posts: 75
Joined: Sat Jun 28, 2014 7:22 am

Re: S3E Lesson7

Postby Bingo600 » Tue Aug 12, 2014 8:08 pm

Thanx Chris

I'm toying a bit with the constraints editor , and right now it says (static timing) :

Design statistics:
Minimum period: 9.823ns{1} (Maximum frequency: 101.802MHz)


Seems like a nice constraint doc
http://www.ue.pwr.wroc.pl/pld/pld_9.pdf

/Bingo

Bingo600
Newbie Pyro
Posts: 75
Joined: Sat Jun 28, 2014 7:22 am

Re: S3E Lesson7

Postby Bingo600 » Wed Aug 13, 2014 6:12 pm

I don't have the time at the moment to draw up a simulation, but if you tried to perform a test-bench for that type of process, you'd see either 'X' or 'U' outputs (undefined/unknown) during the falling edge portion of the clock. Again, that doesn't mean it won't work, just that outputs can't be guaranteed, so its best to follow the standard VHDL register format.


Chris i have fooled with a testbench , that's new & strange to me.

The tb starts with :
BCD[3..0] UUUU and changes to XXXX
SEG7[6..0] UUUUUUU and changes to 000000

On the first transistion of HZ_10_Sync (See attached PDF).


My tb might be wrong but ???

Code: Select all

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_lesson7 IS
END tb_lesson7;
 
ARCHITECTURE behavior OF tb_lesson7 IS
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT lesson7
    PORT(
         RESET : IN  std_logic;
         clk : IN  std_logic;
         BUTTON : IN  std_logic;
         LED_BTN : OUT  std_logic;
         SEG7 : OUT  std_logic_vector(6 downto 0)
        );
    END COMPONENT;
   

   --Inputs
   signal RESET : std_logic := '0';
   signal clk : std_logic := '0';
   signal BUTTON : std_logic := '0';

    --Outputs
   signal LED_BTN : std_logic;
   signal SEG7 : std_logic_vector(6 downto 0);

   -- Clock period definitions
   constant clk_period : time := 10 ns;
 
BEGIN
 
   -- Instantiate the Unit Under Test (UUT)
   uut: lesson7 PORT MAP (
          RESET => RESET,
          clk => clk,
          BUTTON => BUTTON,
          LED_BTN => LED_BTN,
          SEG7 => SEG7
        );

   -- Clock process definitions
   clk_process :process
   begin
      clk <= '0';
      wait for clk_period/2;
      clk <= '1';
      wait for clk_period/2;
   end process;
 END;



But it seems like BCD doesn't change correctly on the HZ_10_sync transitions ???

And therefore SEG7 is always all '0's


Edit... ARGHHH ....
It (ISIM) wanted RESET active for the first 10ns :?
Now it counts and behaves as expected :oops:

Daummmmm i feel like when i learned Basic :?
On a DIY MC6809 w. FLEX OS wayyy back in time.

/Bingo
Attachments
lesson7-tb.pdf.zip
(87.43 KiB) Downloaded 439 times

Bingo600
Newbie Pyro
Posts: 75
Joined: Sat Jun 28, 2014 7:22 am

Re: S3E Lesson7

Postby Bingo600 » Wed Aug 13, 2014 6:56 pm

A bit strange ....

The simulation says i'm 1 off on BCD vs SEG7

Here BCD is 1 , but SEG7 shows "0"
BCD1.png
BCD1.png (182.73 KiB) Viewed 16118 times



Here BCD is 2 , but SEG7 shows "1"
BCD2.png
BCD2.png (183.44 KiB) Viewed 16118 times



Here BCD is 5 , but SEG7 shows "4"
BCD5.png
BCD5.png (183.02 KiB) Viewed 16118 times



I have activated "Reset" for 5ns at the beginning of the "SIM".
See next post :cry: Max 3 attachs"


/Bingo
Last edited by Bingo600 on Wed Aug 13, 2014 7:07 pm, edited 1 time in total.

Bingo600
Newbie Pyro
Posts: 75
Joined: Sat Jun 28, 2014 7:22 am

Re: S3E Lesson7

Postby Bingo600 » Wed Aug 13, 2014 7:02 pm

See start of sim here , where Reset is 1 for 5ns , and BCD & SEG7 are correct ... 0000 and the 7-seg value for "0"

Start-Reset.png
Start-Reset.png (179.68 KiB) Viewed 16118 times



Any hints are welcome ???

Will the somulator change all signals in all proccesses immediately ?
I think so , because it seems like the 1-off is lasting permanently

/Bingo

Bingo600
Newbie Pyro
Posts: 75
Joined: Sat Jun 28, 2014 7:22 am

Re: S3E Lesson7

Postby Bingo600 » Wed Aug 13, 2014 7:24 pm

Hmmmm......

I think i might have the reason or ???

At the excact rising edge of hz_10sync , bcd_value hasn't incremented yet.

But the value of bcd_value is used in the case ..... when assigning the SEG7 bits.

Could that be the reason ?

I do have bcd_value in the sensitivity list of the HC4511: process , but when it changes (later) there is no "rising edge" , and the case
isn't performed ... or ???

/Bingo

Bingo600
Newbie Pyro
Posts: 75
Joined: Sat Jun 28, 2014 7:22 am

Re: S3E Lesson7

Postby Bingo600 » Wed Aug 13, 2014 8:31 pm

Well .....

I tried the assignments outside the process , it didn't help out on the 1-off SEG7 values.

I had to remove the rising_edge from the BCD-7Seg process in order to get the bcd_value and the SEG7 to be in "sync"
It doesn't really matter as bcd_value only changes on the "rising_edge" , and the bcd-7seg "case" can run as much as it wants.

Spookey stuff this HDL :?

Well i learned some testbenching , and the "value of it" ....

The new lesson7 ... With bells and whistles

Code: Select all

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity lesson7 is
   Generic ( osc_freq: natural := 50000000);
   port(
      RESET: in std_logic; --"btn_south" LOC = "K17"
      clk: in std_logic; --50Mhz Clock
      BUTTON: in std_logic; --"btn_west"  LOC = "D18"
      LED_BTN: out std_logic; --LED7
      SEG7: out std_logic_vector(6 downto 0) := "0000000" --LED 6..0
   );
end lesson7;

architecture rtl of lesson7 is
   signal data: std_logic;
   signal bcd_value: std_logic_vector(3 downto 0) := "0000";
   signal bcd_tmp: std_logic_vector(3 downto 0) := "0000";
   signal seg7_tmp: std_logic_vector(6 downto 0) := "0000000";
   signal hz_25m: std_logic :='0';
   signal hz_10: std_logic :='0';
   signal hz_10sync: std_logic :='0';   
   begin

---------------------- Begin 50Mhz to 10Hz Clock divide ---------------------------

-- 50Mhz to 25Mhz predivide
   CLOCK_DIV2: process(clk,RESET)
   begin
   if RESET = '1' then
      hz_25m <= '0';
   elsif rising_edge(clk) then
      hz_25m <= not hz_25m;
   end if;
   end process CLOCK_DIV2;   
   
-- 10HZ Clock   Process
   CLOCK_10HZ: process(hz_25m,RESET)
   VARIABLE ticks:integer range 0 to ((osc_freq/10)/2)-1;
   begin
   if RESET = '1' then
      ticks:=0;
   elsif rising_edge(hz_25m) then
      ticks:=ticks+1;
      if ticks >=(((osc_freq/10)/2)/2)-1 then
         hz_10 <= not hz_10;
         ticks:=0;
      end if;
   end if;
   end process CLOCK_10HZ;

-- 10Hz resync to 50Mhz
   HZ_10_sync: process(clk,hz_10,RESET)
   begin
   if RESET = '1' then
      hz_10sync <= '0';
   elsif rising_edge(clk) then
      hz_10sync <= hz_10;
   end if;
   end process HZ_10_sync;   
   
---------------------- End 50Mhz to 10Hz Clock divide ---------------------------
   
   --First Process
   DATA_REGISTER_0: process(RESET,hz_10sync,BUTTON)
   begin
      if RESET = '1' then
      data <= '0';
      elsif rising_edge(hz_10sync) then
      data <= BUTTON;
      end if;
   end process DATA_REGISTER_0;

   LED_BTN <= data;
   
--Second Process
   TIMER_0: process(RESET,hz_10sync)
   begin
      if RESET = '1' then
      bcd_tmp <= "0000";
      elsif rising_edge(hz_10sync) then
      bcd_tmp <= bcd_tmp + 1;
      end if;
   end process TIMER_0;
   
   bcd_value <= bcd_tmp;
   

-- HC4511 Process   (bcd to 7seg driver)
-- http://www.ti.com/lit/ds/symlink/cd74hc4511.pdf
-- Inspired by http://vhdlguru.blogspot.se/2010/03/vhdl-code-for-bcd-to-7-segment-display.html
-- But changed to "active high" led segments.
--
   HC4511: process(hz_10sync,bcd_value,RESET)
   begin
      if RESET = '1' then
      seg7_tmp <= "1111110";  -- '0'
      else
         case  bcd_value is
            when "0000"=> seg7_tmp <="1111110";  -- '0'
            when "0001"=> seg7_tmp <="0110000";  -- '1'
            when "0010"=> seg7_tmp <="1101101";  -- '2'
            when "0011"=> seg7_tmp <="1111001";  -- '3'
            when "0100"=> seg7_tmp <="0110011";  -- '4'
            when "0101"=> seg7_tmp <="1011011";  -- '5'
            when "0110"=> seg7_tmp <="1011111";  -- '6'
            when "0111"=> seg7_tmp <="1110000";  -- '7'
            when "1000"=> seg7_tmp <="1111111";  -- '8'
            when "1001"=> seg7_tmp <="1111011";  -- '9'
             --nothing is displayed when a number more than 9 is given as input.
            when others=> seg7_tmp <="0000000";
         end case;
      end if;      
   end process HC4511;
   
   SEG7 <= seg7_tmp;
   
end rtl;



Now the 7-seg and the bcd is in sync.

Transition 0 -> 1
1-ok.png
1-ok.png (182.13 KiB) Viewed 16116 times


Transition 1 -> 2
2-ok.png
2-ok.png (181.83 KiB) Viewed 16116 times


Transition 9 -> 10 (blank 7-seg)
9to10-ok.png
9to10-ok.png (170.54 KiB) Viewed 16116 times


/Bingo

Bingo600
Newbie Pyro
Posts: 75
Joined: Sat Jun 28, 2014 7:22 am

Re: S3E Lesson7

Postby Bingo600 » Wed Aug 13, 2014 8:49 pm

What could i have done if i still wanted the bcd-7seg process to only run on the "rising_edge" ... or bcd_value change ?

It seems like when it's triggered (by only rising edge) , the bcd_value haven't changed in the other process.

Could i do a :

Code: Select all

      elsif rising_edge(hz_10sync) || "bcd_value changed" then
         case  bcd_value is


I read somewhere, that a read of a value (signal) inside a process would give the previous assigned value ... or something like that

I'll try a bcd_sync bit.

Hmmm....

I can't seem to get a bcd_sync bit to compile , it says multiple drivers :(


Then again .... Why should the 10Hz have anything to do with the bcd-7seg ....

If i could get it to do a elsif "bcd_value changed" then .... All would be fine.

Well it's fine as it is , as it just behaves as the "HC4511" constantly reacting to the bcd_value.

But what if i encounter a problem where i just want the change when bcd_value has incremented ?
Is it really as easy as ... just having bcd_value and Reset in the sensitivity list ???

Then the process would only execute when one of those has changed ?


/Bingo

ThePyroElectro
PyroElectro Admin
Posts: 1181
Joined: Mon Nov 12, 2007 9:24 pm
Location: Earth
Contact:

Re: S3E Lesson7

Postby ThePyroElectro » Mon Nov 03, 2014 12:00 am

Code: Select all

      elsif rising_edge(hz_10sync) || "bcd_value changed" then
         case  bcd_value is


The tool would likely try to synthesize that as two different global clocks but since bcd_value is a bunch of numbers it won't like that either. Basically it will turn out to be an asynchronous set/reset which could work if it is 1 bit. For example if you built a hardware element to store the previous bcd_value and so there is something to compare it to in order to set an output (interrupt) bit to say things changed.

Most of these issue that's you speak of seem to be clock-domain centric issues that go away when we use MHz speed clocks. Maybe I'm wrong, I honestly didn't go through all of the information you posted above (again due to lack of time, sorry! :( ).

Sorry if i'm too late getting back to you, hope some of this helps :!:


Return to “Introduction to CPLD and FPGA”

Who is online

Users browsing this forum: No registered users and 2 guests