Question

I am writing a RS232 module for my Nexys2 board. I am currently having issues with my baud rate controller which I want to set to 19200.

For this I am using a Mod-M counter, after many ISim simulations the problem with my code is in the mod-m counter as it is not producing any ticks.

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;

I have tested and all the clk inputs and run fine and the issue seems to be with the r_reg and r_next registers. In ISim when outputing either of these on q I get UUUUUUUU, so it seems they are not generating signal. From this i can infer that the two r_reg and r_next registers aren't being created or storing values, is there an issue when using unsigned?

To make triple sure I have even copied the mod-m counter from the book FPGA Prototyping with VHDL (which is the code shown) BUT still this does not work and q output is UUUUUUUU.

If there are any better ways of creating a baud rate from the nexys2 50mz clock that would also be appreciated!

Cheers

Was it helpful?

Solution

Frankly I am horrified if people are expected to learn VHDL from a book where examples like this are presented. I know the author has a similar book on Verilog : do people end up thinking VHDL is just a more verbose Verilog?

Specific criticisms (actually 7,8 are more observations):

1) Spurious type conversions. Q represents an unsigned number. So make it unsigned!

The baud generator isn't the only thing in your FPGA so Q isn't likely to be an off-chip port. There are good arguments for making top level, off-chip ports std_logic_vector but even that isn't compulsory. However, if your customer's specification or coding style insists on spurious type conversions on ports; follow it.

2) the DRY principle:

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

Spot the simplification in maintenance.
If you are using a subtype in several places, put it in a package; the universal code reuse tool.

3) Indentation, formatting. (I recognise that may have become garbled by editor settings). It adds to the brain load reading it. What I've done here isn't The One Way though.

4) Spurious brackets round logical expressions. Harmless, but look like crutches for C programmers.

5) Antique clk'event style. Next year, the rising_edge function will be old enough to drink (in America. In Britain it's been getting plastered every Saturday night for a couple of years now...)

6) The "two process" style with r_reg and r_next. Does he also write state machines with a separate combinational process on next_state? Given this, I'm guessing so. Single process state machines are easier, smaller (to write : they don't generate smaller hardware) and safer.

7) I cheated and my tick is one cycle later than in the original. If that is critical, restore the external "tick" assignment. I also made it synchronous vhich will help performance. Some people would prefer tick <= '0' in an else clause; however the default assignment I used is safe, and prevents a lot of mistakes (and unnecessary else clauses) in larger designs.

8) The assignment to Q can be brought into the process too; if you made r_reg a process variable you'd have to. There is room for other variations and preferences.

    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;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top