Still newbie question : Dialog between states machines.

Discussion in 'VHDL' started by Fred Bartoli, Jan 30, 2004.

  1. Fred Bartoli

    Fred Bartoli Guest

    Hello,

    I have 2 fsm that are clocked on different and asynchronous clocks.

    The first INSTR_fsm (clocked on CPLD_EXEC) executes some commands issued on
    a serial bus. Basically it updates different registers.

    The second GATING_fsm (clocked on Ck1600kHz) drives some signals for a fast
    acquisition process.

    In GATING_fsm I have a Hold_St where the acquired value is held and I wait
    for the measurement to be completed by an external ADC (slow) before going
    to the StartIntegrate_St or StartGate_St state for another measurement
    cycle.
    The state transition to StartIntegrate_St or StartGate_St is triggered by a
    software acknowledge sent to the INSTR_fsm.
    So basically what I have to do is have a MeasReaf flag ff that is set by the
    GATING_fsm when entering the Hold_St state, used as a condition still in
    GATING_fsm and is reset in CMD_fsm on a special command.

    How can I do that in behavioral description ? I mean I'm an hardware guy
    and I've tried hard to stay away from what is my first inclination, i.e.
    thinking in hardware, so as to have good code clarity...

    Oh, strong constrain is the final CPLD size : I can only afford 64MC thanks
    to package size.

    I also welcome any comment/suggestion about the programming style...

    Thanks very much for your time.

    Fred.


    Here's the code :



    -- **************************************************************
    -- Serial communication register
    -- **************************************************************
    LIBRARY ieee;
    USE ieee.std_logic_1164.ALL;
    USE ieee.numeric_std.ALL;

    ENTITY Ser2Par is
    generic ( WIDTH : integer := 8 );
    port (
    Clk : in std_logic;
    SerIn : in std_logic;
    ParOut : out std_logic_vector ( WIDTH-1 downto 0);
    SerOut : out std_logic
    );
    END Ser2Par;

    ARCHITECTURE behv of Ser2Par is
    constant clockEdge : std_logic := '1';
    signal Q : std_logic_vector(WIDTH-1 downto 0);

    BEGIN
    --------------------------------------------------------------------------
    ----
    shr: process(Clk)
    --------------------------------------------------------------------------
    ----
    begin
    if (Clk = clockEdge and Clk'event) then
    Q <= SerIn & Q(WIDTH-1 downto 1);
    end if;
    end process shr;
    --------------------------------------------------------------------------
    ----
    ParOut <= Q;
    SerOut <= Q(0);
    END behv;


    -- **************************************************************
    -- Gating counter
    -- **************************************************************
    LIBRARY ieee;
    USE ieee.std_logic_1164.ALL;
    USE ieee.numeric_std.ALL;

    ENTITY PRBS_10 is
    Port (
    Clk : in std_logic;
    Load : in std_logic;
    Input : in std_logic_vector (9 downto 0);
    EndCount: out std_logic );
    END PRBS_10;

    ARCHITECTURE behv of PRBS_10 is
    signal Q: std_logic_vector (9 downto 0);
    BEGIN
    --------------------------------------------------------------------------
    ----
    counter: process(Clk, Load, Input)
    --------------------------------------------------------------------------
    ----
    variable Count : std_logic_vector (9 downto 0);
    begin
    if Load = '1' then
    Count := Input ;
    elsif (Clk='0' and Clk'event) then
    Count := Q(8 downto 0) & (Q(9) xor Q(6)) ;
    end if;
    Q <= Count;
    end process counter;
    --------------------------------------------------------------------------
    ----
    EndCount <= '1' when Q = b"1111111111" else '0';
    END behv;


    -- **************************************************************
    -- Clock predivider
    -- **************************************************************
    LIBRARY ieee;
    USE ieee.std_logic_1164.ALL;
    USE ieee.numeric_std.ALL;

    ENTITY Ck100K_div is
    Port (
    Clk : In std_logic;
    Rst : In std_logic;
    CkDiv : Out std_logic
    );
    END Ck100K_div;

    ARCHITECTURE behavior of Ck100K_div is
    BEGIN
    --------------------------------------------------------------------------
    ----
    counter: process(Clk, Rst)
    --------------------------------------------------------------------------
    ----
    variable Count: Natural range 0 to 15;
    begin
    if (Rst = '1') then
    count := 0;
    elsif falling_edge(Clk) then -- Count is advanced by 1/2 clock cycle to
    account for the
    count := (count+1) mod 16; -- gating state machine 1 cycle delay when
    stopping counting.
    end if;

    if (Count >= 8) then
    CkDiv <= '1';
    else
    CkDiv <= '0';
    end if;
    end process counter;
    --------------------------------------------------------------------------
    ----
    END behavior;


    -- **************************************************************
    -- CPLD instance
    -- **************************************************************
    --library metamor;
    --use metamor.attributes.all;
    LIBRARY ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;

    ENTITY CPLD is
    port (
    Ck_1600KHz : in std_logic := '0';
    GATE_TRIG : in std_logic := '0';
    CPLD_EXEC : in std_logic := '0';
    SER_DATA : in std_logic := '0';
    SER_CLK : in std_logic := '0';


    CPLD_DATA : out std_logic;
    CPU_REQ : out std_logic;
    CalGen_Clk : out std_logic;
    CalGen_Dat : out std_logic;
    PRESET_ENABLE : out std_logic;
    nCOS_HOLD_P : out std_logic;
    nCOS_HOLD_M : out std_logic;
    nSIN_HOLD_P : out std_logic;
    nSIN_HOLD_M : out std_logic;
    nIF_SAMPLE : out std_logic;

    TEMP_A : out std_logic_vector(2 downto 0);
    PRESET_A : out std_logic_vector(1 downto 0)
    );

    -- attribute pinnum of Ck_1600KHz : signal is "37";
    -- attribute pinnum of GATE_TRIG : signal is "12";
    -- attribute pinnum of CPLD_EXEC : signal is "2";
    -- attribute pinnum of SER_DATA : signal is "11";
    -- attribute pinnum of SER_CLK : signal is "10";
    --
    -- attribute pinnum of CPLD_DATA : signal is "3";
    -- attribute pinnum of CPU_REQ : signal is "5";
    -- attribute pinnum of CalGen_Clk : signal is "33";
    -- attribute pinnum of CalGen_Dat : signal is "34";
    -- attribute pinnum of PRESET_ENABLE: signal is "19";
    -- attribute pinnum of nCOS_HOLD_P : signal is "18";
    -- attribute pinnum of nCOS_HOLD_M : signal is "22";
    -- attribute pinnum of nSIN_HOLD_P : signal is "23";
    -- attribute pinnum of nSIN_HOLD_M : signal is "25";
    -- attribute pinnum of nIF_SAMPLE : signal is "27";
    --
    -- attribute pinnum of TEMP_A : signal is "31,30,28";
    -- attribute pinnum of PRESET_A : signal is "21,20";

    END CPLD;

    ARCHITECTURE structure of CPLD is
    use work.all;
    use work.IF_CPLD_types.all;

    signal GateLoadBus : std_logic_vector ( 9 downto 0);
    signal SerComBus : op;
    alias SerComParm1 : std_logic is SerComBus(0);
    alias SerComParm1_2 : std_logic is SerComBus(1);
    alias SerComParm1_3 : std_logic is SerComBus(2);
    alias SerComParm2 : std_logic_vector (1 downto 0) is SercomBus (1 downto
    0);
    alias SerComParm3 : std_logic_vector (2 downto 0) is SercomBus (2 downto
    0);
    signal Internal_100kHz_Clk : std_logic; -- internal 100KHz clock
    signal CalEnable : std_logic;
    signal GatingEnable : std_logic;
    signal GateCounterLoad : std_logic;
    signal GateEnd : std_logic; -- Pulses when Gatecounter ends.
    signal PresetOn : std_logic; -- PresetEnable default states
    signal PresetMode : std_logic;
    signal PresetGating : std_logic; --
    signal RstCalDiv : std_logic; -- Resets the 100kHz clock divider

    signal SinHold_P : std_logic;
    signal SinHold_M : std_logic;
    signal CosHold_P : std_logic;
    signal CosHold_M : std_logic;
    signal IFsample : std_logic;
    signal Integrate : std_logic;
    signal MeasRead : std_logic;

    type GatingStates is (StartIntegrate_St, StartGate_St, Hold_St,
    WaitTrig_St, Count_St);
    signal GatingState : GatingStates;


    BEGIN
    nSIN_HOLD_P <= not SinHold_P;
    nSIN_HOLD_M <= not SinHold_M;
    nCOS_HOLD_P <= not CosHold_P;
    nCOS_HOLD_M <= not CosHold_M;
    nIF_SAMPLE <= IFsample;


    -- *************************************
    -- Microcontroler interface
    SerialComm: entity Ser2Par port map ( Clk=>SER_CLK, SerIn=>SER_DATA,
    ParOut=>SerComBus, SerOut=>CPLD_DATA);


    -- *************************************
    -- Gating system
    GateCounter: entity PRBS_10 port map (Clk=>Internal_100kHz_Clk ,
    Load=>GateCounterLoad, Input=>GateLoadBus, EndCount=> GateEnd);


    -- *************************************
    -- Dividing and synchronizing the 1.6MHz clock for calibration generator and
    Gate counter clocking.
    CalClk_div: entity Ck100K_div port map (Clk=>Ck_1600KHz, Rst=> RstCalDiv,
    CkDiv=>Internal_100kHz_Clk );
    CalGen_Dat <= CalEnable and Internal_100kHz_Clk;
    CalGen_Clk <= NOT Ck_1600KHz;


    -- *************************************
    -- Instruction process state machine
    --------------------------------------------------------------------------
    ----
    instr_fsm : process (CPLD_EXEC)
    --------------------------------------------------------------------------
    ----
    type Instr_state is (InstrFetch_St,LoadGateCountFetch_St);
    variable Instr_St : Instr_state;
    variable CurrentOp : op;

    begin
    if rising_edge(CPLD_EXEC) then
    CurrentOp := SerComBus and op_mask;

    -- op_LoadGateCount
    case Instr_St is
    when InstrFetch_St =>
    case CurrentOp is
    when op_LoadGateCount =>
    Instr_St := LoadGateCountFetch_St;
    GateLoadBus (9 downto 8) <= SerComParm2;

    when op_LoadTempChannel =>
    TEMP_A <= SerComParm3;

    when op_LoadPresetChannel =>
    PRESET_A <= SerComParm2;
    PresetOn <= SerComParm1_3;

    when op_EnablePresetMode =>
    -- PresetMode <= SerComParm1_2;

    when op_ReadStatus =>
    null;

    when op_EnableCalibration =>
    CalEnable <= SerComParm1;

    when op_EnableGating =>
    GatingEnable <= SerComParm1;

    when op_MeasRead =>
    MeasRead <= '1';

    when op_Integrate =>
    Integrate <= SerComParm1;

    when others =>
    null;

    end case;

    when LoadGateCountFetch_St =>
    Instr_St := InstrFetch_St;
    GateLoadBus (7 downto 0) <= SerCombus;

    end case;
    end if;
    end process;



    -- *************************************
    -- Gating handling state machine
    --------------------------------------------------------------------------
    ----
    Gating_fsm: process (Ck_1600KHz, GatingEnable, CalEnable)
    --------------------------------------------------------------------------
    ----
    -- type GatingStates is (StartIntegrate_St, StartGate_St, Hold_St,
    WaitTrig_St, Count_St);
    variable Gating_St : GatingStates;
    -- variable GatingState : GatingStates;
    variable Sampling : std_logic;
    variable xHold : std_logic;

    begin
    if (GatingEnable = '0') then -- (continuous sampling mode)
    Gating_St := StartIntegrate_St;
    RstCalDiv <= not CalEnable;
    GateCounterLoad <= '0';
    -- PresetGating <= PresetOn; --'0';
    PRESET_ENABLE <= PresetOn;

    SinHold_P <= '0'; -- Averaging mode for all the outputs
    SinHold_M <= '0';
    CosHold_P <= '0';
    CosHold_M <= '0';
    IFSample <= '1'; -- (continuous sampling)

    elsif rising_edge(Ck_1600KHz) then -- (gated sampling mode)
    case Gating_St is
    when StartIntegrate_St =>
    if GATE_TRIG = '1' then
    Gating_St := WaitTrig_St;
    end if;

    when StartGate_St =>
    if GATE_TRIG = '1' then
    Gating_St := WaitTrig_St;
    end if;

    when WaitTrig_St =>
    if GATE_TRIG = '0' then
    Gating_St := Count_St;
    end if;

    when Count_St =>
    if GateEnd = '1' then
    Gating_St := Hold_St;
    end if;

    when Hold_St =>
    if MeasRead = '1' then
    if Integrate = '1' then
    Gating_St := StartIntegrate_St;
    else
    Gating_St := StartGate_St;
    end if;
    end if;

    when others =>
    Gating_St := StartIntegrate_St;
    end case;

    case Gating_St is
    when StartIntegrate_St =>
    GateCounterLoad <= '1'; -- Load the PRBS counter
    RstCalDiv <= '1'; -- Stop the 100kHz gate counter clock
    Sampling := '0';
    PRESET_ENABLE <= '0';
    xHold := '0';
    MeasRead <= '0';
    -- PresetGating <= '1';

    when StartGate_St =>
    GateCounterLoad <= '1'; -- Load the PRBS counter
    RstCalDiv <= '1'; -- Stop the 100kHz gate counter clock
    Sampling := '0';
    PRESET_ENABLE <= '1';
    xHold := '1';
    MeasRead <= '0';
    -- PresetGating <= '1';

    when WaitTrig_St =>
    GateCounterLoad <= '0'; -- Release it and wait for trigger
    Sampling := '0';
    PRESET_ENABLE <= '0';
    xHold := '1';
    -- PresetGating <= '0';

    when Count_St =>
    RstCalDiv <= '0'; -- Allow internal 100kHz clock for gate count
    Sampling := '1';

    when Hold_St =>
    GateCounterLoad <= '1'; -- Load the PRBS counter
    RstCalDiv <= '1'; -- Stop the 100kHz gate counter clock
    Sampling := '0';
    PRESET_ENABLE <= '1';
    xHold := '1';
    -- PresetGating <= '1';

    end case;
    SinHold_P <= Sampling; -- Average mode for all the outputs during gate
    sampling
    SinHold_M <= Sampling;
    CosHold_P <= Sampling;
    CosHold_M <= Sampling;
    IFSample <= not Sampling; -- (Sample)

    GatingState <= GatingStates'val(GatingStates'pos(Gating_St)); -- Just to
    show correct SM states
    end if;
    end process;

    --PRESET_ENABLE <= (PresetGating and GatingEnable) or ((not GatingEnable)
    and PresetOn) ;

    END structure;
     
    Fred Bartoli, Jan 30, 2004
    #1
    1. Advertising

  2. Fred Bartoli wrote:

    > I have 2 fsm that are clocked on different and asynchronous clocks.

    .. . .
    > How can I do that in behavioral description ? I mean I'm an hardware guy
    > and I've tried hard to stay away from what is my first inclination, i.e.
    > thinking in hardware, so as to have good code clarity...


    It is possible to do both.
    I could tell you more if you post your package IF_CPLD_types.
    Is this working code, or a first cut?

    Your biggest need is not code clarity, but synchronization.
    Consider using a single entity CPLD containing two processes:
    serial: process(reset, SER_CLK) and
    parallel: process(reset, Ck_1600KHz)

    All of your other top "clocks" become
    inputs to one of these processes.

    -- Mike Treseler
     
    Mike Treseler, Jan 30, 2004
    #2
    1. Advertising

  3. Fred Bartoli

    Fred Bartoli Guest

    "Mike Treseler" <> a écrit dans le message de news:
    ...
    > Fred Bartoli wrote:
    >
    > > I have 2 fsm that are clocked on different and asynchronous clocks.

    > . . .
    > > How can I do that in behavioral description ? I mean I'm an hardware

    guy
    > > and I've tried hard to stay away from what is my first inclination, i.e.
    > > thinking in hardware, so as to have good code clarity...

    >
    > It is possible to do both.
    > I could tell you more if you post your package IF_CPLD_types.
    > Is this working code, or a first cut?
    >
    > Your biggest need is not code clarity, but synchronization.
    > Consider using a single entity CPLD containing two processes:
    > serial: process(reset, SER_CLK) and
    > parallel: process(reset, Ck_1600KHz)
    >
    > All of your other top "clocks" become
    > inputs to one of these processes.
    >
    > -- Mike Treseler



    Hello Mike,

    thanks for the input.

    No this code is not a (still) working code but I hope to succeed soon. That
    one was a first cut and also my very first attempt to code in VHDL, hence
    all the "errors". This is for a small (64MC) Atmel CPLD that I first wanted
    to code with their demo tools (wincupl then prochip designer cupl) but both
    proved to be the worst useless engineering bugware joke I've ever seen.
    Fortunately the prochipdes VHDL compiler seems to work OK and the demo
    version doesn't time out and is just OK for my project size so I'm using it
    with Sonata for code development and simulation (with also some annoying
    bugs but nothing is perfect). That's probably not very optimal but it's for
    a pretty huge homebrewed project and all my money has to go to the hardware
    so it's OK to me.


    I was not sure what you meant by :
    > Consider using a single entity CPLD containing two processes:
    > serial: process(reset, SER_CLK) and
    > parallel: process(reset, Ck_1600KHz)


    and I had a lot of questions but I decided first to blindly follow your
    advice hoping it'll shed some light and indeed it did to a great extend.

    I then have tried lots of coding options, like where to hang the PRBS and
    CkDivcounter so as to minimize the hardware..., and the one I ended with
    reaches the smallest size I can achieve.
    I've enclosed it at the end. Will you care having a look at it and telling
    me wether it's what you had in thought ?
    Is there some (obvious or maybe less obvious) way to further reduce the
    logic ? (I still have to add some features and don't want to grow in CPLD
    size).

    As per yourequest I've also added the IF_CPLD_types package but it has
    nothing special : just opcodes definitions.

    Thanks again for your help.
    Fred.



    -- **************************************************************
    -- CPLD instance
    -- **************************************************************
    --library metamor;
    --use metamor.attributes.all;
    LIBRARY ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;

    ENTITY CPLD is
    port (
    Ck_1600KHz : in std_logic := '0';
    GATE_TRIG : in std_logic := '0';
    CPLD_EXEC : in std_logic := '0';
    SER_DATA : in std_logic := '0';
    SER_CLK : in std_logic := '0';


    CPLD_DATA : out std_logic;
    CPU_REQ : out std_logic;
    CalGen_Clk : out std_logic;
    CalGen_Dat : out std_logic;
    PRESET_ENABLE : out std_logic;
    nCOS_HOLD_P : out std_logic;
    nCOS_HOLD_M : out std_logic;
    nSIN_HOLD_P : out std_logic;
    nSIN_HOLD_M : out std_logic;
    nIF_SAMPLE : out std_logic;

    TEMP_A : out std_logic_vector(2 downto 0);
    PRESET_A : out std_logic_vector(1 downto 0)
    );

    -- attribute pinnum of Ck_1600KHz : signal is "37";
    -- attribute pinnum of GATE_TRIG : signal is "12";
    -- attribute pinnum of CPLD_EXEC : signal is "2";
    -- attribute pinnum of SER_DATA : signal is "11";
    -- attribute pinnum of SER_CLK : signal is "10";
    --
    -- attribute pinnum of CPLD_DATA : signal is "3";
    -- attribute pinnum of CPU_REQ : signal is "5";
    -- attribute pinnum of CalGen_Clk : signal is "33";
    -- attribute pinnum of CalGen_Dat : signal is "34";
    -- attribute pinnum of PRESET_ENABLE: signal is "19";
    -- attribute pinnum of nCOS_HOLD_P : signal is "18";
    -- attribute pinnum of nCOS_HOLD_M : signal is "22";
    -- attribute pinnum of nSIN_HOLD_P : signal is "23";
    -- attribute pinnum of nSIN_HOLD_M : signal is "25";
    -- attribute pinnum of nIF_SAMPLE : signal is "27";
    --
    -- attribute pinnum of TEMP_A : signal is "31,30,28";
    -- attribute pinnum of PRESET_A : signal is "21,20";

    END CPLD;

    ARCHITECTURE structure of CPLD is
    use work.all;
    use work.IF_CPLD_types.all;

    -- signal GateLength : std_logic_vector ( 9 downto 0);
    signal SerCom : op;
    alias Opcode : op is SerCom;
    alias Param1 : std_logic is Opcode(0);
    alias Param1_2 : std_logic is Opcode(1);
    alias Param1_3 : std_logic is Opcode(2);
    alias Param2 : std_logic_vector (1 downto 0) is Opcode(1 downto 0);
    alias Param3 : std_logic_vector (2 downto 0) is Opcode(2 downto 0);
    alias Param8 : std_logic_vector (7 downto 0) is Opcode;
    signal Internal_100kHz_Clk : std_logic; -- internal 100KHz clock
    signal CalEnable : std_logic;
    signal GatingEnable : std_logic;
    signal PresetOn : std_logic; -- PresetEnable default states
    -- signal PresetMode : std_logic;
    -- signal PresetGating : std_logic; --
    -- signal RstCalDiv : std_logic; -- Resets the 100kHz clock divider

    signal SinHold_P : std_logic;
    signal SinHold_M : std_logic;
    signal CosHold_P : std_logic;
    signal CosHold_M : std_logic;
    signal IFsample : std_logic;
    signal Integrate : std_logic;
    -- signal HoldMeas : std_logic;

    signal PRBS_sig : std_logic_vector(9 downto 0);
    -- signal PRBS_Count : std_logic_vector(9 downto 0);

    type GatingStates is (StartIntegrate_St, StartGate_St, Hold_St,
    WaitTrig_St, Count_St);
    signal GatingState : GatingStates;


    BEGIN


    -- *************************************
    -- Microcontroler interface
    --------------------------------------------------------------------------
    ----
    CPLD_DATA <= SerCom(0);

    shr: process(SER_CLK)
    --------------------------------------------------------------------------
    ----
    begin
    if rising_edge(SER_CLK) then
    SerCom <= SER_DATA & SerCom(7 downto 1);
    end if;
    end process shr;
    --------------------------------------------------------------------------
    ----




    -- *************************************
    -- Dividing and synchronizing the 1.6MHz clock for calibration generator
    and Gate counter clocking.
    CalGen_Dat <= Internal_100kHz_Clk when CalEnable = '1' else '0' ;
    CalGen_Clk <= NOT Ck_1600KHz;




    --------------------------------------------------------------------------
    ----
    Parallel: process (Ck_1600KHz, CPLD_EXEC, Internal_100kHz_Clk, PresetOn,
    CalEnable, GatingEnable)
    --------------------------------------------------------------------------
    ----
    type Instr_state is (InstrFetch_St, LoadGateCountFetch_St);
    variable Instr_St : Instr_state;
    variable CurrentOp : op;

    -- type GatingStates is (StartIntegrate_St, StartGate_St, Hold_St,
    WaitTrig_St, Count_St);
    variable Gating_St : GatingStates;
    variable Sampling : std_logic;
    variable xHold : std_logic;
    variable CkDivCount : Natural range 0 to 15;
    variable PRBS_Count : std_logic_vector(9 downto 0);
    variable GateEnd : std_logic; -- Pulses when Gatecounter ends.
    -- variable GateCounterLoad : std_logic;
    variable HoldMeas : std_logic;
    variable AllowPreset : std_logic;
    variable GateLength : std_logic_vector ( 9 downto 0);
    begin

    -- *************************************
    -- Instruction process state machine
    --------------------------------------------------------------------------
    ----
    if rising_edge(CPLD_EXEC) then
    CurrentOp := Opcode and op_mask;

    case Instr_St is
    when InstrFetch_St =>
    case CurrentOp is
    when op_LoadGateCount =>
    Instr_St := LoadGateCountFetch_St;
    GateLength (9 downto 8) := Param2;

    when op_LoadTempChannel =>
    TEMP_A <= Param3;

    when op_LoadPresetChannel =>
    PRESET_A <= Param2;
    PresetOn <= Param1_3;

    when op_EnablePresetMode =>
    -- PresetMode <= Param1_2;

    when op_ReadStatus =>
    null;

    when op_EnableCalibration =>
    CalEnable <= Param1;

    when op_EnableGating =>
    GatingEnable <= Param1;

    when op_MeasRead =>
    HoldMeas := '0'; -- Clear the flag after software acquired the Meas.

    when op_Integrate =>
    Integrate <= Param1;

    when others =>
    null;

    end case;

    when LoadGateCountFetch_St =>
    Instr_St := InstrFetch_St;
    GateLength (7 downto 0) := Param8;

    when others =>
    null;

    end case;

    end if;
    --------------------------------------------------------------------------
    ----



    -- *************************************
    -- 100KHz clock predivider
    if falling_edge(Ck_1600KHz) then
    if Gating_St = WaitTrig_St then
    CkDivcount := 0;
    else
    CkDivCount := (CkDivCount+1) mod 16;
    end if;
    end if;
    if (CkDivCount >= 8) then
    Internal_100kHz_Clk <= '1';
    else
    Internal_100kHz_Clk <= '0';
    end if;


    -- *************************************
    -- Gating handling state machine
    --------------------------------------------------------------------------
    ----
    if (GatingEnable = '0') then -- (continuous sampling mode)
    Gating_St := StartIntegrate_St;
    AllowPreset := '1';
    HoldMeas := '0';
    Sampling := '1';
    PRBS_Count := (others=>'0');

    GatingState <= Gating_St;
    xHold := '0';
    SinHold_P <= '0'; -- Averaging mode for all the outputs
    SinHold_M <= '0';
    CosHold_P <= '0';
    CosHold_M <= '0';
    IFSample <= '1'; -- (continuous sampling)

    elsif rising_edge(Ck_1600KHz) then -- (gated sampling mode)

    -- CkDivCount := (CkDivCount+1) mod 16;

    case Gating_St is
    when StartIntegrate_St =>
    if GATE_TRIG = '1' then
    Gating_St := WaitTrig_St;
    end if;

    when StartGate_St =>
    if GATE_TRIG = '1' then
    Gating_St := WaitTrig_St;
    end if;

    when WaitTrig_St =>
    if GATE_TRIG = '0' then
    Gating_St := Count_St;
    end if;

    when Count_St =>
    if PRBS_Count = b"1111111111" then
    Gating_St := Hold_St;
    end if;

    when Hold_St =>
    if HoldMeas = '0' then -- Meas has been done and the CPU cleared the
    flag.
    if Integrate = '1' then
    Gating_St := StartIntegrate_St;
    else
    Gating_St := StartGate_St;
    end if;
    end if;

    when others =>
    null;
    end case;

    case Gating_St is
    when StartIntegrate_St =>
    Sampling := '0';
    xHold := '0';
    AllowPreset := '0';

    when StartGate_St =>
    Sampling := '0';
    xHold := '1';
    AllowPreset := '1';

    when WaitTrig_St =>
    -- CkDivCount := 15; -- Resets the 100kHz gate counter clock (better
    done outside)
    PRBS_Count := GateLength ; -- Initialize gate length
    Sampling := '0';
    xHold := '1';
    AllowPreset := '0';

    when Count_St =>
    if CkDivCount = 15 then -- counts one IF clock cycle
    PRBS_Count := PRBS_Count(8 downto 0) & (PRBS_Count(9) xor
    PRBS_Count(6)) ;
    end if;
    Sampling := '1';
    xHold := Integrate;

    when Hold_St =>
    HoldMeas := '1'; -- Holds the result until software clears the flag
    Sampling := '0';
    xHold := '1';
    AllowPreset := '0';

    when others =>
    null;
    end case;

    SinHold_P <= xHold; -- Average mode for all the outputs during gate
    sampling
    SinHold_M <= xHold;
    CosHold_P <= xHold;
    CosHold_M <= xHold;
    IFSample <= Sampling; -- (Sample)

    GatingState <= GatingStates'val(GatingStates'pos(Gating_St)); -- Just to
    show correct SM states
    end if;
    --------------------------------------------------------------------------
    ----

    PRESET_ENABLE <= (AllowPreset and GatingEnable) or ((not GatingEnable) and
    PresetOn) ;

    end process;

    nSIN_HOLD_P <= not SinHold_P;
    nSIN_HOLD_M <= not SinHold_M;
    nCOS_HOLD_P <= not CosHold_P;
    nCOS_HOLD_M <= not CosHold_M;
    nIF_SAMPLE <= not IFsample;


    END structure;



    ******************************************************
    ******************************************************


    package IF_CPLD_types is

    subtype op is std_logic_vector(7 downto 0);
    constant op_mask : op := X"F8";



    constant op_LoadTempChannel : op := X"00"; -- 0 0 O 0 0 T2 T1 T0
    -- with T2 T1 T0 : Temp channel to select
    constant op_LoadPresetChannel : op := X"10"; -- 0 0 O 1 0 En P1 P0
    -- with P1 P0 : Preset channel to select
    constant op_EnablePresetMode : op := X"20"; --
    constant op_LoadGateCount : op := X"30"; -- 0 0 1 1 0 0 G9 G8
    -- G7 G6 G5 G4 G3 G G1 G0
    constant op_ReadStatus : op := X"40";
    constant op_EnableCalibration : op := X"50"; -- 0 1 O 1 0 0 0 En
    constant op_EnableGating : op := X"60"; -- 0 1 1 0 0 0 0 En
    constant op_PresetCal : op := X"70"; -- 0 1 1 1 0 0 C1 C0
    -- C1 C0 : channel to calibrate
    constant op_MeasRead : op := X"80"; -- Clear HoldMeasure flag
    constant op_Integrate : op := X"90"; -- 1 0 O 1 0 0 0 En
    -- constant op_ : op := X"";
    -- constant op_ : op := X"";
    -- constant op_ : op := X"";
    -- constant op_ : op := X"";
    -- constant op_ : op := X"";
    -- constant op_ : op := X"";
    -- constant op_ : op := X"";

    end IF_CPLD_types;

    package body IF_CPLD_types is
    end IF_CPLD_types;
     
    Fred Bartoli, Feb 5, 2004
    #3
  4. Fred Bartoli wrote:

    > I was not sure what you meant by :
    >
    >>Consider using a single entity CPLD containing two processes:
    >>serial: process(reset, SER_CLK) and
    >>parallel: process(reset, Ck_1600KHz)


    All wires crossing clock domains must be synchronized.
    Limiting the design to two domains will minimize this problem.
    Best case would be running everything on the fastest clock.
    Limiting the number of processes is just style.
    I prefer one-liners for counters, shifters etc.


    > I've enclosed it at the end. Will you care having a look at it and telling
    > me wether it's what you had in thought ?


    OK, I'll scan thru here.
    It looks to me like you've paid some dues.
    When you have a working testbench, I'll look again.


    > Is there some (obvious or maybe less obvious) way to further reduce the
    > logic ? (I still have to add some features and don't want to grow in CPLD
    > size).


    Don't worry about that until you have a working sim.
    It's easier to chop things out when you can tell
    if your code is broken or not.

    > As per yourequest I've also added the IF_CPLD_types package but it has
    > nothing special : just opcodes definitions.


    Well, it allowed me to run a sim compile.
    The reason this:
    GatingState := GatingStates'val(GatingStates'pos(Gating_St));

    didn't compile was your use of <= instead of :=
    >
    > -- **************************************************************
    > -- CPLD instance
    > -- **************************************************************
    > --library metamor;
    > --use metamor.attributes.all;
    > LIBRARY ieee;
    > use ieee.std_logic_1164.all;
    > use ieee.numeric_std.all;


    well done.


    >
    > shr: process(SER_CLK)


    can't afford a reset?

    > --------------------------------------------------------------------------
    > ----
    > Parallel: process (Ck_1600KHz, CPLD_EXEC, Internal_100kHz_Clk, PresetOn,
    > CalEnable, GatingEnable)


    I thought Ck_1600KHz was your system clock. This should be

    Parallel: process (CPLD_EXEC);

    to match > if rising_edge(CPLD_EXEC) then



    > -- *************************************
    > -- 100KHz clock predivider
    > if falling_edge(Ck_1600KHz) then
    > if Gating_St = WaitTrig_St then



    No. you only get one edge per process.
    Where does Ck_1600KHz : in std_logic come from?

    -- Mike Treseler
     
    Mike Treseler, Feb 5, 2004
    #4
  5. Fred Bartoli

    Fred Bartoli Guest

    Thanks again Mike,
    Comments, answers and questions follows.


    "Mike Treseler" <> a écrit dans le message de news:
    ...

    > >>Consider using a single entity CPLD containing two processes:
    > >>serial: process(reset, SER_CLK) and
    > >>parallel: process(reset, Ck_1600KHz)

    >
    > All wires crossing clock domains must be synchronized.


    Yep, metastability and all that stuff... but in my case the very short
    resources of the CPLD made me think twice to this and the cost of 2 FFs is
    high in my case. I finally choosed to carefully examine and assume the
    consequences of a metastable event. These could only occur on special
    occasions and will (should), at worst, just imply one Ck_1600kHz cycle delay
    which will be of no consequence when arriving. This of course unless I've
    overlooked something important.


    > Limiting the design to two domains will minimize this problem.
    > Best case would be running everything on the fastest clock.
    > Limiting the number of processes is just style.


    I agree and the mess of my first attempt came from that I first implemented
    the hardware I new I needed, then tried to connect them... In fact I think I
    was trying to use VHDL like ABEL, CUPL. Of course not the right way but I
    must say that my domain of expertise is analog and I just did CPLDs on
    occasions, to debug someone else production.


    <>
    > When you have a working testbench, I'll look again.
    >


    I didn't expected you'll go to the trouble of running the code. That's why I
    have not included the testbench which I have "developped" with the CPLD
    code. In fact this is more a quick and dirty environment that evolved with
    the needs of the CPLD portion to be tested than something with a rigorous
    structure and doesn't respond to any industrial needs, i.e. I just have
    inputs generation and no output tests for example (too much trouble at this
    time).
    Anyway, I'll include it at the end, and also the commands input file for it.


    >
    > > Is there some (obvious or maybe less obvious) way to further reduce the
    > > logic ? (I still have to add some features and don't want to grow in

    CPLD
    > > size).

    >
    > Don't worry about that until you have a working sim.
    > It's easier to chop things out when you can tell
    > if your code is broken or not.
    >


    I have a working sim, and also a great concern about the size : I already
    have the board designed, have to know wether the chossen package size is OK,
    and also have to balance some functionnalities between the CPLD and a small
    onboard uC that'll interpret some high level commands from the main CPU and
    translate them to a list of low level commands for the CPLD.
    I also feel a strong need to learn in any aspect of good VHDL coding as I
    know that my design will probably just fit with the 64MC and I don't want to
    restart coding again and again... This is may look slower at the beginning
    but will make me win some time later. I'll also have other CPLDs to develop,
    .... and the main reason is probably that I've always done like this with
    good fortune, so...


    > > As per yourequest I've also added the IF_CPLD_types package but it has
    > > nothing special : just opcodes definitions.

    >
    > Well, it allowed me to run a sim compile.
    > The reason this:
    > GatingState := GatingStates'val(GatingStates'pos(Gating_St));
    >
    > didn't compile was your use of <= instead of :=



    Hmm, it worked form me. I have such a signal declared at the top level.
    Maybe you had some pb with the hyphen lines wrapping (there's also a
    commented out GatingState variable). BTW the reason of this is a work around
    to display Gating_St for what I think is a Sonata bug with variable display.
    Then the signal is triped by the compiler as the signal is not used
    anywhere.



    > >
    > > -- **************************************************************
    > > -- CPLD instance
    > > -- **************************************************************
    > > --library metamor;
    > > --use metamor.attributes.all;
    > > LIBRARY ieee;
    > > use ieee.std_logic_1164.all;
    > > use ieee.numeric_std.all;

    >
    > well done.
    >
    >
    > >
    > > shr: process(SER_CLK)

    >
    > can't afford a reset?
    >


    I don't know thanks to the size constrain. I have planned to rely on the
    onboard uC to do startup reset for all the parts that need it.
    When the design will be finished and will fit in, then I'll add all the
    hardware resets needed if it fits in.



    >

    --------------------------------------------------------------------------
    > > ----
    > > Parallel: process (Ck_1600KHz, CPLD_EXEC, Internal_100kHz_Clk,

    PresetOn,
    > > CalEnable, GatingEnable)

    >
    > I thought Ck_1600KHz was your system clock. This should be
    >
    > Parallel: process (CPLD_EXEC);
    >
    > to match > if rising_edge(CPLD_EXEC) then
    >
    >


    Ha ha, I think all that needs some clearing about the design so there's no
    misunderstanding.

    So :
    The purpose of the CPLD is to manage the switches of a synchronous detector
    and to provide different measurement methods (normal = averaging, averaged
    time gated with output preset for fast acquisition, integrating). There are
    also different calibration modes and some other minor things like
    temperature monitoring chanel selection.

    For the clocks there's one system reference clock (Ck_1600kHz) from which is
    derived an external 100Khz IF (intermediate frequency) reference clock which
    is resynchronized on board for the switches (no CPLD involved 'til this).
    Then I have only one true system clock for the CPLD : Ck_1600kHz. All the
    critical signals from the CPLD are then externally resynchronized to the
    Ck_1600kHz.

    Other clocking signals are :
    * SER_CLK : generated from the uC. Used for shifting the registers of the
    serial data bus link.
    * CPLD_EXEC : generated from the uC. Just one pulse at the end of each
    serial word to execute the pending command.
    * Internal_100kHz_Clk : a reconstructed 100Khz IF clock, synchronous to the
    external reference one (synchronized through GATE_TRIG) and used to count a
    number (GateLength) of full IF cycles. It's done because it's easier to
    bring an harmonic signal of the IF ref clock than the ref clock itself (the
    If detector is ultra sensitive on its IF 100kHz ref frequency but is totally
    insensitive to even harmonics of the IF 100kHz ref clock).

    The onboard uC clock is asynchrone of Ck_1600kHz, so SER_DATA, SER_CLK and
    CPLD_EXEC are signals of the uC clock domain, and Ck_1600kHz and GATE_TRIG
    of the system clock domain. Also for the speed of the serial link I strongly
    prefer the SER_DATA, SER_CLK and CPLD_EXEC signals not to be sampled by the
    Ck_1600kHz clock.



    >
    > > -- *************************************
    > > -- 100KHz clock predivider
    > > if falling_edge(Ck_1600KHz) then
    > > if Gating_St = WaitTrig_St then

    >
    >
    > No. you only get one edge per process.
    > Where does Ck_1600KHz : in std_logic come from?
    >


    Why can't I ? These FFs are an entirely different set of FFs from the ones
    clocked one the Ck_1600kHz rising edge and also the CPLD_EXEC rising edge.
    At least the code simulates fine and the synthetizer compiles fine and
    infers FFs where I intended it to do and the fitter netlist does show what I
    expected to see. So I'm a bit confused... Do I miss something ?
    The reason, for me, to do this is that the Internal_100kHz_clk is used by
    the gating_fsm which is clocked by the rising edge so it is perfectly stable
    when used.

    Also the reason I thought it was clever from you to put both clock domains
    into one process was that the HoldMeas FF is shared and *updated* by both
    sides. With the 2 processes of my first "design" I could only succeed to
    handle this with 2 FFs, one from one side for signaling and another from the
    other side for acknowledging. Works OK but it costs too much.


    But the picture is now confusing (my lack of experience in this domain) or
    perhaps is it the informations a gave above that where missing to you to ?

    Thanks for clearing me.
    Fred.



    Here's the test bench, followed by a command file to copy in a "CPLDCMD.txt"
    file.

    ***********************************************************************
    -- Run this bench for 500 us
    -- *******************************************
    -- Serial commands generation for the CPLD
    --
    -- *******************************************
    LIBRARY ieee;
    USE ieee.std_logic_1164.ALL;
    USE ieee.numeric_std.ALL;
    USE std.textio.all;

    LIBRARY synopsys;
    USE synopsys.std_logic_textio.all;

    entity CPU_Cmd_block is
    generic (
    WIDTH : integer := 8;
    duty : real := 50.0;
    Tc : time := 100 ns
    );
    port (
    rst : in std_logic := '0';
    SendSeq : in std_logic;

    SerOut : out std_logic;
    SerClk : out std_logic;
    CpldExec: out std_logic
    );
    END CPU_Cmd_block;

    ARCHITECTURE behv of CPU_Cmd_block is
    constant clockEdge : std_logic := '0';
    constant BitsPerWord : integer := 8;
    file CmdFile : text;

    BEGIN
    file_open(CmdFile,"CPLDCMD.txt",READ_MODE);


    CPLDDriver : process
    type fsm_state is (IDLE_St, SEND_St, END_St, READLINE_St);
    variable Ser : std_logic;
    variable fsm_stateM : fsm_state;
    variable bit_count : integer;
    variable Word : std_logic_vector(WIDTH-1 downto 0);
    variable ByteToSend : std_logic_vector(WIDTH-1 downto 0);
    variable line_in,
    line_out : Line;

    begin

    case fsm_stateM is
    when IDLE_St =>
    CpldExec<= '0';
    SerClk <= '0';
    if SendSeq = '1' then
    fsm_stateM := READLINE_St;
    end if;

    when READLINE_St =>
    if not endfile(CmdFile) then
    readline(CmdFile, line_in);
    hread(line_in, ByteToSend);
    Word := ByteToSend;
    bit_count := 0;
    if ByteToSend = X"FF" then -- suspend reading
    fsm_StateM := IDLE_St;
    elsif ByteToSend = X"FC" then
    fsm_StateM := END_St;
    else
    fsm_StateM := SEND_St;
    end if;
    else
    fsm_StateM := END_St;
    end if;

    when SEND_St =>
    if bit_count >= BitsPerWord then
    CpldExec<= '1', '0' after Tc*Duty/100.0;
    fsm_stateM := READLINE_St;
    else
    SerOut <= Word(0);
    Word := '0' & Word(WIDTH-1 downto 1);
    bit_count := bit_count + 1;
    SerClk<= '1' after Tc*Duty/100.0, '0' after Tc;
    end if;

    when END_St =>
    file_close(CmdFile);
    SerClk <= '0';
    wait;
    end case;

    wait for Tc;
    end process;
    END behv;



    --****************************************************************
    --
    -- TestBench definition
    --****************************************************************
    LIBRARY ieee;
    USE ieee.std_logic_1164.ALL;
    USE ieee.numeric_std.ALL;

    ENTITY IF_CPLD_TB is
    end IF_CPLD_TB;

    ARCHITECTURE struct of IF_CPLD_TB is
    use work.all;
    signal SerClk : std_logic;
    signal SerData : std_logic;
    signal CpldExec: std_logic;
    signal word : std_logic_vector(7 downto 0);
    signal SendSeq : std_logic;
    signal HF_clk : std_logic;
    signal Gate_Trig : std_logic;

    BEGIN

    Ck1600k :process
    begin
    HF_clk <= '1', '0' after 312.5 ns;
    wait for 625 ns;
    end process;

    GateTrig :process
    begin
    Gate_Trig <= '0' , '1' after 27 us, '0' after 29.8 us;
    wait for 250 us; --150 us;
    end process;

    Send: process -- send bytes sequences to the CPLD
    begin
    SendSeq <= '0', '1' after (1 us), '0' after 3 us;
    wait for 100 us;
    loop
    SendSeq <= '1', '0' after 200 ns;
    wait for 15 us;
    end loop;
    wait;
    end process;

    WordGen : entity CPU_Cmd_block port map (SerClk => SerClk, SendSeq =>
    SendSeq, SerOut => SerData, CpldExec=>CpldExec);

    IF_CPLD : entity CPLD port map (SER_CLK => SerClk, SER_DATA=> SerData,
    CPLD_EXEC=>CpldExec,
    Ck_1600KHz => HF_clk,
    GATE_TRIG => Gate_Trig);

    END struct;



    CPLDCMD.txt file. (starts right at the "60 Disable..." line. Do not include
    the ***line)
    ***********************************************************************
    60 Disable gating (normal mode)
    10 Load Preset channel 0
    07 load Temp channel 7
    14 Enable OutputPreset
    00 load Temp channel 0
    10 Load Preset channel 0
    60 Disable gating (normal mode)
    50 Enable calibration
    33 Load Gatecount = 38F
    8f
    91 Integrate
    80 MeasRead
    61 Enable gating
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    00
    80 MeasRead
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    80
    FC Close file
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    11
    FF
    12
    FF
    13
    FF
    10
    FF
    *************************************************
     
    Fred Bartoli, Feb 6, 2004
    #5
  6. Fred Bartoli wrote:

    > Yep, metastability and all that stuff...


    It's "that stuff" that's the bigger problem.
    With a two flop synchronizer you're good for a lifetime.
    With a one flop synchronizer you may be good for years.
    With no synchronization, races will bite you every few minutes,
    as data setup sweeps through the full range.


    > I agree and the mess of my first attempt came from that I first implemented
    > the hardware I new I needed, then tried to connect them... In fact I think I
    > was trying to use VHDL like ABEL, CUPL. Of course not the right way but I
    > must say that my domain of expertise is analog and I just did CPLDs on
    > occasions, to debug someone else production.


    Using TTL sized entities is a fine way to
    get started, but it is quite verbose.

    > I didn't expected you'll go to the trouble of running the code.


    It takes far less time to run working a working testbench
    than it does to visually parse non-working code.


    > In fact this is more a quick and dirty environment that evolved with
    > the needs of the CPLD portion to be tested than something with a rigorous
    > structure and doesn't respond to any industrial needs, i.e. I just have
    > inputs generation and no output tests for example (too much trouble at this
    > time).


    All test benches start this way. You don't need to close
    the loop until everything is working.

    > Anyway, I'll include it at the end, and also the commands input file for it.


    I'll take a look at it at lunch time.

    > I have a working sim, and also a great concern about the size : I already
    > have the board designed, have to know wether the chossen package size is OK,
    > and also have to balance some functionnalities between the CPLD and a small
    > onboard uC that'll interpret some high level commands from the main CPU and
    > translate them to a list of low level commands for the CPLD.


    Consider having the CPU do everything it is fast enough to handle.
    Unless you've done this same board before, the odds are the
    the it will have to be spun for one reason or another before your through.

    > I also feel a strong need to learn in any aspect of good VHDL coding as I
    > know that my design will probably just fit with the 64MC and I don't want to
    > restart coding again and again... This is may look slower at the beginning
    > but will make me win some time later. I'll also have other CPLDs to develop,
    > ... and the main reason is probably that I've always done like this with
    > good fortune, so...


    I agree with your outlook. The first outing with an HDL is not
    going to save you any time over schematic entry, especially with
    a small design. The big win is in simulating code at your desk
    vs clipping little probes all over the board at the bench.



    > Hmm, it worked form me. I have such a signal declared at the top level.
    > Maybe you had some pb with the hyphen lines wrapping (there's also a
    > commented out GatingState variable).


    Yes, I probably uncommment that.

    > BTW the reason of this is a work around
    > to display Gating_St for what I think is a Sonata bug with variable display.


    The free version of Sonata doesn't display variables.

    >>can't afford a reset?


    > I don't know thanks to the size constrain. I have planned to rely on the
    > onboard uC to do startup reset for all the parts that need it.
    > When the design will be finished and will fit in, then I'll add all the
    > hardware resets needed if it fits in.


    It's fine to have the reset come from the cpu. Especially
    if it's on the same clock.


    > The purpose of the CPLD is to manage the switches of a synchronous detector
    > and to provide different measurement methods (normal = averaging, averaged
    > time gated with output preset for fast acquisition, integrating). There are
    > also different calibration modes and some other minor things like
    > temperature monitoring chanel selection.


    Cut and paste the text above as comments at the top of your architecture.

    > For the clocks there's one system reference clock (Ck_1600kHz) from which is
    > derived an external 100Khz IF (intermediate frequency) reference clock which
    > is resynchronized on board for the switches (no CPLD involved 'til this).
    > Then I have only one true system clock for the CPLD : Ck_1600kHz. All the
    > critical signals from the CPLD are then externally resynchronized to the
    > Ck_1600kHz.


    In that case, consider using Ck_1600kHz as your only clock.
    Generate different "clock enables" for each process running
    at a slower speed. See:
    http://groups.google.com/groups?q=clock enable vhdl if end

    > Other clocking signals are :
    > * SER_CLK : generated from the uC. Used for shifting the registers of the
    > serial data bus link.
    > * CPLD_EXEC : generated from the uC. Just one pulse at the end of each
    > serial word to execute the pending command.
    > * Internal_100kHz_Clk : a reconstructed 100Khz IF clock, synchronous to the
    > external reference one (synchronized through GATE_TRIG) and used to count a
    > number (GateLength) of full IF cycles. It's done because it's easier to
    > bring an harmonic signal of the IF ref clock than the ref clock itself (the
    > If detector is ultra sensitive on its IF 100kHz ref frequency but is totally
    > insensitive to even harmonics of the IF 100kHz ref clock).


    These all become clock enables. Add text as comments.
    >
    > The onboard uC clock is asynchrone of Ck_1600kHz, so SER_DATA, SER_CLK and
    > CPLD_EXEC are signals of the uC clock domain, and Ck_1600kHz and GATE_TRIG
    > of the system clock domain. Also for the speed of the serial link I strongly
    > prefer the SER_DATA, SER_CLK and CPLD_EXEC signals not to be sampled by the
    > Ck_1600kHz clock.


    OK, if uC clock is faster than 1600kHz, use that as your main clock, and
    make a synchronous pulse at the 1600kHz rate.

    >>> -- 100KHz clock predivider
    >>> if falling_edge(Ck_1600KHz) then
    >>> if Gating_St = WaitTrig_St then

    >>
    >>
    >>No. you only get one edge per process.
    >>Where does Ck_1600KHz : in std_logic come from?


    > Why can't I ?


    Now that I look at your code, I don't even see that
    bit any more.
    I like to make all processes look like this:


    -----------------------------------------
    process(reset,clock) is
    -- declare local variables, functions, procedures here
    begin
    if (reset='1') then
    -- asynch reset assignments
    elsif rising_edge(clock) then
    if(enable='1') then
    -- synchronous reset statements
    -- sequential statement ( <=, :=, if, case, for etc.)
    -- sequential statement ( <=, :=, if, case, for etc.)
    -- sequential statement ( <=, :=, if, case, for etc.)
    -- sequential statement ( <=, :=, if, case, for etc.)
    end if;
    -- must make assignments ( <= ) to at least one
    -- entity port (directly or indirectly)
    -- to avoid a null synthesis.
    end if;
    end process;
    -----------------------------------------------

    I'll have a look at the sim. and get back.

    -- Mike Treseler
     
    Mike Treseler, Feb 6, 2004
    #6
  7. Mike Treseler wrote:

    > I'll have a look at the sim. and get back.


    Fred, your sim ran ok for me.
    Like you said, not everything is hooked up
    and synced up, but it does run.

    Here's how modelsim sees your processes:
    http://home.comcast.net/~mike_treseler/detector.pdf

    I expect that this whole controller could be
    run from the cpu constant clock.
    I assume that the cpu clk is several
    times faster than your ser_clk bursts.

    ser_clk and ser_data would become inputs
    to a synchronous process that shifts out
    a ser_data bit every time ser_clk is high
    and the previous ser_clk was low.

    Here's one way to do this:
    http://groups.google.com/groups?q=vhdl ck_rising

    -- Mike Treseler
     
    Mike Treseler, Feb 7, 2004
    #7
  8. Fred Bartoli

    Fred Bartoli Guest

    "Mike Treseler" <> a écrit dans le message news:
    ...
    > Mike Treseler wrote:
    >
    > > I'll have a look at the sim. and get back.

    >
    > Fred, your sim ran ok for me.
    > Like you said, not everything is hooked up
    > and synced up, but it does run.
    >
    > Here's how modelsim sees your processes:
    > http://home.comcast.net/~mike_treseler/detector.pdf
    >
    > I expect that this whole controller could be
    > run from the cpu constant clock.
    > I assume that the cpu clk is several
    > times faster than your ser_clk bursts.
    >
    > ser_clk and ser_data would become inputs
    > to a synchronous process that shifts out
    > a ser_data bit every time ser_clk is high
    > and the previous ser_clk was low.
    >
    > Here's one way to do this:
    > http://groups.google.com/groups?q=vhdl ck_rising
    >
    > -- Mike Treseler


    I've now implemented almost all of the logic, the sync pb apart, and have
    come short of CPLD ressources, but I've coded it... crudely first to check
    some ideas. I have to polish all this.

    Also I now have a better understanding of the synchronisation pb and some
    solutions and have to think to all this.

    However that's now time for a week off :)

    I'll get back when more advanced/almost finished, but I'm somewhat afraid
    about the CPLD size.

    Thanks,
    Fred.
     
    Fred Bartoli, Feb 7, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Yttrium
    Replies:
    7
    Views:
    2,558
    Yttrium
    Oct 15, 2003
  2. Edwin Knoppert

    Maintain Treeview's expand states between pages

    Edwin Knoppert, Nov 7, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    602
    Edwin Knoppert
    Nov 7, 2005
  3. bill turner

    newbie: xfer files between machines

    bill turner, Oct 20, 2005, in forum: Java
    Replies:
    6
    Views:
    439
  4. Vinodh Kumar P
    Replies:
    1
    Views:
    348
    Jack Klein
    Dec 12, 2003
  5. Don Taylor
    Replies:
    5
    Views:
    611
    Don Taylor
    Feb 22, 2006
Loading...

Share This Page