реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> ТАКТОВЫЙ СИНТЕЗАТОР LMK03000ISQ
lyzifer
сообщение Nov 28 2017, 15:48
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 24
Регистрация: 13-07-17
Пользователь №: 98 133



Есть у меня описание работы синтезатора,состоящего из 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



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



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

Код
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;

Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение Nov 28 2017, 16:19
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 430
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140



В 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 - Nov 28 2017, 16:29
Go to the top of the page
 
+Quote Post
lyzifer
сообщение Nov 28 2017, 16:35
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 24
Регистрация: 13-07-17
Пользователь №: 98 133



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

Код
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;


но Вивада ругается на такое представление...
Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение Nov 28 2017, 16:52
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 430
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140



Цитата(lyzifer @ Nov 28 2017, 19:35) *
ну по началу было так:

Код
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 - Nov 28 2017, 16:58
Go to the top of the page
 
+Quote Post
lyzifer
сообщение Nov 29 2017, 15:37
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 24
Регистрация: 13-07-17
Пользователь №: 98 133



Цитата(Flip-fl0p @ Nov 28 2017, 19:52) *


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

Код
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






Цитата(Flip-fl0p @ Nov 28 2017, 19:52) *


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


Сообщение отредактировал lyzifer - Nov 29 2017, 15:35
Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение Nov 30 2017, 05:33
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 430
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140



Цитата(lyzifer @ Nov 29 2017, 18:37) *
только как мне теперь добиться,чтобы на 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;
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 13th December 2017 - 20:55
Рейтинг@Mail.ru


Страница сгенерированна за 0.01352 секунд с 7
ELECTRONIX ©2004-2016