1

我正在为我的 Nexys2 板编写 RS232 模块。我目前的波特率控制器有问题,我想将其设置为 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 寄存器没有被创建或存储值,使用无符号时是否有问题?

为了确保三重,我什至已经从使用 VHDL 的 FPGA Prototyping 一书中复制了 mod-m 计数器(这是显示的代码)但是这仍然不起作用并且 q 输出是 UUUUUUUU。

如果有任何更好的方法可以从 nexys2 50mz 时钟创建波特率,那也将不胜感激!

干杯

4

1 回答 1

3

坦率地说,如果人们期望从一本提供此类示例的书中学习 VHDL,我感到很震惊。我知道作者有一本关于 Verilog 的类似书:人们最终会认为 VHDL 只是更冗长的 Verilog 吗?

具体批评(实际上是7,8更多的意见):

1) 虚假类型转换。Q 代表一个无符号数。所以让它不签名!

波特率发生器不是 FPGA 中唯一的东西,所以 Q 不太可能是片外端口。制作顶级片外端口 std_logic_vector 有很好的论据,但即使这样也不是强制性的。但是,如果您的客户的规范或编码风格坚持在端口上进行虚假类型转换;跟着它。

2)DRY原则:

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

发现维护的简化。
如果您在多个地方使用子类型,请将其放在一个包中;通用代码重用工具。

3) 缩进、格式化。(我认识到这可能已被编辑器设置弄乱了)。它增加了阅读它的大脑负荷。不过,我在这里所做的并不是 The One Way。

4) 假括号围绕逻辑表达式。无害,但看起来像 C 程序员的拐杖。

5) 古色古香的 clk'event 风格。明年,rising_edge 函数将大到可以饮用(在美国。在英国,它已经在每个星期六晚上都贴满了几年了......)

6) r_reg 和 r_next 的“双进程”风格。他是否也在 next_state 上编写了带有单独组合过程的状态机?鉴于此,我猜是这样。单进程状态机更容易、更小(写起来:它们不会生成更小的硬件)和更安全。

7) 我作弊了,我的tick 比原来晚了一个周期。如果这很关键,请恢复外部“tick”分配。我还让它同步,这将有助于提高性能。有些人更喜欢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;
于 2013-01-11T12:16:04.460 回答