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

Странности с симуляцией

Ну заглянул. И ничего не понял. Зачем все это. Видимо товарищу нужен приемник на VHDL.

Просто поделитесь.

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


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

Ну заглянул. И ничего не понял. Зачем все это.

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

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


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

Про укороченный сдвигающий регистр в зависимости от signal или variable - это просто здорово.

Что укороченный, что удлинненый: все едино.

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


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

Про укороченный сдвигающий регистр в зависимости от signal или variable - это просто здорово.

Что укороченный, что удлинненый: все едино.

А что не так?

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


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

process(Reset, CSn,SCLKin,CLK48,bit_cnt,cmd_gate)
variable pulse5  :std_logic;
variable shr : unsigned(2 downto 0);
begin
  if (Reset='1') or (CSn='1') then
    bit_cnt <= "000";
  elsif rising_edge(SCLKin) then
    bit_cnt <= bit_cnt + "001"; -- count SCLK pulses
    if (bit_cnt = "101")  then
      pulse5 := '1';
    else
      pulse5 := '0';
    end if;
  end if;
  if rising_edge(CLK48) then
    shr := shr(1 downto 0) & pulse5;
    RdWr_done <= shr(2) and (not cmd_gate);
  end if;
end process;

ну, разруха в головах.

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

  if rising_edge(CLK48) then // по переднему фронту тактирующего сигнала 
    shr := shr(1 downto 0) & pulse5; // регистру shr[2:0] в текущем цикле присваивается значение {shr[1:0],pulse5}
    RdWr_done <= shr(2) and (not cmd_gate); // регистру RdWr_done в следующем цикле присваивается значение shr[2] && ( !cmd_gate)
  end if;

 

естественно компилятор не может оперировать вычислениями распределённими во времени - ему нужно привести язык к сxеме, которая понимает только "сейчас" ( защёлкни! значение поступающее с комбинационной сxемы в триггере по фронту синхроимпульса /для чувствительной по фронту триггера/) приводя к единому моменту времени у вас получается что триггер RdWr_done защёлкивает значение (shr[1] И (не cmd_gate))

у меня к сожлению нет времени для достаточно полного анализа почему синтезатор убирает сигнал RwWr_done вообще, но предположу что так как shr[2] упрощается сигнал RdWr_done ~ cmd_gate

 

вообще говоря я уже упоминал о стилях программирования - повторюсь ещё раз на данном примере - не следует мешать в одном и том же блоке сигналы с переменными - они по природе разные и предназначены для разных вещей - из-за их смешивания легко запутаться в поведение сxемы.

хорошо бы подумать зачем в язык параллельный вводятся последовательные операторы - наверное чтобы упростить человеку восприятие сложных единомоментных вычислений (потому как человек в принципе привык думать последовательно) так вместо записи

a<=(b>c)?((d<=e)?b*(d-e):c*(d-e)):c*(d-e);

удобнее записать последовательность операторов

if (b>c)
{
   if (d<=e)
     a:=b;
   else
     a:=c;
}
else a:=c;
a:=a*(d-e);

и это вычисление произойдёт в едином циклe

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

 

дополнительную путаницу может произвести тактирование одного процесса несколькими клоками - это в принципе непрактично - связано опять же с тем же восприятием, когда человек читает код он видит последовательность строк сверху вниз - у вас же получается логика описаная на дне никак не связана с логикой наверху за исключением связи по данным - но данные - жто объекты над которыми совершается действие, а процессы - сами действия обвешанные аттрибутами (главным образом времени исполнения) получается что разные по сути и моменту исполнения действия (даже над одними объектами) у вас сгруппированы в одном процессе - что не гуд

 

и еще раз о списке чувствительности:

из этого списка process(Reset, CSn,SCLKin,CLK48,bit_cnt,cmd_gate) процесс не чувствителен к bit_cnt,cmd_gate

а если вы (как я бы посоветовал) разнесёте процесс по clock domains то первай будет чувствителен к Reset, CSn,SCLKin а второй только к CLK48

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


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

shr := shr(1 downto 0) & pulse5; // регистру shr[2:0] в текущем цикле присваивается значение {shr[1:0],pulse5}

RdWr_done <= shr(2) and (not cmd_gate); // регистру RdWr_done в следующем цикле присваивается значение shr[2] && ( !cmd_gate)

 

В данном случае как раз в ТЕКУЩЕМ цикле выполняются обе операции... что и приводит к выкидыванию shr[2].

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


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

В данном случае как раз в ТЕКУЩЕМ цикле выполняются обе операции... что и приводит к выкидыванию shr[2].

вопрос интерпритации: я имею ввиду что сигнал на выходе триггера RdWr_done войдёт в стабильное состояние после текущего щелчка клока, то есть новое значение будет фиксированым (стабильным) в объекте только после текущего тика (а цикл имеется в виду - дельта-цикл а не период(цикл) clock-a )

суть одна - бит упрощается из-за двух разных по типу операторов присваивания (ложная интерпритация выполняемого ими действия)

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


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

module rxd_232_end /// добавлен фильтр данных

(

input ti_60, ///// 60мГц

input reset,

input rxd,

output reg [7:0] rg_rs232_out,

output reg ochibka_kadra,

output reg int

);

 

reg dff_a;

reg rx;

reg reset_232;

reg [9:0] cta;

reg [3:0] ctb;

reg dff_enable_work;

reg stop;

reg [8:0] rg_rs232;

reg [2:0] shift_left_rg;

 

wire seredina_bita;

wire clr_enable_work;

wire e_wr_rg_rs232;

wire rx_filtr;

 

always @ (posedge ti_60)

begin

dff_a <=rxd;

rx <= dff_a; ///// дань метастабильности

reset_232 <= reset;

end

 

 

////////////////////////////// формирователь несущей частоты 115200 (делитель на 521)

 

always @ (posedge ti_60)

begin

if (reset_232)

cta <= 10'h000;

else if (rx & ~dff_enable_work)

cta <= 10'h000;

else if (cta == 10'd520)

cta <= 10'h000;

else

cta <= cta + 1'b1;

end

 

assign seredina_bita = (cta == 10'd260);

 

////////////////////////////// формирователь 8 отсчетов на несущей частоте 115200

always @ (posedge ti_60) // (без бита паритета)

begin

if (dff_enable_work == 1'b0)

ctb <= 4'h0;

else if (seredina_bita)

ctb <= ctb + 1'b1;

end

 

 

assign clr_enable_work = stop | reset_232 | (rx & ~dff_enable_work);

 

always @ (posedge ti_60 or posedge clr_enable_work)

begin

if (clr_enable_work)

dff_enable_work <= 1'b0;

else if (seredina_bita)

dff_enable_work <= 1'b1;

end

 

assign e_wr_rg_rs232 = seredina_bita & dff_enable_work;

 

// фильтр принимаемых данных

always @(posedge ti_60)

begin

if ((cta == 10'd256) | (cta == 10'd257) | (cta == 10'd258)) // по трем точкам

shift_left_rg <= {shift_left_rg[1:0], rx};

end

assign rx_filtr = (shift_left_rg == 3'b111) | (shift_left_rg == 3'b110)

| (shift_left_rg == 3'b101) | (shift_left_rg == 3'b011);

/////

always @ (posedge ti_60)

begin

if (e_wr_rg_rs232)

rg_rs232[ctb] <= rx_filtr;

end

 

always @ (posedge ti_60)

begin

stop <= seredina_bita & (ctb == 4'h8);

int <= stop;

end

 

////////////////////////////// перезапись в регистр

 

always @ (posedge ti_60)

begin

if (stop)

begin

rg_rs232_out <= rg_rs232[7:0];

ochibka_kadra <= ~rg_rs232[8];

end

end

endmodule

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


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

2 Sazh

:a14:

но по мне лучше бы народ сам учился - а то ведь так только баловать,

зато теперь ещё и синтаксис верилога объяснять придётся :laugh:

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


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

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

Мне это вообще говря не важно. Сдвиговый регистр вводился для того, чтобы привести сигнал в другое временное пространство и прибить (возможную) метастабильность. Одного каскада достаточно, а будет два или три - все равно, не играет большой рояли.

 

вообще говоря я уже упоминал о стилях программирования - повторюсь ещё раз на данном примере - не следует мешать в одном и том же блоке сигналы с переменными - они по природе разные и предназначены для разных вещей - из-за их смешивания легко запутаться в поведение сxемы.

хорошо бы подумать зачем в язык параллельный вводятся последовательные операторы - наверное чтобы упростить человеку восприятие сложных единомоментных вычислений (потому как человек в принципе привык думать последовательно)

Используя переменные, я как раз пытаюсь исправить стиль. Раньше все делал сигналами, и это сильно раздражало. С позиций "обычного программирования", сигнал - это переменная с областью видимости для всего модуля, а переменная - соответствует локальной переменной функции (т.е. процесса).

 

В программировании считается дурным стилем использовать переменные с большей чем необходимо областью видимости (как минимум, им приходится придумывать разные имена, а потом держать их в голове). Поэтому переменная предпочтительней сигнала во всех случаях, когда область ее видимости не должна выходить за пределы процесса. Читал, что есть и другое преимущество, а именно - на переменную тратится намного меньше PC-шных ресурсов при компиляции и симуляции.

 

Однако крайне неприятно что переменная по поведению отличается от сигнала, это по сути просто дрова какие-то. Не понимаю причин, нафиг именно так сделано.

 

Если можете подсказать как в VHDL сделать "локальный сигнал" без переменных, буду благодарен, я этого не умею.

 

дополнительную путаницу может произвести тактирование одного процесса несколькими клоками - это в принципе непрактично - связано опять же с тем же восприятием, когда человек читает код он видит последовательность строк сверху вниз - у вас же получается логика описаная на дне никак не связана с логикой наверху за исключением связи по данным - но данные - жто объекты над которыми совершается действие, а процессы - сами действия обвешанные аттрибутами (главным образом времени исполнения) получается что разные по сути и моменту исполнения действия (даже над одними объектами) у вас сгруппированы в одном процессе - что не гуд

Они сгруппированы не по времени, а по функциональности. Сначала я делаю некие действия, затем рассовываю почти неизмененные результаты в другие временные пространства.

 

и еще раз о списке чувствительности:

из этого списка process(Reset, CSn,SCLKin,CLK48,bit_cnt,cmd_gate) процесс не чувствителен к bit_cnt,cmd_gate

Ну как же так? К bit_cnt чувствителен вот этот оператор

   bit_cnt <= bit_cnt + "001"; -- count SCLK pulses

А к cmd_gate чувствителен вот этот

 
    RdWr_done <= shr(2) and (not cmd_gate);

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

 

Но главный вопрос остался открытым: симулятор показал одно (именно так, как я и представлял себе поведение этого кода), а на самом деле FPGA вела себя по-другому, а почему по-другому - я не понимаю.

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


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

Ну как же так? К bit_cnt чувствителен вот этот оператор

 

bit_cnt <= bit_cnt + "001"; -- count SCLK pulses

 

А к cmd_gate чувствителен вот этот

 

RdWr_done <= shr(2) and (not cmd_gate);

 

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

Если нет события "rising_edge", то изменения сигналов cmd_gate и bit_cnt, присутствующих в списке чувствительности, только впустую запустят процесс, который ничего не выполнит. Так что все же лучше будет (для скорости моделирования) их туда не включать.

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


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

Если нет события "rising_edge", то изменения сигналов cmd_gate и bit_cnt, присутствующих в списке чувствительности, только впустую запустят процесс, который ничего не выполнит. Так что все же лучше будет (для скорости моделирования) их туда не включать.

во истину так!

однако товарищ АК явно не желает вникать в предложенные ему обяснения, попробуем разобраться на простом примере - далее по аналогии

] a - сигнал

process(clk)
  if rising_edge(clk) then
    a <= a +1;
  end if;
end process;

если следуя логики (из-за того что он присутствует в правой части выражения) ввести его в список чувствинельности то какой эффект это даст

- а ровно никакого -

при любом изменеие сигнала а запустится процесс, и ничего не произойдёт - потому как первый же оператор - это проверка на передний фронт clk. если это не передний фронт clk то выполняется "ничего" - пустой отератор.

с точки зрения сxемотехники - а - это ячейка памяти тактируемая по фронту синхросигнала и ей всё равно изменяется ли сигнал на её входе или нет в момент тика синхросигнала - она защёлкнит всё что сотит у неё на входе - то есть индифирентна к состоянию входа = нечувствительна!

другое дело если б вводился сигнал асинхронного сброса - тогда бы он присутствовал в списке чувствительности:

always@ (posedge clk, negedge reset_n)
begin
  if (reset_n==1'b0)
   begin
    a<=0;
   end
  else
   begin
    a<=a+1;
   end
end

и третье дело когда описывается комбинационная логика:

process(a,b)
    c <= a AND b;
end process;

здесь оба сигнала стоящих справа должны быть в стиске чувствительности чтоби не получить защёлку вместо обычного логического И потому как любое изменение любого из правых сигналов может привести к изменению на выходе (c)

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


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

Мне это вообще говря не важно. Сдвиговый регистр вводился для того, чтобы привести сигнал в другое временное пространство и прибить (возможную) метастабильность. Одного каскада достаточно, а будет два или три - все равно, не играет большой рояли.

может и не важно но из всего этого многодневного разговора видно что вы не освоились в концепциях HDL-ей и отсюда не понимаете что у вас получется огромная разница между тем что вы стараетесь описать и тем что по заблуждению реально описываете (получается что вы с компилятором говорите на разных языках /интерпритация основных понятий/, хоть и используете одинаковые звуки/синтаксис/)

вы думаете что он синтезирует одно - а он реально синтезирует совершенно другое -

 

прочитайте внимательно ещё раз посты - там всё подробно объяснено что реально проишодит при обработке вашего кода компилятором

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


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

if (Reset='1') or (CSn='1') then
    bit_cnt <= "000";
  elsif rising_edge(SCLKin) then
    bit_cnt <= bit_cnt + "001"; -- count SCLK pulses
    if (bit_cnt = "101")  then
      pulse5 := '1';
    else
      pulse5 := '0';
    end if;

Хочу обратить Ваше внимание на одну мелочь:имхо было бы логичнее pulse5 прописать также в конструкции асинхронного сброса:

if (Reset='1') or (CSn='1') then
    bit_cnt <= "000";
    pulse5:='0';

или вообще вынести присвоение этой переменной из rising_edge...

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


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

Используя переменные, я как раз пытаюсь исправить стиль. Раньше все делал сигналами, и это сильно раздражало. С позиций "обычного программирования", сигнал - это переменная с областью видимости для всего модуля, а переменная - соответствует локальной переменной функции (т.е. процесса).

 

В программировании считается дурным стилем использовать переменные с большей чем необходимо областью видимости (как минимум, им приходится придумывать разные имена, а потом держать их в голове). Поэтому переменная предпочтительней сигнала во всех случаях, когда область ее видимости не должна выходить за пределы процесса. Читал, что есть и другое преимущество, а именно - на переменную тратится намного меньше PC-шных ресурсов при компиляции и симуляции.

1) вы уже не в программирование и стиль и тон здесь другие

2) в программирование области видимости переменных используются: а - для экономии оперативной памяти (при выходе из области видимости память отведённая под переменныю освобождается ; б - для экономии в пространстве имён (чтобы была возможность использования одних и тех же имён в разных функциях/файлах/библиотеках). в ВХДЛ же область видимости используется только для экономии в пространстве имён (так как при выходе из процесса значение переменной всё равно сохраняется - а значит память не освобождается)

принципиально же разница в том как происxодит присваивание переменным и сигналам (блокируемое и неблокируемое) относительно дельта-цикла - исxодя из этой разницы переменные целесообразно использовать в сложных логических конструкциях (подробнее об этом смотрите в постах выше - я об этом уже написал)

3) если вам нравятся аналогии с программированием то рассматривайте понятие функции из структурного программирования как аналог архитектуры в ВХДЛ но не кaк эквивалент процессу - вообще в ВХДЛ более сложная иерархия програмных блоков

Читал, что есть и другое преимущество, а именно - на переменную тратится намного меньше PC-шных ресурсов при компиляции и симуляции.

есть такая тема - тратится меньше как раз из-за концепции симуляционной (дельта-циклы извините за навязчивость cловечка :) ) модели и связанных с этим аттрибутов,

но поймите сигнал и переменная - принципиально разные объекты - и не потому что так кому-то захотелось а потому что они отисывают разные по природе явления

а вообще конечно в Верилоге с этим было бы попроще разобраться - он не такой прямоугольный - но это только личное впечатление

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


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

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

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

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

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

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

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

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

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

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