|
Custom Peripheral, есть вопросы.. |
|
|
|
May 14 2008, 07:30
|

Гуру
     
Группа: Свой
Сообщений: 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 их забирать, если да то как это реализовать ? Если мапированный вариант - тогда тут вопросов пока нет. 1-й сложнее но позволяет съэкономить память если там буфер будет килобайт там или больше, а 2-й проще.Пока не остановился на каком-то 1-м варинате.. Касательно реализации в VHDL - нашёл такие мегафункции как altsyncram и dcfifo и примеры их использования - в принципе с 1-го можно составить FIFO со своей логикой (что мне и надо), а ко 2-му - приёдётся накручивать к уже имеющейся логике, ту которая требуется. Начну с dcfifo (схемный вариант тем более есть), а потом попробую с altsyncram. Есчё есть вопрос касательно IRQ -> после того как буфер набрался - если в контрольном регистре выставлен бит интерупта - выставляется бит в регистре статуса и должно следовать IRQ. Однако судя по данным с литературы (апноты) они занимают довольно много времени. Можно ли как то уменьшить время реакции? В Custom Instructions есть Interrupt Vector - если в правильном направлении смотрю, то насколько это сильно может ускорить время ответа на интерупт ?? Буду признателен за советы, помощь и критику
|
|
|
|
|
May 14 2008, 11:13
|
Знающий
   
Группа: Свой
Сообщений: 518
Регистрация: 12-04-07
Из: Санкт-Петербург
Пользователь №: 26 997

|
Я бы на заморачивался с фифо и делал бы сдвиговый регистр - по логике задачи он тут, имхо, лучше всего подходит. Когда мне надо передать большой объем данных из модуля в проц или другой модуль, но не критично ко времени, я обычно делаю в системе память (можно onchip, можно внешнюю), добавляю модулю мастерпорт и подключаю его к этой памяти (слейв модуля подключен к мастеру проца, мастер модуля - к слейву памяти). Далее проц выделяет нужный объем памяти, сообщает модулю (слейв модуля сделан для регистровой работы) адрес начала блока. Модуль данные принимает, обрабатывает и по ходу процесса скидывает в память. А далее проц их сам забирает. На сколько такой подход хорош здесь - не знаю, может быть либо избыточность памяти, либо критичность времени записи в память. Вообщем, думать надо, варианты есть разные.
|
|
|
|
|
May 14 2008, 14:28
|

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

|
2 Kuzmi4 - глянул на сдвиговый регистр - действительно вы правы оказались Я так понял вот такая реализация имелась ввиду:
Плохо нас основам учили - не теми понятиями оперирую блин... Однако есть нъюанс - если я захочу например буфер в 1024 отсчёта а отсчёт будет 16 битным - а для 1 бита мне нужно 1 тригер - тогда мне понадобится 1024 х16 D-тригеров - жирновато получается... При старте с начальными параметрами в мегавизарде у меня 8-битный сдвиговый занимает 8 лутов... dcfifo - получается самое то для меня... Тем более думаю конструкция скорость в 20-60 МГц выдержит..
|
|
|
|
|
May 15 2008, 13:33
|

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

|
Цитата(Kuzmi4 @ May 14 2008, 17:28)  2 Kuzmi4 - глянул на сдвиговый регистр - действительно вы правы оказались Я так понял вот такая реализация имелась ввиду:
Плохо нас основам учили - не теми понятиями оперирую блин... Однако есть нъюанс - если я захочу например буфер в 1024 отсчёта а отсчёт будет 16 битным - а для 1 бита мне нужно 1 тригер - тогда мне понадобится 1024 х16 D-тригеров - жирновато получается... При старте с начальными параметрами в мегавизарде у меня 8-битный сдвиговый занимает 8 лутов... dcfifo - получается самое то для меня... Тем более думаю конструкция скорость в 20-60 МГц выдержит.. Сразу оговариваюсь с Альтерой не работаю. Может (в принципе должно быть) у Альтеры есть аналогичное что-то. Ниже привожу для Xilinx: Вы попробуйте использовать сдвиговый регистр на основе LUT таблицы - SRL (Shift Register LUT), у Xilinx это описано в XAPP210 для Virtex и Virtex-II series для FPGAs " This application note describes the implementation of Linear Feedback Shift Registers (LFSR) using the SRL macroavailable in the Virtex™ and Virtex-II series of FPGAs. The optimal implementation of a 15-bit LFSR, a 52-bit LFSR, and a 118-bit LFSR are discussed in this application note. " " The Virtex-II devices have a similar macro, a selectable SRL that utilizes one LUT to implement a 16-bit shift register. This macro has two outputs, one is the dedicated output from the 16th register, and the other is selected using the address lines. This enables the macros to be cascadable to implement 32-bit, 64-bit, and 128-bit shift registers in one CLB. "
--------------------
If it doesn't work in simulation, it won't work on the board.
"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
|
|
|
|
|
May 15 2008, 15:46
|

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

|
Цитата(RHnd @ May 15 2008, 18:40)  Вы кем пользуетесь? LPM_SHIFT? Так это не совсем то.  Посмотрите на Memory Compiler -> Shift Register RAM based. Спасибо, а то чуть в тупик зашёл тут. Кричит Цитата Error (10820): Netlist error at my_fifo.vhd(148): can't infer register for in_rst_signal because its behavior depends on the edges of multiple distinct clocks И всё тут. В принципе догадываюсь, что это - мои кривые руки, но если использовать сдвиговые - они будут выглядеть не так кривовато....
|
|
|
|
|
May 29 2008, 12:31
|

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

|
Вроде сварганил я костяк периферии, теперь надо его адаптировать к Avalon Memory-Mapped. Вот тут появились некоторый вопросы  то есть не могу правильно понять... Камень преткновения - byteenable. Значит в Avalon Memory-Mapped Interface Specification за May 2007 дано описание евойное. На сколько я понял - оно связано с writedata - то есть забор байтов с порта writedata будет вестись в таком соответствии
Однако в таблице 1 на странице 16 в Avalon Memory-Mapped Interface Specification в колонке Required обозначено No. Как то странновато получается.... В обсчем из всего вышеизложенного и краткого описания byteenable на стр.16 Цитата Byte-enable signals to enable specific byte lane(s) during transfers on ports of width greater than 8 bits. я пришёл к выводу что этот сигнал нужен когда входной порт имеет размерность больше 8 бит - то есть 16 или 32. То есть если у меня например есть control и status регистры 8-битные - то им до лампочки он будет, потому как там разрядность 8 бит(всегда будет 0001 на byteenable), а вот если регистр данных , в котором по задумке 16 бит - то ему нужно будет мониторить это самый byteenable... Правильно ли я всё понял ? Спасибо.
|
|
|
|
|
May 29 2008, 13:45
|

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

|
У меня тут такая заковыка - есть 2 8 битных регистра и 1 16 битный - то есть в обсчем 32 бита. Потому шину readdata решил сделать 16 битной. Когда идёт чтение данных то я выдаю на порт readdata (который у меня 16 битный) то что у меня в фифо. А когда идёт чтение конфига или статуса - то тогда на нижние 8 бит ложаться соответствующие регистры. Что читается смотрю с адреса авалона что заводится на слейв. Так понимаю, что если у меня не будет записи в мой 16 битный регистр данных то можно и не юзать byteenable.. Потому пока решил что ничего писать не буду туда(оставим разбор с этим зверем до лучших времён  , но хотелось всё таки прояснить... ) Но как быть с чтением - всё ли так там будет корректно ?? Всмысле чтение с 16/8 - битного регистра в 32 битный РОН CPU ? Или стоит расширить всё таки регистры до 32-х? 2 Stewart Little - на счёт byteenable - а по моему не совсем так: Avalon Memory-Mapped Interface Specification, p.27 Цитата During write transfers to a slave port greater than 8 bits wide, the system interconnect fabric asserts the byteenable signal to specify which byte lane(s) to write Тобто более 8 а не меньше или равно 32...
|
|
|
|
|
Jun 2 2008, 12:20
|

Гуру
     
Группа: Модераторы
Сообщений: 2 095
Регистрация: 27-08-04
Из: Россия, СПб
Пользователь №: 553

|
Цитата 2 vetal - а как маскировать byte_enable - это ж я так понял арбитр выставляет ? Тобто юзеру к нему не достучаться - это внутреннее мнение арбитра... IOWR(IORD)8 @ base +0 = доступ к нижней половине 16-ти бит (будет выставлена маска 01) IOWR(IORD)8 @ base +1 = доступ к верхней половине 16-ти бит (будет выставлена маска 10) IOWR(IORD)16 @ base = доступ ко всему регистру. (будет выставлена маска 11) Причем ваше периферийное устройство может по всем этим трем(шести) типам доступа сопоставлять разные регистры/выполнять раные функции. PS: Самый простой способ разобраться - создать тестовую систему + тестовое ПО и прогнать в симуляторе.
|
|
|
|
|
Jun 20 2008, 12:37
|

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

|
Возвращемся к нашим баранам... Есть непонятный нъюанс с адресом на шине : Возмём обсчий случай - допустим я хочу сделать Avalon Memory Mapped Slave и сварганить там например N регистров каких то 8-битных каких то 16-ти, каких то 32-х Код N = N1(8bit)+N2(16bit)+N3(32bit) Итого у меня выходит целый набор.. А как это указать в компоненте ? + alignment - я так понимаю это не касается кратной 8 адресации.... На сколько я понимаю - address - это типа внутренний адрес в адресном пространстве. Но на счёт разрадности - если у меня на address 1 там или 2 - это сколько смещение от начала ? В даташите написано Цитата For example, address= 0 selects the first <slave data width> bits of slave data; address=1 selects the second <slave data width> bits of slave data. Однако что это за таинственная "slave data width" - не указано и особенно где её задавать. Вопрос вроде и простой , но что-то нету как то глобального понимая...
|
|
|
|
|
Jun 22 2008, 16:40
|

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

|
2 vetal - Что-то не понял я ваших манипуляций Цитата 6*16 == 8*16 Почему 6*16 == 8*16 ?? Но даже в таком случае - это 16 байт , а в мапе существует 32 байта для этого компонента.
|
|
|
|
|
Jun 22 2008, 18:30
|

Гуру
     
Группа: Модераторы
Сообщений: 2 095
Регистрация: 27-08-04
Из: Россия, СПб
Пользователь №: 553

|
Цитата(Kuzmi4 @ Jun 22 2008, 20:40)  2 vetal - Что-то не понял я ваших манипуляций Почему 6*16 == 8*16 ?? Но даже в таком случае - это 16 байт , а в мапе существует 32 байта для этого компонента.  6 и 8 - это в пересчете на линии адреса равны. По адресации я уже сказал - 32 битный доступ к регистрам. Если регистр 16 бит, то это не говорит что он занимает 2 байта в адресном пространстве. Он может занимать и 4, и 8 (для 64 битного мастера) и.т.д. Такое решение дает упрощение дешифраторов в шине.
|
|
|
|
|
Jun 23 2008, 13:34
|

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

|
Значит сваял я тут свою периферийку по an333 - мдя - сильно отличается процесс от того, что описан в апноте.. Значит что имеется
тобто есть 3 32-х битных регистра В RTL-е показало вот это:
Внутренности своей периферии проверил - всё как должно быть. В итоге в мапе получил вот что :
Как видно из приведённых рисунков - должно было быть 3х4 байта,а в результате в мапе - 16 байт... В принипе есть идейка - разрядность адреса у меня - [1..0] - тобто 0,1,2,3 - юзается 3 но есть 4 элемента. То есть получается система просто добавила есчё 1-н 32-х битный регистр чтоб был полный набор - 00,01,10,11 для шины адреса ? То есть получается система довалила сама 1 слово в мапу памяти для своего внутреннего удобства ?? Если да - то какие есчё сюрпризы могут подстерегать ?
|
|
|
|
|
Jun 23 2008, 17:01
|

Гуру
     
Группа: Модераторы
Сообщений: 2 095
Регистрация: 27-08-04
Из: Россия, СПб
Пользователь №: 553

|
Цитата В принипе есть идейка - разрядность адреса у меня - [1..0] - тобто 0,1,2,3 - юзается 3 но есть 4 элемента. То есть получается система просто добавила есчё 1-н 32-х битный регистр чтоб был полный набор - 00,01,10,11 для шины адреса ? То есть получается система довалила сама 1 слово в мапу памяти для своего внутреннего удобства ?? Если да - то какие есчё сюрпризы могут подстерегать ? рекомендую нарисовать ручками(на мультиплексорах) схему, которую вы пытаетесь реализовать и попытаться разобраться самому. Если вы выделили 2 линии адреса, то сколько в выделенном вами адресном пространстве может поместиться полноразрядных(data_len-1 .. 0) регистров? И сколько это будет байт? И что по вашему должен отобразить sopc_builder для заданных вами условий?
|
|
|
|
|
Jun 24 2008, 13:53
|

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

|
Значит переработал я апнот333 - чтоб его в свю систему интегрировать - как оказалось не всё там так просто да и не работает он как должно быть - то есть при записи начальных данных - секундный интервал (50MHz тикалка на борде), быть в 0 - пол секунды потом в 1 - пол секунды -> имеем - сначала выход установлен в 0 (где то пол секунды как и должно быть) , потом в 1 и всё (проверяю светодиодом на лапе , потому как осцила под рукой нету) - далее светодиод горит и не тухнет - то есть отрабатывается 1 цикл - а дальше - глухо.. В дебуге проверял - значения по адресам записываются правильные.. Проверял несколько раз - логика враппера и PWM - вроде правильная .. Но вот почему не работает... Значит такой глобальный смысл
Верхняя картинка - это то , что написано в апноте - нижняя - то что есть в действительности на лапе 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; Буду очень признателен если кто подскажет где наплужил. А то сам проверял - вроде всё верно ....
|
|
|
|
|
Jun 25 2008, 03:07
|

МедвеД Инженер 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; Буду очень признателен если кто подскажет где наплужил. А то сам проверял - вроде всё верно ....  Очень и очень мне лениво ковырятся в вашем коде но вот не ясно почему компаритор не сбрасывает в 0 -tmp_pwm_out; ???? с таким компаритором код и будет работать так как вы описали. может сначала родной аппнот запустить? без глубокой переработки...а потом уже совершенствовать под себя? или я что не понимаю
--------------------
Cogito ergo sum
|
|
|
|
|
Jun 25 2008, 08:59
|

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

|
2 Postoroniy_V - большой  . При создании почему то больше уделил внимания авалоновской части и почему то из вида упустил именно это. Завтыкал просто конструкцию Код if (counter == 0) pwm_out <= 0; else pwm_out <= pwm_out; end Это else для Код if (counter >= duty_cycle)begin pwm_out <= 1'b1; end Есчё раз дЯкую!
|
|
|
|
|
Aug 6 2008, 13:01
|

Частый гость
 
Группа: Свой
Сообщений: 154
Регистрация: 16-08-07
Из: Москва
Пользователь №: 29 829

|
насколько я понял при помощи вот этого сигнала "slave_address" можно обращаться к внутренним регистрам компонента к примеру (писал на верилоге) Код always @(posedge clk) begin if (slave_write == 1'b1) begin case (slave_address) 1'b0 : begin control_register1 <= slave_writedata; end 1'b1 : begin control_register2 <= slave_writedata; end endcase end end ну в зависимости от синала slave_write, slave_read, можно записывать или читать из компонента. при помощи таких примерно макросов Код #ifndef _altera_avalon_test2_regs_ #define _altera_avalon_test2_regs_
#include <io.h>
#define IOADDR_test_CNTR1(base) __IO_CALC_ADDRESS_NATIVE(base, test_CNTR1_REGISTER_OFFSET) #define IORD_test_CNTR1(base) IORD_32DIRECT(base, test_CNTR1_REGISTER_OFFSET) #define IOWR_test_CNTR1(base, data) IOWR_32DIRECT(base, test_CNTR1_REGISTER_OFFSET, data)
#define IOADDR_test_CNTR2(base) __IO_CALC_ADDRESS_NATIVE(base, test_CNTR2_REGISTER_OFFSET) #define IORD_test_CNTR2(base) IORD_32DIRECT(base, test_CNTR2_REGISTER_OFFSET) #define IOWR_test_CNTR2(base, data) IOWR_32DIRECT(base, test_CNTR2_REGISTER_OFFSET, data)
#define test_CNTR1_REGISTER_OFFSET 0 #define test_CNTR2_REGISTER_OFFSET 1
#endif /*_altera_avalon_test2_regs_*/ написал тестовую программку очень тестовую Код IOWR_test_CNTR1(TEST2_INST_BASE, 21); IOWR_test_CNTR2(TEST2_INST_BASE, 19); temp1 = IORD_test_CNTR1(TEST2_INST_BASE); temp2 = IORD_test_CNTR2(TEST2_INST_BASE); IOWR_test_CNTR1(TEST2_INST_BASE, 16); IOWR_test_CNTR2(TEST2_INST_BASE, 14); temp1 = IORD_test_CNTR1(TEST2_INST_BASE); temp2 = IORD_test_CNTR2(TEST2_INST_BASE); и при чтении temp1 и temp2 = я вычитываю сначало 19, потом 14... что ещё надо "курить" чтобы правильно сделать?? з.ы. верилоговский файл я приложил //------------------------------------------------------------------ всё разобрался... напутал с адресацией...
Сообщение отредактировал Mozart - Aug 6 2008, 13:54
Прикрепленные файлы
test.rar ( 387 байт )
Кол-во скачиваний: 26
--------------------
все косяки, даже о которых не знает сам разработчик, - мои
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|