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

Обращаюсь к знатокам VHDL

Всем добрый день! Появились проблемы при разработке протокола Modbus для slave на VHDL, ПЛИС фирмы Xilinx XC6SLX9. Сам код:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity newmodbus is
port (clk    : in std_logic;
       ce    : in std_logic;
       ena_rx: out std_logic;--выход разрешения приема данных
       re     : in std_logic;--строб чтения байта
       data_rx: in std_logic_vector(7 downto 0);--байт данных        
        
       ena_tx: out std_logic;--выход разрешения приема данных
       wr     : in std_logic;--строб передачи байта
      data_tx    : out std_logic_vector(7 downto 0);        
      done     : in std_logic;
      r00, r01, r02                 : in std_logic_vector(15 downto 0);--регистры Modbus 
      r03, r04, r05, r06, r07 : inout std_logic_vector(15 downto 0);--регистры Modbus        
      r08, r09, r0a, r0b, r0c, r0d, r0e, r0f, r10, r11, r12, r13, r14, r15, r16, r17 : in std_logic_vector(15 downto 0);--регистры Modbus
      r18, r19, r1a, r1b, r1c, r1d, r1e, r1f, r20, r21, r22, r23, r24, r25, r26, r27, r28, r29 : inout std_logic_vector(15 downto 0) --регистры Modbus
        );        
end newmodbus;

architecture Behavioral of newmodbus is
type ram_type is array (0 to 100) of std_logic_vector(7 downto 0);


signal rxx        : ram_type:=(others =>(others => '0'));--значение регистров Modbus
signal dat_tx    : ram_type:=(others =>(others => '0'));--данные для передачи
signal dat_rx    : ram_type:=(others =>(others => '0'));--принимаемые данные

signal code        : std_logic_vector(0 to 7):= (others => '0');--код функции

signal crc16    : std_logic_vector(15 downto 0):= (others => '0');--контрольная сумма CRC16
signal crcrx    : std_logic_vector(15 downto 0):= (others => '0');
signal crctx    : std_logic_vector(15 downto 0):= (others => '0');
signal crc        : std_logic_vector(15 downto 0):= (others => '0');

signal inc_rx    : std_logic_vector(7 downto 0):= (others => '0');--счетчик принимаемых байтов
signal nrx        : std_logic_vector(7 downto 0):= (others => '0'); --количество принимаемых байт
signal inc_tx    : std_logic_vector(7 downto 0):= (others => '0');--счетчик передаваемых байтов
signal ntx        : std_logic_vector(7 downto 0):= (others => '0');--количество передаваемых байт

signal state    : std_logic_vector(1 downto 0):=(others => '0');--состояние блока Modbus
signal inc_d    : std_logic_vector(7 downto 0):= (others => '0');
signal del1     : std_logic_vector(1 downto 0):= (others => '0');
signal del2     : std_logic_vector(1 downto 0):= (others => '0');

constant addr    : std_logic_vector:=x"01";--адрес устройства
--CRC16 
function crc_rs(dat : ram_type; n : std_logic_vector)                                                   
        return std_logic_vector is                            
variable flag    : std_logic;
variable reg     : std_logic_vector(0 to 15):=x"ffff";
variable r        : std_logic_vector(0 to 15);
begin        
    for j in 0 to 100 loop    
        reg(8 to 15) := reg(8 to 15) xor dat(j);        
        for i in 0 to 7 loop
            flag := reg(15);        
            reg := '0' & reg(0 to 14); 
            if flag = '1' then
                reg := reg xor x"a001"; 
            end if;
        end loop;
        exit when j = n;
    end loop;
    r := reg(8 to 15) & reg(0 to 7);
    return (r);    
end function crc_rs;
--
procedure dis(signal di : in ram_type;
      signal do : out ram_type;
      signal m : in std_logic_vector(7 downto 0);
      signal n : in std_logic_vector(7 downto 0))is
begin
    for j in 0 to 93 loop    
        do(3+j) <= di(conv_integer(m+m)+j);
        exit when j = (n+n-1);
    end loop;
end dis;
--
begin

--состояние сигнала state
--0 - прием
--1 - обработка данных
--2 - передача данных

pro:process (clk)
    begin        
        if clk'event and clk = '1' then
            --rx
            if conv_integer(state) = 0 then
                if re = '1' then
                    dat_rx(conv_integer(inc_rx)) <= data_rx;                
                    if conv_integer(inc_rx) = 7 then
                        state <= conv_std_logic_vector(1,2);                        
                        inc_rx <= conv_std_logic_vector(0,8);
                        else inc_rx <= inc_rx + 1;
                    end if;
                end if;
            end if;
            --
            if conv_integer(state) = 1 then
                --прверка контрольной суммы принятых данных
                nrx <= x"05";        
                crcrx <= crc_rs(dat_rx, nrx); --расчет CRC
                crc <= dat_rx(6) & dat_rx(7);
                if conv_integer(del1) = 3 then                                
                    if crcrx = crc then    --проверка принятого и расчетного CRC
                    --адрес устройства                
                        if dat_rx(0) = addr then
                            --код фунукции    
                            case dat_rx(1) is
                                when x"03" => --получение текущего значения регистров                                
                                    dat_tx(0) <= x"01";
                                    dat_tx(1) <= x"03";                        
                                    dat_tx(2) <= dat_rx(5)+dat_rx(5);                                    
                                    dis(rxx, dat_tx, dat_rx(3), dat_rx(5));                                    
                                    ntx <= dat_rx(5)+dat_rx(5);                                    
                                    crctx <= crc_rs(dat_tx, ntx); --расчет CRC                                 
                                    if conv_integer(del2) = 3 then
                                        del2 <= conv_std_logic_vector(0,2);
                                        del1 <= conv_std_logic_vector(0,2);                                        
                                        dat_tx(conv_integer(dat_rx(5)+dat_rx(5))+3) <= crctx(15 downto 8);
                                        dat_tx(conv_integer(dat_rx(5)+dat_rx(5))+4) <= crctx(7 downto 0);
                                        state <= conv_std_logic_vector(2,2);
                                        else del2 <= del2 + 1;
                                    end if;
                                when x"06" => --запись нового значения в регистр
                                    rxx(conv_integer(dat_rx(3)+dat_rx(3)) to (conv_integer(dat_rx(3)+dat_rx(3))+1)) <= dat_rx(4 to 5);                                    
                                    dat_tx(0) <= addr;
                                    dat_tx(1) <= x"06";                        
                                    dat_tx(2) <= dat_rx(2);
                                    dat_tx(3) <= dat_rx(3);
                                    dat_tx(4) <= dat_rx(4);
                                    dat_tx(5) <= dat_rx(5);
                                    ntx <= x"05";                                
                                    crctx <= crc_rs(dat_tx, ntx); --расчет CRC
                                    if conv_integer(del2) = 3 then
                                        del2 <= conv_std_logic_vector(0,2);
                                        del1 <= conv_std_logic_vector(0,2);                                        
                                        dat_tx(6) <= crctx(15 downto 8);
                                        dat_tx(7) <= crctx(7 downto 0);
                                        state <= conv_std_logic_vector(2,2);
                                        else del2 <= del2 + 1;
                                    end if;                
                                when others => state <= conv_std_logic_vector(0,2);--принятый код функции не может быть обработан
                            end case;
                            else state <= conv_std_logic_vector(0,2);
                        end if;
                        else state <= conv_std_logic_vector(0,2);
                    end if;
                    else del1 <= del1 + 1;
                end if;
            end if;
            --tx
            if conv_integer(state) = 2 then
                if wr = '1' then
                    data_tx <= dat_tx(conv_integer(inc_tx));                
                    if inc_tx = (ntx + 2) then--учет двух байтов контрольной суммы
                        inc_tx <= conv_std_logic_vector(0,8);                
                        else inc_tx <= inc_tx +1;
                    end if;                                        
                end if;
                if done = '1' then
                    if conv_integer(inc_d) = (ntx + 2) then
                        state <= conv_std_logic_vector(0,2);
                        inc_d <=conv_std_logic_vector(0,8);
                        else inc_d <= inc_d +1;
                    end if;
                end if;
            end if;            
        end if;
    end process pro;
    
    r03 <= crctx;   r04<= rxx(8)&rxx(9);   r05<= rxx(10)&rxx(11); r06<= rxx(12)&rxx(13); r07<= rxx(14)&rxx(15);
    r18 <= rxx(48)&rxx(49); r19<= rxx(50)&rxx(51); r1a<= rxx(52)&rxx(53); r1b<= rxx(54)&rxx(55); r1c<= rxx(56)&rxx(57);
    r1d <= rxx(58)&rxx(59); r1e<= rxx(60)&rxx(61); r1f<= rxx(62)&rxx(63); r20<= rxx(64)&rxx(65); r21<= rxx(66)&rxx(67);
    r22 <= rxx(68)&rxx(69); r23<= rxx(70)&rxx(71); r24<= rxx(72)&rxx(73); r25<= rxx(74)&rxx(75); r26<= rxx(76)&rxx(77);
    r27 <= rxx(78)&rxx(79); r28<= rxx(80)&rxx(81); r29<= rxx(82)&rxx(83);    
    
    ena_tx <= '1' when (conv_integer(state) = 2) else '0';
    ena_rx <= '1' when (conv_integer(state) = 0) else '0';
end Behavioral;

 

Ну и сама проблема:

1. crctx <= crc_rs(dat_tx, ntx); Присвоение сигналу crctx, в симуляторе ISim, происходит не сразу а через такт clk. Это так и должно быть? Для решения проблемы я ввел как бы задержку на dal1 и del2. Я так предполагаю, что это решение не совсем правильное!

2. Компиляция проекта происходит очень долго и с ошибками. Но если закомментировать строчку data_tx <= dat_tx(conv_integer(inc_tx)); то компиляция происходит быстро и без ошибок. Может быть проблема в неверном обращении с сигналами типа массив! Где я не прав в коде?

 

Может быть есть более простые варианты решения данной задачи?

 

 

 

 

 

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


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

state лучше писать через перечислимый тип, а не числами, и через case. Во-первых, это более традиционно, во-вторых, этим вы позволяете синтезатору выбрать оптимальный вариант кодирования конечного автомата.

 

Нет необходимости писать в стиле conv_integer(foo) = bar; ? Операция сравнения перегружена для многих типов. Вполне себе работает foo = bar.

 

У вас в фунции crc_rs какая-то адски многослойная логика.

 

Попробуйте нормальный симулятор. ModelSim, например.

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


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

Спасибо.

state лучше писать через перечислимый тип, а не числами, и через case. Во-первых, это более традиционно, во-вторых, этим вы позволяете синтезатору выбрать оптимальный вариант кодирования конечного автомата

Это сделать можно. Уже сделал. Но при компиляции проекта вот такая ошибка

ERROR:Pack:2412 - The number of logical LUT blocks exceeds the capacity for the target device.

ERROR:Map:237 - The design is too large to fit the device. Please check the Design Summary section to see which resource requirement for

your design exceeds the resources available in the device. Note that the number of slices reported may not be reflected accurately as

their packing might not have been completed.

И я не знаю, что можно сделать!

У вас в фунции crc_rs какая-то адски многослойная логика.

Тут два вложенных цикла для расчета контрольной суммы CRC16, остальные операции в функции достаточно простые это сложение по модулю два и сдвиг.

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


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

Эти ошибки говорят о том, что проект не лезет в микросхему, и язык описания тут не причем. Возьмите микросхему побольше. И тормоза, скорее всего, оттуда же, долго пытается "впихнуть невпихуемое"

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


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

Возьмите микросхему побольше.

Воу, воу, воу... это мой подход:) вы должны были предложить адскую оптимизацию через схему триггеров;)...

 

на самом деле этот спартан обладает 5720 Лутами, неужели их всех съела функция расчета CRC16 и остальные "достаточно простые" операции?

 

Хоть я и сторонник грубой силы, но тут явно надо все оптимизировать, переменные до 16 бит, а все луты кончились. Надо половину того что пытается сделаться за 1 такт разбить на несколько тактов, из простого: посоветовать синтезатору-имплементатору подключить ДСП блоки, поставить оптимизацию на площадь а не скорость.

 

 

 

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


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

TC попробуйте описать FSM как описано в хендбуках по синтезу от Xilinx или Altera, ну или в книгах Бибило

 

 

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


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

Воу, воу, воу... это мой подход:) вы должны были предложить адскую оптимизацию через схему триггеров;)...

 

Вообще совершенно незачем тут пока компилироваться. Надо все отладить для начала в моделировщике. Я предложил увеличение микросхемы лишь для того, чтобы оно скомпилировалось, и автор увидел, какого монстра он своими циклами нагенерировал, скорее всего, по причине непонимания того, как схемотехнически устроен описанный им блок, ну или просто не подумав об этом.

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


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

Тут два вложенных цикла для расчета контрольной суммы CRC16
Вы представляете себе реализацию цикла в железе? Вы хотите посчитать crc за один такт. Соответственно, все циклы разворачиваются и внезапно оказывается, это занимает больше, чем может влезть в кристалл.

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


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

Вы представляете себе реализацию цикла в железе?

К сожалению не представляю. Расскажите пожалуйста о реализации цикла в железе!

какого монстра он своими циклами нагенерировал, скорее всего, по причине непонимания того, как схемотехнически устроен описанный им блок, ну или просто не подумав об этом

Потихоньку начинаю понимать, что сотворил. Получается циклы лучше не использовать в VHDL? В каких случаях их нужно использовать?

Есть еще табличный метод расчета CRC16, попробую с ним разобраться.

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


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

Получается циклы лучше не использовать в VHDL? В каких случаях их нужно использовать?

Циклы можно и нужно использовать,только нужно ясно представлять себе во что они реализуются в железе.

Вот пример весьма полезного цикла.

 

m1 : for i in 0 to nTap-1 generate
mulah: Dmul16x20 port map (
        clk => clk,
        b => std_logic_vector(SigTapA(i)),
        a => std_logic_vector(CoeffBand(i)),
        p => SumA1V(i));
end generate m1;

 

Без применения цикла пришлось бы nTap раз описывать port map перемножителя,например. С циклом запись получается компактней.

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


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

расчет CRC16 стандартная продцедура, значит в сети полно примеров как правильно ее реализовать на ПЛИС

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


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

была тема с примерами в 2008 году http://electronix.ru/forum/index.php?showtopic=47349

 

или пример xilinx verilog xapp209 : http://www.xilinx.com/support/documentatio...tes/xapp209.pdf

 

исходники :

 

http://ftp.cse.sc.edu/jdavis/csce613/Xilin...ode/xapp209.zip

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


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

Здравствуйте.

Для создания кода по расчету КС использую ресурс

http://outputlogic.com/?page_id=321

 

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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