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

 
 
> Custom Peripheral, есть вопросы..
Kuzmi4
сообщение May 14 2008, 07:30
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



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

Хочу сотворить собственную периферию, чтоб в SoPC Builder`е можно было свободно использовать.
Ну и как всегда есть вопросы ( в принципе если кто-то решит тоже начать писать свою периферию - тож думаю будет полезно, если начинать с нуля ).

Для полноты картины опишу что хочется поиметь:
В 2-х словах - нужно фотография импульса, то есть N/2 отсчётов до и N/2 отсчётов после.
Реализация как она была на рассыпухе - есть FIFO. В него пишется через логику данные с параллельного ADC. При чём, чтобы получить именно "фото" с заданными характеристиками в FIFO пишется до половины, потом по выставлению флага Half_Full начинается запись/чтение с FIFO - то есть отсчёт записывается в FIFO уровнем на лапке WR и потом после записи уровнем на лапке RD считывается - это позволяет как бы пропускать динамическую картинку через буффер обёмом N/2. Далее, когда приходит сигнал с ДНУ - ногодрыгание на лапе RD прекращается и мы дописываем оставшиеся N/2 отсчётов - и вуаля! - в результате у нас картинка где есть N/2 записей с ADC до и N/2 записей с ADC после сигнала. Если сигнал с ДНУ приходит раньше чем выставляется флаг Half_Full - начинается вышеописанная процедура, а потом в проге юзер решает что делать с этим фреймом.

Касательно реализации интерфеса - будет Avalon M-M Slave. В документации для "Avalon Memory-Mapped Interfaces" прочитал как работает слейв и про смысл разнообразных wires на шине. Так же прочитал про пакетную передачу данных. И тут возник вопрос касательно реализации регистров устройства, а если точнее передачи данных - можно сделать вариант 1 -> 3 регистра: status,control, data;вариант 2 -> status, control, data[0], data[1]... data[N-1];
Собственно по первому варианту будет пакетная передача данных, а по второму как обыкновенная мапа памяти - обращение к ячейке и все дела... Однако есть вопрос касательно пакетной передачи, как видно из рисунка:
Прикрепленное изображение

Выдача данных слейвом ведётся по фронтам клока - будет ли успевать CPU их забирать, если да то как это реализовать ? smile3046.gif
Если мапированный вариант - тогда тут вопросов пока нет. smile.gif
1-й сложнее но позволяет съэкономить память если там буфер будет килобайт там или больше, а 2-й проще.Пока не остановился на каком-то 1-м варинате..

Касательно реализации в VHDL - нашёл такие мегафункции как altsyncram и dcfifo и примеры их использования - в принципе с 1-го можно составить FIFO со своей логикой (что мне и надо), а ко 2-му - приёдётся накручивать к уже имеющейся логике, ту которая требуется. Начну с dcfifo (схемный вариант тем более есть), а потом попробую с altsyncram.

Есчё есть вопрос касательно IRQ -> после того как буфер набрался - если в контрольном регистре выставлен бит интерупта - выставляется бит в регистре статуса и должно следовать IRQ. Однако судя по данным с литературы (апноты) они занимают довольно много времени. Можно ли как то уменьшить время реакции? В Custom Instructions есть Interrupt Vector - если в правильном направлении смотрю, то насколько это сильно может ускорить время ответа на интерупт ?? smile3046.gif

Буду признателен за советы, помощь и критику
laughing.gif
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Kuzmi4
сообщение Jun 24 2008, 13:53
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



Значит переработал я апнот333 - чтоб его в свю систему интегрировать - как оказалось не всё там так просто да и не работает он как должно быть - то есть при записи начальных данных - секундный интервал (50MHz тикалка на борде), быть в 0 - пол секунды потом в 1 - пол секунды -> имеем - сначала выход установлен в 0 (где то пол секунды как и должно быть) , потом в 1 и всё (проверяю светодиодом на лапе , потому как осцила под рукой нету) - далее светодиод горит и не тухнет - то есть отрабатывается 1 цикл - а дальше - глухо..
В дебуге проверял - значения по адресам записываются правильные..
Проверял несколько раз - логика враппера и PWM - вроде правильная .. Но вот почему не работает... sad.gif
Значит такой глобальный смысл
Прикрепленное изображение

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

Значит собственно wrapper девайса для avalon memory-mapped slave device:
Код
-- Adress decode
clock_divide_reg_selected <=  ( not address(1) ) and ( not address(0) );    --address 00
duty_cycle_reg_selected <= ( not address(1) ) and  address(0);        --address 01
enable_reg_selected       <=  address(1) and ( not address(0) );    --address 10
--Determination - if a vaild transaction was initiated
valid_write <= chip_select and write_signal;
valid_read  <= chip_select and read_signal;
--Determination - if a write occurred to a specific address
write_to_clock_divide <= valid_write and clock_divide_reg_selected;
--write_to_duty_cycle   <= valid_write and duty_cycle_reg_selected;
--write_to_enable       <= valid_write and enable_reg_selected;
--Determination - if a read occurred to a specific address
read_to_clock_divide <= valid_read and clock_divide_reg_selected;
read_to_duty_cycle   <= valid_read and duty_cycle_reg_selected;
read_to_enable       <= valid_read and enable_reg_selected;
--Determination - which byte lane to write
clk_div_en3 <= valid_write and write_to_clock_divide and byte_enable(3);
clk_div_en2 <= valid_write and write_to_clock_divide and byte_enable(2);
clk_div_en1 <= valid_write and write_to_clock_divide and byte_enable(1);
clk_div_en0 <= valid_write and write_to_clock_divide and byte_enable(0);

duty_cyc_en3 <= valid_write and duty_cycle_reg_selected and byte_enable(3);
duty_cyc_en2 <= valid_write and duty_cycle_reg_selected and byte_enable(2);
duty_cyc_en1 <= valid_write and duty_cycle_reg_selected and byte_enable(1);
duty_cyc_en0 <= valid_write and duty_cycle_reg_selected and byte_enable(0);

enable_en0   <= valid_write and enable_reg_selected and byte_enable(0);

-----------------------------------------------------------------------
-- Read Data Bus Mux
-----------------------------------------------------------------------
Read_process:    process (read_to_clock_divide, read_to_duty_cycle, read_to_enable )
                begin
                --================================================================================
=======================================================
                    if (read_to_clock_divide='1') then
                        read_data <= clock_divide_register;
                    elsif (read_to_duty_cycle='1') then
                        read_data <= duty_cycle_register;
                    elsif (read_to_enable='1') then
                        read_data <= "0000000000000000000000000000000" & enable_register;
                    else
                        read_data <= "00000000000000000000000000000000"; -- if nothing selected - ZEROs out
                    end if;
                --================================================================================
=======================================================    
                end process;
-----------------------------------------------------------------------
-- Write to clock_divide Register
-----------------------------------------------------------------------
WR_CLK_DIVIDE:    process (clk, resetn)
                begin
                    if (resetn='0') then
                        clock_divide_register <= "00000000000000000000000000000000";
                    elsif (rising_edge(clk)) then
                        --++++++++++++++++++++++++
                            if(clk_div_en3='1') then
                                clock_divide_register(31 downto 24) <= write_data(31 downto 24);     
                            else         
                                clock_divide_register(31 downto 24) <= clock_divide_register(31 downto 24);  
                            end if;
                            if(clk_div_en2='1') then
                                clock_divide_register(23 downto 16) <= write_data(23 downto 16);     
                            else
                                clock_divide_register(23 downto 16) <= clock_divide_register(23 downto 16);    
                            end if;
                            if(clk_div_en1='1') then
                                clock_divide_register(15 downto 8) <= write_data(15 downto 8);     
                            else
                                clock_divide_register(15 downto 8) <= clock_divide_register(15 downto 8);
                            end if;
                            if(clk_div_en0='1') then
                                clock_divide_register(7 downto 0) <= write_data(7 downto 0);
                            else
                                clock_divide_register(7 downto 0) <= clock_divide_register(7 downto 0);
                            end if;
                        --++++++++++++++++++++++++
                    end if;
                end process;
-----------------------------------------------------------------------
-- Write to duty_cycle Register
-----------------------------------------------------------------------
WR_DC_REGISTER:    process (clk, resetn)    
                begin
                    if (resetn='0') then
                        duty_cycle_register <= "00000000000000000000000000000000";
                    elsif (rising_edge(clk)) then
                        --++++++++++++++++++++++++
                            if(duty_cyc_en3='1') then
                                duty_cycle_register(31 downto 24) <= write_data(31 downto 24);     
                            else         
                                duty_cycle_register(31 downto 24) <= duty_cycle_register(31 downto 24);  
                            end if;
                            if(duty_cyc_en2='1') then
                                duty_cycle_register(23 downto 16) <= write_data(23 downto 16);     
                            else
                                duty_cycle_register(23 downto 16) <= duty_cycle_register(23 downto 16);    
                            end if;
                            if(duty_cyc_en1='1') then
                                duty_cycle_register(15 downto 8) <= write_data(15 downto 8);     
                            else
                                duty_cycle_register(15 downto 8) <= duty_cycle_register(15 downto 8);
                            end if;
                            if(duty_cyc_en0='1') then
                                duty_cycle_register(7 downto 0) <= write_data(7 downto 0);
                            else
                                duty_cycle_register(7 downto 0) <= duty_cycle_register(7 downto 0);
                            end if;
                    end if;
                end process;
-----------------------------------------------------------------------
-- Write to Enable Register
-----------------------------------------------------------------------
WR_TO_EN:        process (clk, resetn)
                begin
                    if (resetn='0') then
                        enable_register <= '0';
                    elsif (rising_edge(clk)) then
                        if(enable_en0='1') then
                            enable_register <= write_data(0);
                        else
                            enable_register <= enable_register;
                        end if;
                    end if;
                end process;
-----------------------------------------------------------------------
-- Assigning Input to Output
--assign register values to register file outputs to the PWM
pwm_clock_divide <= clock_divide_register;
pwm_duty_cycle   <= duty_cycle_register;
pwm_enable       <= enable_register;


Собсно PWM
Код
--PWM Counter Process
    process (clk,resetn)
    begin
    --********************************************************************
    if (rising_edge(clk)) then
    --====================================================================
        if (resetn = '0') then
            counter <= "00000000000000000000000000000000";
        else
            if (pwm_enable='1') then
                if ( counter >= clock_divide ) then
                    counter <= "00000000000000000000000000000000";
                else
                    counter <= counter + 1;
                end if;
            end if;
        end if;
    --====================================================================
    end if;
    --********************************************************************
    end process;
--//////////////////////////////////////////////////////////////////////////////
--PWM Comparitor
    process (clk,resetn)
    begin
    --********************************************************************
    if (rising_edge(clk)) then
    --====================================================================    
    if (resetn='0') then
            tmp_pwm_out <= '0';
    else
            if (pwm_enable='1') then
                if ( counter >= duty_cycle ) then
                    tmp_pwm_out <= '1';
                else
                    tmp_pwm_out <= tmp_pwm_out;
                end if;
            end if;            
    end if;
    --====================================================================    
    end if;    
    --********************************************************************
    end process;
--route signal
pwm_out <= tmp_pwm_out;

Буду очень признателен если кто подскажет где наплужил. crying.gif
А то сам проверял - вроде всё верно ....
help.gif
Go to the top of the page
 
+Quote Post
Postoroniy_V
сообщение Jun 25 2008, 03:07
Сообщение #3


МедвеД Инженер I
****

Группа: Свой
Сообщений: 816
Регистрация: 21-10-04
Пользователь №: 951



Цитата(Kuzmi4 @ Jun 24 2008, 22:53) *
Значит переработал я апнот333 - чтоб его в свю систему интегрировать - как оказалось не всё там так просто да и не работает он как должно быть - то есть при записи начальных данных - секундный интервал (50MHz тикалка на борде), быть в 0 - пол секунды потом в 1 - пол секунды -> имеем - сначала выход установлен в 0 (где то пол секунды как и должно быть) , потом в 1 и всё (проверяю светодиодом на лапе , потому как осцила под рукой нету) - далее светодиод горит и не тухнет - то есть отрабатывается 1 цикл - а дальше - глухо..
......
Верхняя картинка - это то , что написано в апноте - нижняя - то что есть в действительности на лапе PWM в моей переработанной реализации..
Симуляция именно самого PWM - показывает , что он при стабильных значениях на входах - выход генерит постоянно - как и должно быть по сути..

Значит собственно wrapper девайса для avalon memory-mapped slave device:
...........

Собсно PWM
Код
...............
--PWM Comparitor
    process (clk,resetn)
    begin
    --********************************************************************
    if (rising_edge(clk)) then
    --====================================================================    
    if (resetn='0') then
            tmp_pwm_out <= '0';
    else
            if (pwm_enable='1') then
                if ( counter >= duty_cycle ) then
                    tmp_pwm_out <= '1';
                else
                    tmp_pwm_out <= tmp_pwm_out;--tmp_pwm_out <= '0';??????????????????????????????????????????????
                end if;
            end if;            
    end if;
    --====================================================================    
    end if;    
    --********************************************************************
    end process;
--route signal
pwm_out <= tmp_pwm_out;

Буду очень признателен если кто подскажет где наплужил. crying.gif
А то сам проверял - вроде всё верно ....
help.gif

Очень и очень мне лениво ковырятся в вашем коде
но вот не ясно почему компаритор не сбрасывает в 0 -tmp_pwm_out; ????
с таким компаритором код и будет работать так как вы описали.
может сначала родной аппнот запустить? без глубокой переработки...а потом уже совершенствовать под себя?
или я что не понимаю 07.gif


--------------------
Cogito ergo sum
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Kuzmi4   Custom Peripheral   May 14 2008, 07:30
- - RHnd   Я бы на заморачивался с фифо и делал бы сдвиговый ...   May 14 2008, 11:13
- - Kuzmi4   2 RHnd - можете объяснить, чем сдесь фифо не подхо...   May 14 2008, 11:38
|- - RHnd   Не то, чтоб фифо не подходит, но сдвиговый регистр...   May 14 2008, 11:45
- - Kuzmi4   2 RHnd - спасибо за идейку, не подумал А можете...   May 14 2008, 11:49
|- - RHnd   Цитата(Kuzmi4 @ May 14 2008, 15:49) А мож...   May 14 2008, 12:14
- - Kuzmi4   Есть. Посмотрю сегодня... Остановился пока на фифо...   May 14 2008, 12:18
- - Kuzmi4   2 Kuzmi4 - глянул на сдвиговый регистр - действите...   May 14 2008, 14:28
|- - RHnd   Угу. Примерно оно. Я только не понял, Вы в схемати...   May 14 2008, 18:00
|- - Maverick   Цитата(Kuzmi4 @ May 14 2008, 17:28) 2 Kuz...   May 15 2008, 13:33
- - Kuzmi4   2 RHnd - схематик мне нужен для понимания процесса...   May 15 2008, 08:56
|- - RHnd   Цитата(Kuzmi4 @ May 15 2008, 12:56) на сч...   May 15 2008, 15:40
- - Kuzmi4   Цитата(RHnd @ May 15 2008, 18:40) Вы кем ...   May 15 2008, 15:46
- - Kuzmi4   Вроде сварганил я костяк периферии, теперь надо ег...   May 29 2008, 12:31
|- - Stewart Little   Цитата(Kuzmi4 @ May 29 2008, 16:31) я при...   May 29 2008, 13:31
- - RHnd   Эксперименты не ставил, но смутно подозреваю, что ...   May 29 2008, 13:15
- - Kuzmi4   У меня тут такая заковыка - есть 2 8 битных регист...   May 29 2008, 13:45
- - vetal   исходить надо из разрядности мастера, периферии и ...   May 29 2008, 16:34
- - Kuzmi4   2 vetal - а как маскировать byte_enable - это ж я ...   Jun 2 2008, 12:09
- - vetal   Цитата2 vetal - а как маскировать byte_enable - эт...   Jun 2 2008, 12:20
- - Kuzmi4   2 vetal - спасибо, буду знать. А идея на счёт мест...   Jun 2 2008, 13:09
- - vetal   ЦитатаА в каком симуляторе можно посмотреть сигнал...   Jun 2 2008, 13:25
- - Kuzmi4   2vetal - я сигналы смотрю симулятором в квартусе. ...   Jun 2 2008, 13:54
|- - Stewart Little   Цитата(Kuzmi4 @ Jun 2 2008, 17:54) 2vetal...   Jun 2 2008, 19:49
- - Kuzmi4   Возвращемся к нашим баранам... Есть непонятный нъю...   Jun 20 2008, 12:37
- - Kuzmi4   Покопал в этом направлении - посмотрел в глубь соб...   Jun 21 2008, 16:27
- - vetal   ЦитатаЗначит имеем занятое адресное пространство -...   Jun 21 2008, 18:21
- - Kuzmi4   2 vetal - спасибо, вчера сам догнал что пургу смо...   Jun 22 2008, 14:21
- - vetal   Цитатапочему так wacko.gif ?? доступ 32битный реал...   Jun 22 2008, 16:10
- - Kuzmi4   2 vetal - Что-то не понял я ваших манипуляций Цит...   Jun 22 2008, 16:40
|- - vetal   Цитата(Kuzmi4 @ Jun 22 2008, 20:40) 2 vet...   Jun 22 2008, 18:30
- - Kuzmi4   Что - то чем дальше в лес тем толще партизаны... Н...   Jun 23 2008, 06:43
- - Kuzmi4   Значит сваял я тут свою периферийку по an333 - мдя...   Jun 23 2008, 13:34
- - vetal   ЦитатаВ принипе есть идейка - разрядность адреса у...   Jun 23 2008, 17:01
- - Kuzmi4   2 vetal - Спасибо, потихоньку начинаю понимать. Я ...   Jun 24 2008, 07:37
- - Kuzmi4   2 Postoroniy_V - большой . При создании почему т...   Jun 25 2008, 08:59
- - Kuzmi4   Тут появился вопросик касательно INOUT бита - ну н...   Jun 27 2008, 07:38
- - Kuzmi4   В обсчем поборол я этот вопрос - сврганил там 2 ши...   Jun 28 2008, 21:47
- - Mozart   насколько я понял при помощи вот этого сигнала ...   Aug 6 2008, 13:01


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

 


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


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