3.9 STEP 8: A BCD-Counter

3.9.1 Synopsis

The desired exposure time and the number of pictures are stored in BCD (Binary Coded Decimal) format. This means that every decimal digit is coded by its binary value. Therefore, two times 4 bits are needed to represent the decimal number '15'. If a binary representation was used, 4 bits would be enough.

While this representation is convenient for the display driver modules, it makes it a lot harder to do the actual counting. A procedure shall be designed that implements a single digit BCD adder with carry. A complete BCD counter is then generated by calling this procedure for each digit of the counter range.

The start of a new exposure is signaled via TIMER_GO. It is not necessary to detect a rising edge as this signal is active for the duration of one clock period, only. When the start signal arrives, the lens shutter has to be opened. The lens shutter remains open as long as the EXPOSE signal is set to '1'. The picture count (NO_PICS) shall be incremented whenever a new picture is taken, i.e. whenever a rising edge of the EXPOSE signal is detected. Additional TIMER_GO signals during the actual exposure of the new picture have to be ignored.

The exposure timer is a bit tricky as only the display values (EXP_TIME) are available as input. It is therefore necessary to map the BCD-values to counter limits. Of course, it would be possible to use a single counter. Yet it is probably more comprehensible to split the task between two counters as all exposure times are a multiple of 1/512 second. At a clock frequency of 8192 Hz this equals 16 clock cycles. These timesteps will be counted by a second counter and will be compared with the counter limits from the mapper.

Please have a look at the module interface before you start to design:

 

The exposure controller

 

3.9.2 Implementation

The VHDL code for the exposure controller

library ieee;
use ieee.std_logic_1164.all;
use work.P_DISPLAY.all;

entity EXP_CTRL is
  port(CLK : in std_ulogic;
       RESET : in std_ulogic;
       TIMER_GO : in std_ulogic;
       EXP_TIME : in T_DIGITS;
       EXPOSE : buffer std_ulogic;
       NO_PICS : buffer T_DIGITS);
end EXP_CTRL;
  • The EXPOSE and NO_PICS signals
    are generated by this module but are
    also read by processes of this entity.
    Therefore, the port mode buffer is used
    which allows the signal to be used as
    input as well. This does not indicate
    that a buffer cell should be placed on
    these ports during synthesis!
architecture RTL of EXP_CTRL is
  signal LIMIT: integer range 0 to 511;




  procedure INC_DIGIT (
    DIGIT : inout integer;
    CARRY : inout std_ulogic) is



  begin
    if CARRY = '1' then


      if DIGIT /= 9 then
        DIGIT := DIGIT + 1;
        CARRY := '0';
      else
        DIGIT := 0;
      end if;        -- OVERFLOW
    end if;          -- CARRY = '1'
  end INC_DIGIT;

begin                -- architecture
  MAPPER: process (EXP_TIME, EXPOSE)
  begin

    LIMIT <= 0;

    if EXPOSE = '0' then
      if    EXP_TIME = (5,1,2) then
        LIMIT <=   0;
      elsif EXP_TIME = (2,5,6) then
        LIMIT <=   1;
      elsif EXP_TIME = (1,2,8) then
        LIMIT <=   3;
      elsif EXP_TIME = (0,6,4) then
        LIMIT <=   7;
      elsif EXP_TIME = (0,3,2) then
        LIMIT <=  15;
      elsif EXP_TIME = (0,1,6) then
        LIMIT <=  31;
      elsif EXP_TIME = (0,0,8) then
        LIMIT <=  63;
      elsif EXP_TIME = (0,0,4) then
        LIMIT <= 127;
      elsif EXP_TIME = (0,0,2) then
        LIMIT <= 255;
      elsif EXP_TIME = (0,0,1) then
        LIMIT <= 511;
      end if;
    end if;
  end process MAPPER;
  • The LIMIT signal will hold the result
    of the mapping from the exposure time
    to the number of 1/512 s timesteps.
  • This procedure implements a single
    BCD digit increment algorithm. The
    digit itself and the carry bit are modi-
    fied "in place", i.e. they have to be of
    mode inout.
  • As the carry bit will be added, the
    operation is carried out only if the
    carry bit is '1'.
  • As long as no overflow occurs, a 1 is
    added to the digit value and the carry
    bit is reset to 0.
  • Else, the result would be 10, i.e. the
    carry bit remains set and the digit
    value is set to 0.
       
  • Abnormal exposure time values shall
    be ignored.
       
  • The mapping algorithm is executed
    whenever the exposure time changes.
    If a new picture is currently taken
    (EXPOSE = '1') the exposure time
    should not be allowed to change.
    Remember that all signals that might
    be read in a pure combinational proc-
    ess must be placed in the sensitivity
    list.
           
  EXP_TIMER: process (CLK, RESET)
    variable COUNT_16: integer
                           range 0 to 15;
    variable TIMER:    integer
                           range 0 to 511;
  begin
    if RESET = '1' then
      COUNT_16 := 0;
      TIMER := 0;
      EXPOSE <= '0';

    elsif (CLK'event and CLK = '1') then
      if EXPOSE = '1' then

        if COUNT_16 /= 15 then
          COUNT_16 := COUNT_16 + 1;
        else
          COUNT_16 := 0;
          if TIMER = LIMIT then
            EXPOSE <= '0';
          else
            TIMER := TIMER + 1;
          end if;
        end if;
      elsif TIMER_GO = '1' then
        EXPOSE <= '1';
        COUNT_16 := 0;
        TIMER := 0;
      end if;
    end if;
  end process EXP_TIMER;
  PIC_COUNT: process(CLK, RESET)
    variable LAST_EXPOSE: std_ulogic;
    variable CARRY: std_ulogic;
    variable DIGIT: integer;

  begin
    if RESET = '1' then
      LAST_EXPOSE := '0';
      NO_PICS <= (0, 0, 0);

    elsif CLK'event and CLK = '1' then
      if EXPOSE      = '1' and
         LAST_EXPOSE = '0' then
        CARRY := '1';
        for I in T_DIGITS'low
              to T_DIGITS'high loop
          DIGIT := NO_PICS(I);
          INC_DIGIT(DIGIT, CARRY);
          NO_PICS(I) <= DIGIT;
        end loop;
      end if;

      LAST_EXPOSE := EXPOSE;
    end if;
  end process PIC_COUNT;
end RTL;
  • The counter of the exposure time is
    split into 2 parts: a divider by 16 in
    order to get the 1/512 s timebase and a
    counter for the number of 1/512 s
    intervals.
 
  • If the exposure timer is currently
    active...
       
  • Wait for the end of another 1/512 s
    interval.
  • Restart the timebase counter.
  • If the counter limit is reached, the
    exposure is terminated, else the coun-
    ter is incremented.
  • Otherwise, if no picture is currently
    being taken, the exposure timer waits
    for the GO signal.
       
  • In order to detect a rising edge of the
    EXPOSE signal, the current value
    must be compared with the last one.
  • The CARRY and DIGIT variables are
    just temporary variables for the BCD
    counter and do not infer Flip Flops.
    Therefore a range specification and a
    reset value are not necessary.
  • If a rising edge of the EXPOSE signal
    is detected, the picture counter is
    incremented. The CARRY bit must be
    set to '1' as initial value for the least
    significant digit.
  • Finally, the current value of the
    EXPOSE signal is stored for later com-
    parison.