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

    

ТАКТОВЫЙ СИНТЕЗАТОР 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;

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


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

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация