Счетчик Mod-M Значения без знака не имеют сигнала

Я пишу модуль RS232 для своей платы Nexys2. В настоящее время у меня проблемы с контроллером скорости передачи данных, который я хочу установить на 19200.

Для этого я использую счетчик Mod-M, после многих симуляций ISim проблема с моим кодом заключается в счетчике mod-m, поскольку он не производит никаких тиков.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity baud_rate is
    generic (
    N: integer := 8;
    M: integer :=163);
    Port (clk, reset : in  STD_LOGIC;
           tick : out  STD_LOGIC;
              q : out STD_LOGIC_VECTOR(N-1 downto 0));

end baud_rate;

architecture Behavioral of baud_rate is
signal r_reg :  unsigned(N-1 downto 0);
signal r_next : unsigned(N-1 downto 0);
begin
process(clk,reset)
begin
    if (reset ='1') then
        r_reg <= (others=>'0');
    elsif(clk'event and clk='1') then 
    r_reg <= r_next;
    end if;
end process;

r_next <= (others =>'0') when r_reg=(M-1) else r_reg+1;
tick <='1' when r_reg=(M-1) else '0';
q <= std_logic_vector(r_reg);


end Behavioral;

Я протестировал все входы clk и работает нормально, и проблема, похоже, связана с регистрами r_reg и r_next. В ISim при выводе любого из них на q я получаю UUUUUUUU, поэтому кажется, что они не генерируют сигнал. Из этого я могу сделать вывод, что два регистра r_reg и r_next не создаются и не хранят значения, есть ли проблема при использовании без знака?

Чтобы убедиться втройне, я даже скопировал счетчик mod-m из книги «Прототипирование FPGA с VHDL» (который является показанным кодом), НО все равно это не работает, и вывод q — UUUUUUUU.

Если есть какие-либо лучшие способы создания скорости передачи из часов nexys2 50mz, это также будет оценено!

Ваше здоровье


person Sam Palmer    schedule 11.01.2013    source источник
comment
Поскольку вы не показали нам тестовый стенд, я должен спросить: вы подали сигнал сброса? Что случилось с r_reg, когда вы это сделали? Кроме того: это довольно плохой VHDL (хотя не так уж плохо, что он сломан); это действительно пришло из книги Понг Чу?   -  person user_1818839    schedule 11.01.2013
comment
Я не подавал сигнал сброса, и да, он взят из книги, так как я хотел убедиться, что он работает! Но я попытался использовать r_reg ‹= r_next за пределами события clk, чтобы проверить, были ли проблемы с часами, и все равно ничего.   -  person Sam Palmer    schedule 11.01.2013
comment
Я не устанавливал тестовый стенд, так как все, что он делает, это передача сигнала clk и считывание тиков и q (если бы вы могли указать мне какой-нибудь лучший код, я был бы очень признателен, даже будучи новичком, я нашел это довольно уродливым! )   -  person Sam Palmer    schedule 11.01.2013
comment
Ну вот вам и ответ. ЕДИНСТВЕННЫЙ выход из r_reg = UUUU находится в предложении Reset. Я добавлю ответ с более аккуратным, но непроверенным VHDL.   -  person user_1818839    schedule 11.01.2013
comment
большое спасибо, я просто принудительно сбросил на «1» на ISim, и когда я вывожу r_reg, я теперь получаю XXXXXXXX, так что я думаю, что теперь r_next ломается, когда я делаю r_reg ‹= r_next   -  person Sam Palmer    schedule 11.01.2013


Ответы (1)


Честно говоря, я в ужасе, если люди должны изучать VHDL по книге, в которой представлены подобные примеры. Я знаю, что у автора есть похожая книга по Verilog: неужели люди в конечном итоге думают, что VHDL — это просто более подробный Verilog?

Конкретные критические замечания (на самом деле 7,8 больше наблюдений):

1) Ложные преобразования типов. Q представляет беззнаковое число. Так сделайте его без подписи!

Генератор бод - не единственная вещь в вашей FPGA, поэтому Q вряд ли будет внешним портом. Есть веские аргументы в пользу создания внешних портов верхнего уровня std_logic_vector, но даже это не является обязательным. Однако, если спецификация вашего клиента или стиль кодирования настаивают на ложных преобразованиях типов в портах; Следуйте за ним.

2) СУХОЙ принцип:

package CPU_types is
    subtype baud_count is unsigned(7 downto 0);
end CPU_types;

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

3) Отступ, форматирование. (Я понимаю, что это могло быть искажено настройками редактора). Это увеличивает нагрузку на мозг при чтении. Однако то, что я здесь сделал, не является Единственным Путем.

4) Ложные скобки вокруг логических выражений. Безобидно, но похоже на костыли для C-программистов.

5) Старинный стиль clk'event. В следующем году функция Rising_Edge станет достаточно старой, чтобы ее можно было пить (в Америке. В Британии ее намазывают каждую субботу вечером уже пару лет...)

6) Стиль "два процесса" с r_reg и r_next. Он тоже пишет конечные автоматы с отдельным комбинационным процессом на next_state? Учитывая это, я так предполагаю. Конечные автоматы с одним процессом проще, меньше (для записи: они не генерируют меньшее оборудование) и безопаснее.

7) Я сжульничал, и мой тик на один цикл позже, чем в оригинале. Если это критично, восстановите внешнее «галочное» назначение. Я также сделал его синхронным, что поможет производительности. Некоторые люди предпочли бы tick <= '0' в предложении else; однако присваивание по умолчанию, которое я использовал, безопасно и предотвращает множество ошибок (и ненужных предложений else) в больших проектах.

8) Присвоение Q также может быть введено в процесс; если бы вы сделали r_reg переменной процесса, вам пришлось бы это сделать. Есть место для других вариаций и предпочтений.

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;
    use CPU_types.all;

    entity baud_rate is
        generic (
            M: integer := 163);
        Port (
            clk, reset : in  STD_LOGIC;
            tick : out  STD_LOGIC;
            q    : out baud_count);  
    end baud_rate;

    architecture Behavioral of baud_rate is
        signal r_reg : baud_count;
    begin

    process(clk,reset)
    begin
        if reset ='1' then
            r_reg <= (others=>'0');
        elsif rising_edge(clk) then 
            tick  <= 0;
            r_reg <= r_reg+1;
            if r_reg = M then 
                tick  <= '1';
                r_reg <= (others=>'0');
            end if;
        end if;
    end process;

--    tick <='1' when r_reg = M-1 else '0';
--    or simpler, when r_reg = 0
    q <= r_reg;

    end Behavioral;
person user_1818839    schedule 11.01.2013
comment
Спасибо за отличный ответ, очень признателен! - person Sam Palmer; 11.01.2013
comment
Single process state machines are easier, smaller (to write : they don't generate smaller hardware) - большего железа они тоже не генерируют :) - person Martin Thompson; 11.01.2013
comment
@BrianDrummond Учитывая, насколько уродлив исходный код, я вполне мог что-то упустить из виду, но разве строка if r_reg = M then не должна быть на самом деле if r_reg = M-1 then? Я думаю, что то, как вы закодировали это, заставляет r_reg считать от 0 до M включительно, что приведет к тому, что ваши тики будут на один цикл дальше друг от друга, чем в оригинале. Обратите внимание, что r_reg не является переменной, поэтому присваивание r_reg <= r_reg+1; не повлияет на оператор if! - person zennehoy; 11.01.2013
comment
@Zennehoy: совершенно верно! Теперь, если бы R_Reg был переменной, а не сигналом, мой код был бы правильным! (потому что он проверяется после приращения). Конечно, мы не знаем, откуда взялось магическое значение для М. Общая должна быть скоростью передачи данных, а M должна быть внутренней константой, рассчитанной из нее и периода часов... - person user_1818839; 11.01.2013
comment
привет, я просто тестирую это сейчас, извините, у меня был напряженный день, но дам вам знать, как это работает! - person Sam Palmer; 11.01.2013
comment
К сожалению не работает, галочка не ставится и q по прежнему хххххххх, но огромное спасибо за подсказки очень помогли если ничего не помогло! - person Sam Palmer; 11.01.2013
comment
Хотя я только что понял, что есть какое-то действие, после 60 пс тиковая линия переходит от U-> 0, а q переходит от UUUUUUUU -> XXXXXXXX, так что что-то происходит. Я поработаю и дам вам знать - person Sam Palmer; 11.01.2013
comment
Даже если установить сброс на 1, а затем снова установить его на 0 через 20 пс, q все еще XXXXXXXX. Из этого я делаю вывод, что это проблема в настройке r_reg (которая также является проблемой с исходным кодом), но я действительно не вижу ничего плохого! - person Sam Palmer; 11.01.2013
comment
Одна вещь, которую вы могли бы попробовать (и, желательно, сделать привычкой), это инициализировать ваши сигналы. Измените объявление сигнала для r_reg на: signal r_reg : baud_count := (others=>'0'); и посмотрите, поможет ли это. - person zennehoy; 11.01.2013
comment
@zennehoy: это не плохая привычка, но здесь она может мешать правильному пониманию того, что происходит. Лучшим предложением будет тестовый стенд VHDL, который работает в течение нескольких тактов. (Установите общее значение 5 или что-то подобное, когда вы создаете экземпляр счетчика в ТБ. Сохраняет ожидание!) - person user_1818839; 11.01.2013
comment
это было решено, проблема заключалась в том, что мне понадобился тик после того, как я использовал более позднее назначение тика, проблема заключалась в том, что r_reg обрабатывается вне процесса. - person Sam Palmer; 11.01.2013