Garik 0 22 апреля, 2014 Опубликовано 22 апреля, 2014 · Жалоба Всем добрый день! Появились проблемы при разработке протокола 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)); то компиляция происходит быстро и без ошибок. Может быть проблема в неверном обращении с сигналами типа массив! Где я не прав в коде? Может быть есть более простые варианты решения данной задачи? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 17 22 апреля, 2014 Опубликовано 22 апреля, 2014 · Жалоба state лучше писать через перечислимый тип, а не числами, и через case. Во-первых, это более традиционно, во-вторых, этим вы позволяете синтезатору выбрать оптимальный вариант кодирования конечного автомата. Нет необходимости писать в стиле conv_integer(foo) = bar; ? Операция сравнения перегружена для многих типов. Вполне себе работает foo = bar. У вас в фунции crc_rs какая-то адски многослойная логика. Попробуйте нормальный симулятор. ModelSim, например. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Garik 0 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба Спасибо. 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, остальные операции в функции достаточно простые это сложение по модулю два и сдвиг. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба Эти ошибки говорят о том, что проект не лезет в микросхему, и язык описания тут не причем. Возьмите микросхему побольше. И тормоза, скорее всего, оттуда же, долго пытается "впихнуть невпихуемое" Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба Возьмите микросхему побольше. Воу, воу, воу... это мой подход:) вы должны были предложить адскую оптимизацию через схему триггеров;)... на самом деле этот спартан обладает 5720 Лутами, неужели их всех съела функция расчета CRC16 и остальные "достаточно простые" операции? Хоть я и сторонник грубой силы, но тут явно надо все оптимизировать, переменные до 16 бит, а все луты кончились. Надо половину того что пытается сделаться за 1 такт разбить на несколько тактов, из простого: посоветовать синтезатору-имплементатору подключить ДСП блоки, поставить оптимизацию на площадь а не скорость. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба TC попробуйте описать FSM как описано в хендбуках по синтезу от Xilinx или Altera, ну или в книгах Бибило Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба Воу, воу, воу... это мой подход:) вы должны были предложить адскую оптимизацию через схему триггеров;)... Вообще совершенно незачем тут пока компилироваться. Надо все отладить для начала в моделировщике. Я предложил увеличение микросхемы лишь для того, чтобы оно скомпилировалось, и автор увидел, какого монстра он своими циклами нагенерировал, скорее всего, по причине непонимания того, как схемотехнически устроен описанный им блок, ну или просто не подумав об этом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 17 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба Тут два вложенных цикла для расчета контрольной суммы CRC16Вы представляете себе реализацию цикла в железе? Вы хотите посчитать crc за один такт. Соответственно, все циклы разворачиваются и внезапно оказывается, это занимает больше, чем может влезть в кристалл. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Garik 0 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба Вы представляете себе реализацию цикла в железе? К сожалению не представляю. Расскажите пожалуйста о реализации цикла в железе! какого монстра он своими циклами нагенерировал, скорее всего, по причине непонимания того, как схемотехнически устроен описанный им блок, ну или просто не подумав об этом Потихоньку начинаю понимать, что сотворил. Получается циклы лучше не использовать в VHDL? В каких случаях их нужно использовать? Есть еще табличный метод расчета CRC16, попробую с ним разобраться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_sda 0 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба Получается циклы лучше не использовать в 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 перемножителя,например. С циклом запись получается компактней. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ZASADA 0 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба расчет CRC16 стандартная продцедура, значит в сети полно примеров как правильно ее реализовать на ПЛИС Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 17 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба Вот пример весьма полезного цикла.Это не тот цикл. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_sda 0 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба Это не тот цикл. Это просто цикл. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
litv 0 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба была тема с примерами в 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dlsh 2 23 апреля, 2014 Опубликовано 23 апреля, 2014 · Жалоба Здравствуйте. Для создания кода по расчету КС использую ресурс http://outputlogic.com/?page_id=321 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться