Connect with us

Digital Tachometer VHDL

Discussion in 'General Electronics Discussion' started by tachometer, Mar 25, 2012.

Scroll to continue with content
  1. tachometer

    tachometer

    14
    0
    Mar 25, 2012
    Hi,

    I have this project where I have to design a tachometer using VHDL. The thing is I m pretty new to the field of electronic projects and I m very new to VHDL.
    The project asks me to count the Rotations/per Minute from a motor.
    It has to be in the range 19-98 RPM, the measurement time is 1.1s, and the display resolution is 0.1 .

    The good part is that I dont have to create a system to get this rotations, they are given to me thru a generator. I just have to count the pulses and display the result.
    http://imageshack.us/photo/my-images/546/blockvk.jpg
    So, I tought I'll use an AND gate with the signal from the general as one input and the clock divided so I'll obtain the period of 1.1s .
    http://imageshack.us/photo/my-images/839/clockbg.jpg/

    What I have to do next is when i press a button it will count the pulses for 1.1s and then display the result. [During counting the display will be OFF].

    Sorry for the long post but the first problem resumes to this. How do i design a clock divider so I can get a period of 1.1s.
    I have a basic clock divider code where i count the rising edges and then i change the state of clock. But how many edges i have to count?

    Code:
    ENTITY CLKDIV IS
    PORT(
    CLK: IN STD_LOGIC;
    CLKOUT: OUT STD_LOGIC
    );
    END CLKDIV;
    
    ARCHITECTURE DIV OF CLKDIV IS
    BEGIN
    PROCESS (CLK)
    VARIABLE COUNT: INTEGER RANGE 0 TO ????  :=0;
    VARIABLE STATE: STD_LOGIC := '1'; 
    BEGIN
    IF(RISING_EDGE (CLK)) THEN 
     IF(COUNT=  )THEN
    COUNT:=0;
    STATE:= '1';
    ELSE
    COUNT := COUNT+1;
    END IF;
     IF(COUNT=)
    STATE:= NOT STATE;
    END IF;
    END IF;
    CLKOUT <= STATE; 
    END PROCESS;
    END DIV;
    
     
  2. Harald Kapp

    Harald Kapp Moderator Moderator

    10,396
    2,271
    Nov 17, 2011
    A clock of frequency xxx Hz has xxx cycles per second. So in 1.1 seconds this clock will have No_of_cycles=xxxHz*1.1s. Now that you know the number of clock cycles, you know the denominator (or divisor) for your counter (or clock scaler).

    Although it's been some time I last programmed VHDL, may I suggest you change the architecture of your divider slightly? I would include the state of the pushbutton as one process variable. Then I would look for the state of this button and keep the counter in reset (output of the preocess = "0") until the button is pressed. If the button is pressed, I would change the output of the process to "1" and start counting until 1.1s have passed. During counting the state of the button is ignored, so once the counter starts running, you can release the button or press it without affecting the counting operation. If the counter reaches the llimit as calculated above, bring it back to the reset state, set the process output to "0" and start looking for the state of the button again.
    You can then directly use the output of the counter as one input of the AND gate for counting the RPMs in a second counter.

    Harald
     
  3. tachometer

    tachometer

    14
    0
    Mar 25, 2012
    I thought that if 50MHZ means a 0.2us period,then because 1.s/0.2us =5.5*10^7 I should count 5.5*10^7 rising edges and then change the state to 0. Am I right? Is this gonna get a 0.909 Hertz signal?


    I was about to include the button but in the main process.. now I m just doing the individual blocks.
    CLKDIV, AND, COUNTER (I m gonna use 2 bcd counters one for units and the other for above 9 connected to some MUX ), and the 7 segments Display with Common Anode.
     
    Last edited: Mar 27, 2012
  4. Harald Kapp

    Harald Kapp Moderator Moderator

    10,396
    2,271
    Nov 17, 2011
    1/50 MHz = 20 ns, not 200 ns as you write. But 55*10^6 counts will give you 1.1 s, that's right.

    Harald
     
  5. tachometer

    tachometer

    14
    0
    Mar 25, 2012
    Thank you! I will keep posting my progress. I m pretty sure I am going to have some problems with those BCDs :)
     
  6. tachometer

    tachometer

    14
    0
    Mar 25, 2012
    Is there any faster way to do this?
    Cause the simulation for CLKDIV takes forever. Obviously it has to count to 55 000 000 but i thought it will be a lot faster and I m afraid this will affect my entire system. After i press the button in 1.1 sec I should have a result..
     
  7. Harald Kapp

    Harald Kapp Moderator Moderator

    10,396
    2,271
    Nov 17, 2011
    You shouldn't expect a simulation to run in real time.
    You could use a much slower clock, e.g. 50 kHz and count to 55 000, or 50 Hz and count to 55, as long as this doesn't affect other aspects/functions of your simulation.

    Harald
     
  8. tachometer

    tachometer

    14
    0
    Mar 25, 2012
    It s me again.
    So i've done most of my project. The only problem i have to figure out now it s this.
    So i have a button. When i press the button the system should start and display the result in 1.1s. During this time the display should be off.
    What buggs me its this button. I know i have to use it in my clock divider and to reset my counters but i`m not quite sure how to do so.
    Here is the code i have for the 1.1s high generator.

    entity clkdiv is
    port (
    CLK: in std_logic;
    CLKOUT: out std_logic;
    PB: in std_logic -- state of the button
    );
    end clkdiv;

    architecture DIV of clkdiv is
    begin
    process (CLK, PB)
    variable MAXCOUNT: integer :=5500;
    variable COUNT: integer range 0 to MAXCOUNT :=0 ;
    begin
    if (PB='1') then
    if(rising_edge (CLK)) then
    if(COUNT < MAXCOUNT ) then
    COUNT :=COUNT+1;
    CLKOUT <= '1';
    end if;
    if (COUNT=MAXCOUNT) then
    PUSHBUTTON:= 0;
    COUNT :=0;
    CLKOUT <= '0';
    end if;
    end if;
    else
    COUNT :=0;
    CLKOUT <= '0';
    end if;
    end process;
    end DIV;


    Should the button be an entity itself?

    Thanks.
     
  9. Harald Kapp

    Harald Kapp Moderator Moderator

    10,396
    2,271
    Nov 17, 2011
    As I said, it's been soooome time I last programmed VHDL. But a few things strike me as illogical:

    1) There is PB as an input to your process, but within the process you use PUSHBUTTON and PB without declaring PUSHBUTTON.

    2) The statement if (PB='1') then looks for PB (presumedly the PUSHBUTTON) to be 1. This will work only as long as PB is pressed (1). I don't think it is your intention that the user has to keep the button pressed until 1.1 s are over. I suggest you use an internal state variable, say BUTTON_PRESSED and set this variable initially 0. Then on detecting a rising edge of PB you set BUTTON_PRESSED:=1. The above statement in italics is modified to look for the state variable, not for PB: if (BUTTON_PRESSED='1') then . At the end of the count cycles (1.1 s) you reset BUTTON_PRESSED:=0.
    I think this is the statement
    if (COUNT=MAXCOUNT) then
    PUSHBUTTON:= 0;

    which becomes
    if (COUNT=MAXCOUNT) then
    BUTTON_PRESSED:= 0;

    Don't forget to declare the state variable BUTTON_PRESSED.

    This may not be all you need but it should help you get along. I'm no VHDL expert - I think I repeat myself :)

    Harald
     
  10. tachometer

    tachometer

    14
    0
    Mar 25, 2012
    Yeah, sorry. Thats a mistake from me. I've copied the wrong code.. I've tried different ways that s why there is a PB and a PUSHBUTTON also, in the final code instead of pushbutton it s PB.

    I guess what I'm trying to figure out is that if the state of the button is a signal or a variable. You solution seems excelent. I dont understand yet ". Then on detecting a rising edge of PB " of button but i`ll look into it :) From what you re saying it looks like the button acts as a clock or something :)

    Thanks.
     
  11. Harald Kapp

    Harald Kapp Moderator Moderator

    10,396
    2,271
    Nov 17, 2011
    is essentially the same as detecting a clock edge:
    Harald
     
  12. tachometer

    tachometer

    14
    0
    Mar 25, 2012
    Ok, keep in mind that I m very new to this :)
    I m trying to create the system entity and to connect everything togeter.
    Now, i have this:
    [​IMG]
    http://imageshack.us/photo/my-images/859/schematic.jpg/

    The counters are described in the same entity. Can i instantiate the same entity multiple times? My question is how can i connect all the counters to each MUX?

    Thanks for the help again.

    What I'm thinking is this:
    architecture SYS of System is
    ...

    component BCD_Counter
    port(
    clock: in std_logic;
    reset: in std_logic;
    carry: out std_logic;
    output: out std_logic_vector(0 to 3));
    end component;

    signal IES_01 : std_logic_vector(0 to 3);
    signal IES_1 : std_logic_vector(0 to 3);
    signal IES_10 : std_logic_vector(0 to 3);
    signal Scarry: std_logic;
    signal Scarry1: std_logic;

    counter01: BCD_Counter portmap (clock<=CLK, reset<=RST, carry<=Scarry, out<=IES_01 );
    counter1 : BCD_Counter portmap (clock<=Scarry, reset<=RST, carry<=Scarry1, out<=IES_1 );
    counter10 : BCD_Counter portmap (clock<=Scarry1, reset<=RST, carry<=Carry, out<=IES_10 );

    component mux4 is
    port ( INS: in std_logic_vector (0 to 3);
    EN: in std_logic;
    Sel: in std_logic_vector (0 to 1);
    outmux: out std_logic
    );
    end component;

    signal INS0 : std_logic_vector(0 to 3):= ??? IES_01(0) IES_1(0) IES_10(0) 1 ???
    signal INS1 : std_logic_vector(0 to 3):= ??? IES_01(1) IES_1(1) IES_10(1) 1 ???
    signal INS2 : std_logic_vector(0 to 3):= ??? IES_01(2) IES_1(2) IES_10(2) 1 ???
    signal INS3 : std_logic_vector(0 to 3):= ??? IES_01(3) IES_1(3) IES_10(3) 1 ???


    signal OUTMUXES : std_logic_vector(0 to 3);

    mux1 : mux4 portmap (INS0, EN, Sel, OUTMUXES(0) );
    mux2 : mux4 portmap (INS1, EN, Sel, OUTMUXES(1) );


    .......... :)



    I hope you understand what I m trying to ask.. :)
     
    Last edited: May 7, 2012
  13. tachometer

    tachometer

    14
    0
    Mar 25, 2012
  14. tachometer

    tachometer

    14
    0
    Mar 25, 2012
  15. Harald Kapp

    Harald Kapp Moderator Moderator

    10,396
    2,271
    Nov 17, 2011
    I have no real idea.
    Does this happen at the code loacations you show? Or maybe somewhere else and you have a collision between more than one statement trying to assign conflicting values to the variables?


    Harald
     
  16. tachometer

    tachometer

    14
    0
    Mar 25, 2012
    It happens for every output of this entity.. it gets the '1' s right but instead of '0' it s X.
    I m going to ask one of my teachers today.
     
  17. Harald Kapp

    Harald Kapp Moderator Moderator

    10,396
    2,271
    Nov 17, 2011
    Sorry for not being able to help.
    Would you mind posting the result?


    Harald
     
  18. tachometer

    tachometer

    14
    0
    Mar 25, 2012
    I found what the problem was:
    My code was something like this:

    display: sevseg port map (INM=>sig6, nodisp=>sig1, AtoG=>sigout);
    ....
    if(rotatii<19 or rotatii>98 or (sig5='1')) then
    sigout<= "1111111";
    end if;
    ....


    From what i can tell it didnt like the fact that i was using the same signal sigout and that I was forcing it to '1111111' when the range condition wasnt satisfied.
    so i changed the signals and now it is fine... well almost fine.

    So i have to count the rotations, which it does just fine but if they go out of a range (<19 or >98), then I should close the display. and the problem is that i dont know how to do that.

    process(CLOCK)
    begin

    if(Scarry2='1')then
    sig5<='1';
    end if;
    if(rotatii<19 or rotatii>98 or (sig5='1')) then
    sigout<= "1111111";
    else
    sigout<=sig7;
    end if;

    end process;
    end sys;


    I tried this, where sig7 its the signal I get from the seven segments display and sigout is the signal which controles the leds for display, but this is not a solution because even if I'm in the range sigout it s delayed compared to sig7 because the process it s CLOCK sensitive.

    I really dont know how I m gonna do this :) I ve attached my system.vhd if that s any help.

    Thank you.
     

    Attached Files:

  19. Harald Kapp

    Harald Kapp Moderator Moderator

    10,396
    2,271
    Nov 17, 2011
    Your process is clock sensitive but not edge sensitive:
    There is no reference to the rising clock edge.
    As a guess you may try to insert something like
    into this process and into this process
    This may help, because both processes are now synchronyzed to the rising edge of the clock.
    Harald
     
  20. tachometer

    tachometer

    14
    0
    Mar 25, 2012
    What I did is this: process(CLOCK,RESET, sig7)

    And now, finally my project seems to be working :) Starting tomorrow I m going to do the fpga implementation. My deadline is next friday.

    Thank you Harald for all the help, you made me continue in times when I was about to give up. :) Hope you`ll win the lottery soon as a reward for your kindness . :D
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-