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

 
 
 
Reply to this topicStart new topic
> VHDL тестбенч, процессы и процедуры, зы. кодбоксы поправил
GAYVER
сообщение Apr 19 2017, 13:23
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 126
Регистрация: 3-04-13
Пользователь №: 76 333



дано: блок управления термодатчиком с ИНАУТ портом (1-WIRE). тестбенч, который рулит этим портом в соответствии с протоколом 1-WIRE и внутренним алгоритмом работы блока и термодатчика. в тестбенче нюхается перепад на шине 1->0 и запускаются соответствующие ветки обработки, в зависимости от того какой это слот - сброс, запись 0, запись 1, чтение. все работает

задача: сделать тестбенч, который будет управлять НЕСКОЛЬКИМИ такими однотипными блоками и их 1-WIRE шинами, который объединены в 1 вектор (каждый бит которого - шина отдельно взятого блока). сделать надо красиво - параметризируемо и работающее в автомате.


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

с параметризацией модуля вопросов не возникает. проблема с красивой рулежкой 1-WIRE шинами. пока что додумался только до того, чтобы забить код управления одной шиной в процедуру, и вызывать ее каждый раз когда меняется состояние общей шины. но на этом этапе столкнулся с проблемой - блоки работают абсолютно идентично и дергают шину в одно и то же время, в коде управления шиной присутствуют задержки. соответственно при одновременном "запросе" на обработку запускается первая процедура, обрабатывается какое то время, затем запускается вторая. но времянка для второй уже убежала и блок термодатчика уходит в обработку этой сдвинутой времянки, через какое то время выставляет новый "запрос" на обработку и если в этот момент первый датчик не работает, то запускается процедура

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

это код управления одним датчиком:
CODE
pr_wire:process
begin

wait until wire'event;
if wire'event and wire='0' then
wire<='Z';
--если нет флага рукопожатия, то датчик в режиме ожидания. запуск проверки сброса
if f_hs=false then
--отсчитываем минимальное время удержания мастером шины в 0 (480мкс)
wait for 480 us;

--мaстер отпускает шину. ждем 15мкс пока она подтянется к 1
wait for 15 us;

--мастер отдал шину, датчик выставляет ответ и удерживает его минимум 60мкс, отпускаем шину
if f_hs_first=true then wire<='1';
else wire<='0';
end if;
wait for 60 us;
wire<='Z';

ct_slot<=15;
if f_hs_first=true then f_hs_first<=false;
else f_hs<=true;
end if;

--если прошел процесс рукопожатия и нет признака команды чтения, значит датчик находится в режиме ожидания команды. тогда:
--если через 1мкс (по протоколу, на модели будем ждать 2мкс) шина=0 и УБУФ=0, значит идет запись 0
--если через 1мкс (по протоколу, на модели будем ждать 2мкс) шина=1 и УБУФ=1, значит идет запись 1
else
wait for 2 us;

--прием команды
if f_rd=false then rgd_in(ct_slot)<=wire;
ct_slot<=ct_slot-1;
--если конец записи - анализ принятого данного
if ct_slot=8 then
wait for 1 ps;
--команда "чтение температуры". записать в регистр данных температуру
if rgd_in(15 downto 8)="H0H0H0H0" then f_rd<=true;
rgd<=conv_std_logic_vector(ct_tmp,8);
ct_tmp<=ct_tmp+1;
if ct_tmp=4 then ct_tmp<=1;
end if;
--команда "чтение регистра статуса". переписать содержимое рг_ст в регистр данных
elsif rgd_in(15 downto 8)="H0H0HH00" then wait for 1 ps;
if f_control_first=true
then f_control_first<=false;
rgd<="00000101";
else rgd<=rg_st;
end if;
f_rd<=true;
--команда "старт преобразования" и "стоп преобразования". обнулить счетчик
elsif rgd_in(15 downto 8)="HHH0HHH0" or rgd_in(15 downto 8)="00H000H0"
then wait for 1 ps;
ct_slot<=15;
f_hs<=false;
wait for 1 ps;
rgd_in<="0000000000000000";
end if;
--если счетчик дойдет до 0, это значит что идет запись в регистр и дополнительных проверок не надо
elsif ct_slot=0 then wait for 1 ps;
rg_st<=rgd_in(7 downto 0);
ct_slot<=15;
--закончилась команда записи в регистр, датчик переводится в режим ожидания следующей команды
f_hs<=false;
wait for 1 ps;
rgd_in<="0000000000000000";
end if;
--значит идет чтение
else
--выставили на шину значение
wire<=rgd(ct_slot);
ct_slot<=ct_slot-1;
--если выдано последнее данное - сбросить все признаки, обнулить счетчик
if ct_slot=0 then wait for 1 ps;
f_hs<=false;
f_rd<=false;
ct_slot<=15;
wait for 1 ps;
rgd_in<="0000000000000000";
end if;
--удержали его до конца слота (60-2=58мкс), отпустили шину
wait for 58 us;
wire<='Z';
end if;

end if;
end if;
end process;


это муки творчества с процедурой:
CODE
process_wire: process
procedure procedure_wire(num : in integer) is
variable f_wr, f_hs, f_rd, rd_tmp: boolean:=false;
--установка этих сигналов в истину включает имитацию
--1) не прохождения рукопожатия с первого раза
--2) не прохождение контроля с первого раза
--эти фишки проверены и отключены для сокращения диаграммы
variable f_hs_first, f_control_first: boolean:=false;
variable ct_slot:integer:=15;
variable ct_tmp:integer:=1;
variable rgd, rg_com:std_logic_vector(7 downto 0);
variable rgd_in:std_logic_vector(15 downto 0);
variable rg_st:std_logic_vector(7 downto 0):="01010101";
begin
if wire(num)='0' then
wire(num)<='Z';
--если нет флага рукопожатия, то датчик в режиме ожидания. запуск проверки сброса
if f_hs=false then
--отсчитываем минимальное время удержания мастером шины в 0 (480мкс)
wait for 480 us;

--мaстер отпускает шину. ждем 15мкс пока она подтянется к 1
wait for 15 us;

--мастер отдал шину, датчик выставляет ответ и удерживает его минимум 60мкс, отпускаем шину
if f_hs_first=true then wire(num)<='1';
else wire(num)<='0';
end if;
wait for 60 us;
wire(num)<='Z';

ct_slot:=15;
if f_hs_first=true then f_hs_first:=false;
else f_hs:=true;
end if;

--если прошел процесс рукопожатия и нет признака команды чтения, значит датчик находится в режиме ожидания команды. тогда:
--если через 1мкс (по протоколу, на модели будем ждать 2мкс) шина=0 и УБУФ=0, значит идет запись 0
--если через 1мкс (по протоколу, на модели будем ждать 2мкс) шина=1 и УБУФ=1, значит идет запись 1
else
wait for 2 us;

--прием команды
if f_rd=false then rgd_in(ct_slot):=wire(num);
ct_slot:=ct_slot-1;
--если конец записи - анализ принятого данного
if ct_slot=8 then
wait for 1 ps;
--команда "чтение температуры". записать в регистр данных температуру
if rgd_in(15 downto 8)="H0H0H0H0" then f_rd:=true;
rgd:=conv_std_logic_vector(ct_tmp,8);
ct_tmp:=ct_tmp+1;
if ct_tmp=4 then ct_tmp:=1;
end if;
--команда "чтение регистра статуса". переписать содержимое рг_ст в регистр данных
elsif rgd_in(15 downto 8)="H0H0HH00" then wait for 1 ps;
if f_control_first=true then f_control_first:=false;
rgd:="00000101";
else rgd:=rg_st;
end if;
f_rd:=true;
--команда "старт преобразования" и "стоп преобразования". обнулить счетчик
elsif rgd_in(15 downto 8)="HHH0HHH0" or rgd_in(15 downto 8)="00H000H0"
then wait for 1 ps;
ct_slot:=15;
f_hs:=false;
wait for 1 ps;
rgd_in:="0000000000000000";
end if;
--если счетчик дойдет до 0, это значит что идет запись в регистр и дополнительных проверок не надо
elsif ct_slot=0 then wait for 1 ps;
rg_st:=rgd_in(7 downto 0);
ct_slot:=15;
--закончилась команда записи в регистр, датчик переводится в режим ожидания следующей команды
f_hs:=false;
wait for 1 ps;
rgd_in:="0000000000000000";
end if;
wire(num)<='Z';
--значит идет чтение
else
--выставили на шину значение
wire(num)<=rgd(ct_slot);
ct_slot:=ct_slot-1;

--если выдано последнее данное - сбросить все признаки, обнулить счетчик
if ct_slot=0 then wait for 1 ps;
f_hs:=false;
f_rd:=false;
ct_slot:=15;
wait for 1 ps;
rgd_in:="0000000000000000";
end if;
--удержали его до конца слота (60-2=58мкс), отпустили шину
wait for 58 us;
wire(num)<='Z';
end if;

end if;
end if;
end procedure;

begin
wait until wire'event;
procedure_wire(1);
procedure_wire(2);
-- if wire(1)='0' then procedure_wire(1);
-- end if;
-- if wire(2)='0' then procedure_wire(2);
-- end if;
end process process_wire;



еще результат моделирования
в первой точке первый датчик забивает сброс второму. во второй точке наоборот. плюс во второй точке видно красные тычки по ВАЙР второго датчика - "помехи" от первого

а должно быть полностью идентично (скрин2)
Эскизы прикрепленных изображений
Прикрепленное изображение
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
Timmy
сообщение Apr 19 2017, 15:21
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 813
Регистрация: 9-08-08
Из: Санкт-Петербург
Пользователь №: 39 515



Очевидно, следует использовать GENERATE, и для каждой тестируемой однопроводной шины создать свой экземпляр тестового процесса или модуля. На всякий случай напомню, что внутри GENERATE блока можно локально создавать всё то же, что и в основном блоке архитектуры - константы, процессы, сигналы, последовательные операторы, экземпляры модулей. Кстати, фронта можно ждать оператором wait until wire'event and wire='0';, тогда не нужен IF.
Go to the top of the page
 
+Quote Post
Maverick
сообщение Apr 19 2017, 17:23
Сообщение #3


я только учусь...
******

Группа: Модераторы
Сообщений: 3 386
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839



Прошу прощения, что влажу в чужую тему, но есть вопрос как раз по процедуре в тестбенче.
хочу "засунуть" в процедуру:
Код
AWADDR2 <= b"000001100";
        WDATA2 <= x"A5A5A5A5";
        WSTRB2 <=b"1111";
        sendIt2 <= '1';                
        wait for 1 ns; sendIt2 <= '0';
    wait until BVALID2 = '1';
    wait until BVALID2 = '0';
        WSTRB2 <= b"0000";

только передавать данные для сигналов:
AWADDR2 и WDATA2
извне.

моя процедура:
Код
procedure write_data (
signal in_addr : in STD_LOGIC_VECTOR(8 DOWNTO 0);
signal in_data  : in STD_LOGIC_VECTOR(31 DOWNTO 0);
signal in_bvalid2  : in STD_LOGIC
signal reg_sendIt2  : out std_logic;
signal out_WSTRB2 : out STD_LOGIC_VECTOR(3 DOWNTO 0);
signal out_WDATA2  : out STD_LOGIC_VECTOR(31 DOWNTO 0);
signal out_AWADDR2 : out STD_LOGIC_VECTOR(8 DOWNTO 0)
) is

begin
     out_AWADDR2 <= in_addr;
        out_WDATA2 <= in_data;
        out_WSTRB2 <= b"1111";
        reg_sendIt2 <= '1';                
        wait for 1 ns; reg_sendIt2 <= '0';
    wait until in_bvalid2 = '1';
    wait until in_bvalid2 = '0';  
        out_WSTRB2 <= b"0000";
end write_data;


вызов процедцры:
write_data(r_AWADDR2, r_WDATA2, bvalid2, sendIt2, WSTRB2, wdata2, awaddr2 );
(типы совпадают-правильные)

ошибка в моделсиме:
# * Error: No feasible entries for subprogram "write_data".

процедура присутствует только в тестбенче


--------------------
If it doesn't work in simulation, it won't work on the board.

"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение Apr 19 2017, 18:55
Сообщение #4


Местный
***

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



Код
# * Error:  No feasible entries for subprogram "write_data".

Если я не ошибаюсь, иногда для процедуры важно место её объявления. Где Вы её объявляете ?
Во всяком случае, у меня процедуры заработали только тогда, когда я их объявил в теле процесса, в котором они запускается.

Сообщение отредактировал Flip-fl0p - Apr 19 2017, 18:57
Go to the top of the page
 
+Quote Post
GAYVER
сообщение Apr 20 2017, 05:57
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 126
Регистрация: 3-04-13
Пользователь №: 76 333



Цитата(Maverick @ Apr 19 2017, 20:23) *
Прошу прощения, что влажу в чужую тему, но есть вопрос как раз по процедуре в тестбенче.
хочу "засунуть" в процедуру:

ошибка в моделсиме:
# * Error: No feasible entries for subprogram "write_data".

процедура присутствует только в тестбенче


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

Цитата(Timmy @ Apr 19 2017, 18:21) *
Очевидно, следует использовать GENERATE, и для каждой тестируемой однопроводной шины создать свой экземпляр тестового процесса или модуля. На всякий случай напомню, что внутри GENERATE блока можно локально создавать всё то же, что и в основном блоке архитектуры - константы, процессы, сигналы, последовательные операторы, экземпляры модулей.


никогда не встречал использование GENERATE для "размножения" процесса. а сделать это нужно именно отдельным процессом внутри большого тестбенча, т.к. на топ-лвл от термодатчиков выходит только ВАЙР шина и к ним сигналы управления внешними буферами на плате. а помимо них еще куча всего, чем так же надо рулить. если не сложно покажите пример использования, или ткните ссылкой где это можно посмотреть


Цитата(Timmy @ Apr 19 2017, 18:21) *
Кстати, фронта можно ждать оператором wait until wire'event and wire='0';, тогда не нужен IF.


я в курсе sm.gif. это аппендицит от предыдущих вариаций кода - лень было переделывать sm.gif
Go to the top of the page
 
+Quote Post
Maverick
сообщение Apr 20 2017, 06:12
Сообщение #6


я только учусь...
******

Группа: Модераторы
Сообщений: 3 386
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839



Цитата(Flip-fl0p @ Apr 19 2017, 21:55) *
Код
# * Error:  No feasible entries for subprogram "write_data".

Если я не ошибаюсь, иногда для процедуры важно место её объявления. Где Вы её объявляете ?
Во всяком случае, у меня процедуры заработали только тогда, когда я их объявил в теле процесса, в котором они запускается.

Спасибо большое. Вы абсолютно правы. Tело/объявление процедуры надо было поместить в процесс.

Цитата(GAYVER @ Apr 20 2017, 08:57) *
чтобы была возможность присваивать сигналы внутри процедуры, она должна быть описана в процессе из которого вызывается

не обязательно sm.gif


--------------------
If it doesn't work in simulation, it won't work on the board.

"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Apr 20 2017, 06:15
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 821
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(Maverick @ Apr 19 2017, 20:23) *
моя процедура:
Код
procedure write_data (
  [...]
signal in_bvalid2  : in STD_LOGIC
  [...]
) is

begin
  [...]    wait until in_bvalid2 = '1';
         wait until in_bvalid2 = '0';  
  [...]
end write_data;
Это работать не будет. Аргумент-сигнал не передаётся в процедуру "постоянно", он туда передаётся однократно в момент вызова процедуры. То есть внутри процедуры сигнал превратится в константу, поэтому отслеживать его события бесполезно. Уберите его из аргументов in_bvalid2 и отслеживайте внешний BVALID2.
Go to the top of the page
 
+Quote Post
GAYVER
сообщение Apr 20 2017, 06:39
Сообщение #8


Частый гость
**

Группа: Свой
Сообщений: 126
Регистрация: 3-04-13
Пользователь №: 76 333



вай-вай-вай, все заработало

отдельная благодарность Timmy за открытие новой фишки. теперь мои тестбенчи будут еще злее sm.gif


CODE
ARCHITECTURE behavior OF tb_top_test IS

constant kol_izp:integer:=8;
constant kol_td:integer:=2;

type m_bool is array (1 to kol_td) of boolean;
type m_int is array (1 to kol_td) of integer;
type m_vect8 is array (1 to kol_td) of std_logic_vector(7 downto 0);
type m_vect16 is array (1 to kol_td) of std_logic_vector(15 downto 0);

signal f_wr, f_hs, f_rd, rd_tmp: m_bool:=(others=>false);
--установка этих сигналов в истину включает имитацию
--1) не прохождения рукопожатия с первого раза
--2) не прохождение контроля с первого раза
--эти фишки проверены и отключены для сокращения диаграммы
signal f_hs_first, f_control_first: m_bool:=(others=>false);
signal ct_slot: m_int:=(others=>15);
signal ct_tmp: m_int:=(others=>1);
signal rgd, rg_com: m_vect8;
signal rgd_in: m_vect16;
signal rg_st: m_vect8:=(others=>"01010101");

BEGIN


pr_wire:for i in 1 to kol_td generate
process
begin
wait until wire(i)'event;
if wire(i)'event and wire(i)='0' then
wire(i)<='Z';
--если нет флага рукопожатия, то датчик в режиме ожидания. запуск проверки сброса
if f_hs(i)=false then

и далее по тексту...

end process;
end generate

Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post

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

 


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


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