Перейти к содержанию
    

ТАКТОВЫЙ СИНТЕЗАТОР LMK03000ISQ

Есть у меня описание работы синтезатора,состоящего из 3-x модулей. RTL-анализ проходит успешно,а вот тестбенч не выдаёт ничего путного. А я в свою очередь не могу понять,в чём проблема, то ли просто тестбенч косячно написал,то ли в описании устройства ошибся.

 

Вот его описание на VHDL:

 

1)ОСНОВНОЙ МОДУЛЬ

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity TOP is
    Port ( clk  : in STD_LOGIC;
           reset: in STD_LOGIC;
           DATAuWire : out STD_LOGIC;
           CLKuWire : out STD_LOGIC;
           LEuWire : out STD_LOGIC
          
    );
end TOP;

architecture Behavioral of TOP is

component spi_interface
Generic(CLK_DIV: integer := 2);
    Port ( clk_20: in STD_LOGIC;                           -- System clk = 20 MHz
           reset_n : in STD_LOGIC;                          -- Reset signal
           start_interface : in STD_LOGIC;                  -- Send data via SPI interface
           data_2write : in STD_LOGIC_VECTOR(31 downto 0);  -- CDCE62005 register content                     
           get_data : inout STD_LOGIC;                        -- Transmit complete, get a new data to interface
           DATAuWire : out STD_LOGIC;                         -- Serial Clock 
           CLKuWire : out STD_LOGIC;                        -- SPI master output signal
           --spi_miso : in STD_LOGIC;                         -- SPI input signal
           LEuWire : out STD_LOGIC);                         -- Latch enable
end component;

component programming_sequence
Port ( clk_20 : in STD_LOGIC;                               -- System clk = 20 MHz
           reset_n : in STD_LOGIC;                              -- Reset signal
           get_data : in STD_LOGIC;                             -- Change register content
           start_interface : out STD_LOGIC;                     -- Send data via SPI interface
           data_2write : out STD_LOGIC_VECTOR (31 downto 0);    -- CDCE62005 register content 
           sync : out STD_LOGIC;                                -- CDCE62005 SYNC#
           power_down : out STD_LOGIC);                         -- CDCE62005 Power Down#
end component;

signal si : std_logic;
signal dw : STD_LOGIC_VECTOR(31 downto 0);
signal gd : std_logic; 

begin
dd1:component programming_sequence port map (clk_20=>clk,reset_n=>reset,get_data=>gd,start_interface=>si,data_2write=>dw);
dd2:component spi_interface        port map (clk_20=>clk,reset_n=>reset,start_interface=>si,data_2write=>dw,get_data=>gd,CLKuWire=>CLKuWire,LEuWire=>LEuWire,DATAuWire=>DATAuWire);

end Behavioral;

 

2)programming_sequence (МОДУЛЬ УПРАВЛЕНИЯ И ПАМЯТИ)

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity programming_sequence is
    Port ( clk_20 : in STD_LOGIC;                               -- System clk = 20 MHz
           reset_n : in STD_LOGIC;                              -- Reset signal
           get_data : in STD_LOGIC;                             -- Change register content
           start_interface : out STD_LOGIC;                     -- Send data via SPI interface
           data_2write : out STD_LOGIC_VECTOR (31 downto 0);    -- CDCE62005 register content 
           sync : out STD_LOGIC;                                -- CDCE62005 SYNC#
           power_down : out STD_LOGIC);                         -- CDCE62005 Power Down#
end programming_sequence;

architecture Behavioral of programming_sequence is
    type statetype is (START, R0, R1, R2, R3, R4, R5, R6, R7, R8, FINISH);
    signal state, nextstate: statetype;
    signal change_state_d, change_state_q: std_logic;   -- Change state trigger
begin

    power_down <= '1';
    
    --State register
    process (clk_20, reset_n) begin
        if reset_n = '1' then
            state <= START;
            change_state_q <= '0';
        elsif rising_edge(clk_20) then
            state <= nextstate;
            change_state_q <= change_state_d;            
        end if;
    end process;
    
    start_interface <= '0' when state = START else ((change_state_d xor change_state_q) and '1');
    
    -- Next state logic
    process (state, get_data) begin
        case state is
            when START =>                   -- Idle state
                nextstate <= R0;
            when R0 =>                      -- Write Register 0
                if get_data = '1' then
                    nextstate <= R1;
                else
                    nextstate <= R0;
                end if;
            when R1 =>                      -- Write Register 1
                if get_data = '1' then
                    nextstate <= R2;
                else
                    nextstate <= R1;
                end if;
            when R2 =>                      -- Write Register 2
                if get_data = '1' then
                    nextstate <= R3;
                else
                    nextstate <= R2;
                end if;
            when R3 =>                      -- Write Register 3
                if get_data = '1' then
                    nextstate <= R4;
                else
                    nextstate <= R3;
                end if;
            when R4 =>                      -- Write Register 4
                if get_data = '1' then
                    nextstate <= R5;
                else
                    nextstate <= R4;
                end if;
            when R5 =>                      -- Write Register 5
                if get_data = '1' then
                    nextstate <= R6;
                else
                    nextstate <= R5;
                end if; 
            when R6 =>                      -- Write Register 6
                if get_data = '1' then
                    nextstate <= R7;
                else
                    nextstate <= R6;
                end if;
            when R7 =>                      -- Write Register 7
                if get_data = '1' then
                    nextstate <= R8;
                else
                    nextstate <= R7;
                end if;
            when R8 =>                      -- Write Register 8
                if get_data = '1' then
                    nextstate <= FINISH;
                else
                    nextstate <= R8;
                end if;
            when FINISH =>                  -- End config
                nextstate <= FINISH;
            when others =>
                nextstate <= START;
        end case;
    end process;
    
    -- Registered output logic
    process (clk_20, state) begin
        sync <= '0';
        change_state_d <= '0';
        case state is
            when START =>
                data_2write <= "11111100000000000000000000000010";
                change_state_d <= '0';
            when R0 =>
                data_2write <= "00000000000000000000000000000000";
                change_state_d <= '1';
            when R1 =>
                data_2write <= "00000000000000000000000000000000";
                change_state_d <= '0';
            when R2 =>
                data_2write <= "00000000000000000000000000000000";
                change_state_d <= '1';
            when R3 =>
                data_2write <= "00000000000000000000000000000000";
                change_state_d <= '0';
            when R4 =>
                data_2write <= "00000000000000000000000000000000";
                change_state_d <= '1';
            when R5 =>
                data_2write <= "00000000000000000000000000000000";
                change_state_d <= '0';
            when R6 =>
                data_2write <= "00000000000000000000000000000000";
                change_state_d <= '1';
            when R7 =>
                data_2write <= "00000000000000000000000000000000";
                change_state_d <= '0';
            when R8 =>
                data_2write <= "00000000000000000000000000000000";
                change_state_d <= '1';
            when FINISH =>
                data_2write <= "00000000000000000000000000000000";
                --change_state_d <= '1';
                sync <= '1';
            when others =>
                data_2write <= "00000000000000000000000000000000";
                change_state_d <= '0';
        end case;
    end process;
end Behavioral;

 

3)spi_interface (ПЕРЕДАЮЩИЙ МОДУЛЬ)

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity spi_interface is
    Generic(CLK_DIV: integer := 2);
    Port ( clk_20: in STD_LOGIC;                           -- System clk = 20 MHz
           reset_n : in STD_LOGIC;                          -- Reset signal
           start_interface : in STD_LOGIC;                  -- Send data via SPI interface
           data_2write : in STD_LOGIC_VECTOR(31 downto 0);  -- CDCE62005 register content                     
           get_data : out STD_LOGIC;                        -- Transmit complete, get a new data to interface
           DATAuWire : out STD_LOGIC;                         -- Serial Clock 
           CLKuWire : out STD_LOGIC;                        -- SPI master output signal
           --spi_miso : in STD_LOGIC;                         -- SPI input signal
           LEuWire : out STD_LOGIC);                         -- Latch enable
end spi_interface;  

architecture Behavioral of spi_interface is
    type statetype is (IDLE, WAIT_HALF, TRANSFER);
    signal state_d, state_q: statetype;
    
    signal data_d, data_q:          STD_LOGIC_VECTOR(31 downto 0);              -- Input data register
    signal CLKuWire_d, CLKuWire_q:    STD_LOGIC_VECTOR(CLK_DIV - 1 downto 0); 
    signal DATAuWire_d, DATAuWire_q:  STD_LOGIC;                                  -- Shift Out SPI data
    signal ctr_d, ctr_q:            STD_LOGIC_VECTOR(4 downto 0);              -- Bit Counter
    signal get_data_d, get_data_q:  STD_LOGIC;                                  -- Transmit complete
begin
    -- Output signal assigment
   DATAuWire <= DATAuWire_q;
    LEuWire   <= '1' when state_q = IDLE else '0';
    get_data <= get_data_q;
    
    -- State register, and memory system 
    process(clk_20, reset_n) begin
        if reset_n = '1' then state_q       <= IDLE;  
                              data_q        <= "11111100000000000000000000000010";
                              CLKuWire_q     <= "00";
                              DATAuWire_q    <= '0';
                              ctr_q         <= "00000";
                              get_data_q    <= '0';
        elsif rising_edge(clk_20) then state_q      <= state_d;
                                       data_q       <= data_d;
                                       CLKuWire_q    <= CLKuWire_d;
                                       DATAuWire_q   <= DATAuWire_d;
                                       ctr_q        <= ctr_d;
                                       get_data_q   <= get_data_d;
        end if;
    end process;
    
    --Next state logic
    process(state_q, start_interface, CLKuWire_q, ctr_q) begin
        state_d     <= state_q;
        data_d      <= data_q;
        CLKuWire_d   <= CLKuWire_q;
        DATAuWire_d  <= DATAuWire_q;
        ctr_d       <= ctr_q;
        get_data_d  <= get_data_q;
        case state_q is
            when IDLE =>
                CLKuWire_d   <= "00";            -- Reset Clock counter
                ctr_d       <= "00000";         -- Reset Bit counter
                if start_interface = '1' then   -- If Start signal is active 
                    data_d  <= data_2write;     -- Load data to register
                    state_d <= WAIT_HALF;       -- Change state on next
                else
                    state_d <= IDLE;            -- Else stay in current state
                end if;
            when WAIT_HALF =>
                CLKuWire_d <= CLKuWire_q + 1;     -- Increment clock counter
                if (CLKuWire_q = "01") then      -- If clock counter if half_full (about to fall)
                    CLKuWire_d <= "00";          -- Reset to 0
                    state_d <= TRANSFER;        -- Change state
                else
                    state_d <= WAIT_HALF;       -- Else stay in current state              
                end if;
            when TRANSFER =>
                CLKuWire_d <= CLKuWire_q + 1;                 -- Increment clock counter
                if (CLKuWire_q = "00") then                  -- If Clock counter is o
                    DATAuWire_d <= data_q(31);               -- Shift out MSB data
                elsif (CLKuWire_q = "01") then               -- Else if it's half full(about to fall)
                    data_d <= (data_q(30 downto 0) & '0');  -- Shift in zero 
                elsif (CLKuWire_q = "11") then               -- Else if it's full(about to rise)
                    ctr_d <= ctr_q + 1;                     -- Increment bit counter
                    if (ctr_q = "11111") then               -- If we are on the last bit
                        state_d <= IDLE;
                        get_data_d <= '1';
                    else
                        state_d <= TRANSFER;                -- Else stay in current state
                    end if;
                end if;
            when others =>
                state_d <= IDLE;
        end case;      
    end process; 
    
    process (clk_20) begin
        if rising_edge(clk_20) then
            case state_q is
                when others => CLKuWire <= '0';
            end case;
        end if;
    end process;

end Behavioral;

 

RTL

 

TOP.jpg

 

ВОТ ТАКИЕ СИГНАЛЫ Я ДОЛЖЕН ПОЛУЧИТЬ

 

CLK.jpg

 

А ВОТ И МОЙ ТЕСТБЕНЧ

 

library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_Std.all;

entity TOP_tb is
end;

architecture bench of TOP_tb is

  component TOP
      Port ( clk  : in STD_LOGIC;
             reset: in STD_LOGIC;
             DATAuWire : out STD_LOGIC;
             CLKuWire : out STD_LOGIC;
             LEuWire : out STD_LOGIC
      );
  end component;

  signal clk: STD_LOGIC;
  signal reset: STD_LOGIC;
  signal DATAuWire: STD_LOGIC;
  signal CLKuWire: STD_LOGIC;
  signal LEuWire: STD_LOGIC;
  
  constant PERIOD : TIME := 100 ns;
  constant DUTY_CYCLE : real := 0.5;
  constant OFFSET : time := 1 ns; 

begin

uut: TOP port map ( clk      => clk,
                      reset    => reset,
                      DATAuWire => DATAuWire,
                      CLKuWire  => CLKuWire,
                      LEuWire   => LEuWire );
                 
clk_gen: PROCESS 
                      BEGIN
                      WAIT for OFFSET;
                      CLOCK_LOOP : LOOP
                      CLK <= '0';
                      WAIT FOR (PERIOD - (PERIOD * DUTY_CYCLE));
                      CLK <= '1';
                      WAIT FOR (PERIOD * DUTY_CYCLE);
                      END LOOP CLOCK_LOOP;
                      END PROCESS; 
                      
   reset<='0';                   
--                      rst_gen: PROCESS 
--                      BEGIN
--                      WAIT for OFFSET;
--                      reset <='1';
--                      wait for period * DUTY_CYCLE *2;
--                      reset <='0';
--                      wait;
--                      END PROCESS;  

end;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В Entitiy spi_interface так и должно быть ?

 

   CLKuWire : out STD_LOGIC;                        -- SPI master output signal

 

    process (clk_20) begin
        if rising_edge(clk_20) then
            case state_q is
                when others => CLKuWire <= '0';
            end case;
        end if;
    end process;

 

Так-же в VHDL совсем не обязательно описывать компонент в области декларации архитектуры.

Можно писать вот так:

    dd1: entity work.programming_sequence 
    port map 
    (
        clk_20          => clk,
        reset_n         => reset,
        get_data        => gd,
        start_interface => si,
        data_2write     => dw
    );

Ну и старайтесь избегать записи в port map в одну строчку. Это делает проект абсолютно не читаемым.

Изменено пользователем Flip-fl0p

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ну по началу было так:

 

process (clk_20) begin
        if rising_edge(clk_20) then
            case state_q is
                when TRANSFER =>
                    spi_clk <= (spi_clk_q(CLK_DIV - 1));
            end case;
        end if;
    end process;

 

но Вивада ругается на такое представление...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ну по началу было так:

 

process (clk_20) begin
        if rising_edge(clk_20) then
            case state_q is
                when TRANSFER =>
                    spi_clk <= (spi_clk_q(CLK_DIV - 1));
            end case;
        end if;
    end process;

 

но Вивада ругается на такое представление...

Добавили бы тогда строчку:

when others => null;

 

Так-же присутствуют ошибки неполного списка чувствительности:

Warning (10492): VHDL Process Statement warning at spi_interface.vhd(67): signal "data_q" is read inside the Process Statement but isn't in the Process Statement's sensitivity list
Warning (10492): VHDL Process Statement warning at spi_interface.vhd(69): signal "DATAuWire_q" is read inside the Process Statement but isn't in the Process Statement's sensitivity list
Warning (10492): VHDL Process Statement warning at spi_interface.vhd(71): signal "get_data_q" is read inside the Process Statement but isn't in the Process Statement's sensitivity list
Warning (10492): VHDL Process Statement warning at spi_interface.vhd(77): signal "data_2write" is read inside the Process Statement but isn't in the Process Statement's sensitivity list
Warning (10492): VHDL Process Statement warning at spi_interface.vhd(93): signal "data_q" is read inside the Process Statement but isn't in the Process Statement's sensitivity list
Warning (10492): VHDL Process Statement warning at spi_interface.vhd(95): signal "data_q" is read inside the Process Statement but isn't in the Process Statement's sensitivity list

 

Изменено пользователем Flip-fl0p

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

ооо,вот тут помогло:

 

process (clk_20) begin
            if rising_edge(clk_20) then
                case state_q is
                    when TRANSFER =>
                        CLKuWire <= (CLKuWire_q(CLK_DIV - 1));
                        when others => null;
                end case;
            end if;
        end process;

 

в тестбенче CLKuWire теперь выдаёт результаты. а вот список чувствительности в принципе ничего не дал

 

process(state_q, start_interface, CLKuWire_q, ctr_q, data_q, DATAuWire_q, get_data_q, data_2write) begin

 

ccc1.jpg

 

ccc2.jpg

 

 

только как мне теперь добиться,чтобы на DATAuWire выдавались данные со всех регистров, а не только с 2х ?

 

Изменено пользователем lyzifer

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

только как мне теперь добиться,чтобы на DATAuWire выдавались данные со всех регистров, а не только с 2х ?

Со всех это с каких ?

Вообще данные выдаются только с одного регистра:

DATAuWire <= DATAuWire_q;

 

Я бы посоветовал сначала:

1. Разобраться с сигналом reset_n. Назван он будто имеет логический уровень "0", о чем говорит общепринятый постфикс _n, а работает по лог. "1". Запутаете себя таким образом.

2. Нужен ли асинхронный reset вообще ?

3. Чем обусловлено применение библиотек:

IEEE.STD_LOGIC_ARITH.ALL;

IEEE.STD_LOGIC_UNSIGNED.ALL;

4. Если у Вас достаточно мощная система для моделирования, можно смело писать список чувствительности вот так: process(all), тогда будет с ним меньше мороки. Но в любом варианте надо разобраться с ним.

5. Переписать автомат на что-то более понятное. Я так и не понял, как он должен работать.

6. Применять понятные обозначения регистров. Ибо среди объявленных сигналов регистр только один:

    signal get_data_d   :  STD_LOGIC                              := '0';                          -- Transmit complete
    signal get_data_q   :  STD_LOGIC                              := '0';                          -- Transmit complete

 

А именно:

signal get_data_q   :  STD_LOGIC                              := '0';                          -- Transmit complete

 

Так и объявляли бы его как :

 signal get_data_reg  :  STD_LOGIC                              := '0';                          -- Transmit complete

 

Тогда, читающим Ваш код было бы существенно проще разобраться с ним. Либо где-то пишите соглашение об именах, чтобы было понятно что сигналы с постфиксом _q - это регистры.

Хотя я считаю, что лучше давать "говорящие" имена, где само название переменной говорит за себя и практически не нуждается в пояснении.

Так-же и сигналы автомата. Не проще их назвать как-нибудь типа press_state и next_state.

Уж очень тяжко понимать такие вот названия

 state_d, state_q: statetype;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...