Self implemented UART in VHDL always skips second character - vhdl

I am learning VHDL right now and I tried to implement UART (1 start bit, 8 data bits, 1 stop bit) to periodically send a hardcoded string.
Everything works as expected - I receive string every 1 second. However, there is no second character.
No matter how long the string is, which character it is. I checked this fact on a oscilloscope and there is no waveform for this particular character. 1 start bit, 8 bits for first character, stop bit, start bit and 8 bits for third character, not the second one.
Following code is for 10 MHz clock divided to send with ~38 400 bits per second, I also tried with 9600 bits per second, both the same problem.
I'm using Altera MAX10 dev board: http://maximator-fpga.org/
Short video how it works:
https://gfycat.com/JoyousIlliterateGuillemot
UART.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.ALL;
use ieee.std_logic_arith.all;
entity UART is
port (
clk_10mhz: in STD_LOGIC;
txPin: out STD_LOGIC
);
end entity;
architecture Test of UART is
signal txStart: STD_LOGIC;
signal txIdle: STD_LOGIC;
signal txData: STD_LOGIC_VECTOR(7 downto 0);
component TX is
port (
clk_in: in STD_LOGIC;
start: in STD_LOGIC;
data: in STD_LOGIC_VECTOR(7 downto 0);
tx: out STD_LOGIC;
txIdle: out STD_LOGIC
);
end component TX;
begin
process (clk_10mhz, txIdle)
variable clkDividerCounter : integer range 0 to 10000000;
variable textToSend : string(1 to 31) := "Hello darkness my old friend!" & CR & LF;
variable currentCharacterIndex : integer range 0 to 31;
begin
if (rising_edge(clk_10mhz)) then
if (clkDividerCounter < 10000000) then
clkDividerCounter := clkDividerCounter + 1;
else
clkDividerCounter := 0;
currentCharacterIndex := 1;
end if;
if (txIdle = '1' and currentCharacterIndex > 0) then
txData <= CONV_STD_LOGIC_VECTOR(character'pos(textToSend(currentCharacterIndex)),8);
txStart <= '1';
if (currentCharacterIndex < 31) then
currentCharacterIndex := currentCharacterIndex + 1;
else
currentCharacterIndex := 0;
txStart <= '0';
end if;
end if;
end if;
end process;
u1: TX port map (clk_10mhz, txStart, txData, txPin, txIdle);
end Test;
TX.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.ALL;
entity TX is
port (
clk_in: in STD_LOGIC;
start: in STD_LOGIC;
data: in STD_LOGIC_VECTOR(7 downto 0);
tx: out STD_LOGIC;
txIdle: out STD_LOGIC
);
end entity;
architecture Test of TX is
signal idle: STD_LOGIC;
begin
process (clk_in)
variable bitIndex : integer range 0 to 9;
variable clkDividerCounter : integer range 0 to 260;
variable dataFrame : STD_LOGIC_VECTOR(9 downto 0);
variable dataFrameCurrentIndex : integer range 0 to 9;
begin
if (rising_edge(clk_in)) then
if (start = '1' and idle = '1') then
dataFrame(0) := '0';
dataFrame(8 downto 1) := data;
dataFrame(9) := '1';
dataFrameCurrentIndex := 0;
idle <= '0';
end if;
if (idle = '0') then
if (clkDividerCounter < 260) then
clkDividerCounter := clkDividerCounter + 1;
else
if (dataFrameCurrentIndex <= 9) then
tx <= dataFrame(dataFrameCurrentIndex);
dataFrameCurrentIndex := dataFrameCurrentIndex + 1;
else
idle <= '1';
end if;
clkDividerCounter := 0;
end if;
end if;
txIdle <= idle;
end if;
end process;
end Test;

Move the line
txIdle <= idle;
from TX.vhd outside the process. Signals take their new value after the process ends.
For example:
idle <= '0';
txIdle <= idle;
Will set txIdle to '1' if idle was '1' when the two statements were executed inside a process. You should notice that this means that txIdle will be '1' for two consecutive cycles and causes currentCharacterIndex to increment twice at the start.
Note that contrary to signals, variable take their new value when the assigning statement is encountered, and not at the end of the process as signals do.
While your code is not that terrible for a beginner, I recommend to use only signal when you start learning VHDL. It is much easier to make mistake with variables, or describe sub-optimal or broken implementation.
Also, as Brian mentioned, don't use std_logic_arith, especially when using numeric_std. They are conflicting with each other (some tools deal with it though) and std_logic_arith is not a IEEE standard, while numeric_std is.
Finally, simulation is a crucial part of hardware design. To avoid uninitialized pin, add a reset to your circuit, which is generally a good idea.

Related

Would like someone to double check code for 8bit up counter with enable

I am a novice coder and don't know if what I did was correct so I would appreciate if someone could double check it for me.
So im trying to make an 8-bit up counter with an active-low count enable control signal. The counter should advance to the next count if cten = 0 and stops at the current count if cten = 1. The counter resets into a state that outputs binary 0 and progresses upward on each clock edge when counting is enabled until it reaches 255. It locks in the state producing output 255. I also tried to change the clock to 1Hz clock from a 50MHz clock the is on a FPGA board that will be used to run some instructions (with there being no more than 255 instructions, hence wanting to lock at that number) based off the count value of int_q.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity counter is
port(
clk, rst, cten: in std_logic;
q: out std_logic_vector(7 downto 0)
);
end entity counter;
architecture moore of counter is
signal d,int_q: std_logic_vector(7 downto 0);
signal cnt: integer range 0 to 25000;
signal clk1Hz: std_logic;
begin
-- drive internal Q signal to output signal
q <= int_q;
-- next-state logic: add 1 unless 255, lock at 255
d <= int_q+1 when int_q < 255;
d <= int_q when int_q = 255;
process(clk)
begin
if rising_edge(clk) then
cnt <= cnt+1;
if cnt = 25000 then
clk1Hz <= not clk1Hz;
cnt <= 0;
end if;
end if;
end process;
-- register process
process(all)
begin
if rising_edge(clk1Hz) then
if rst ='1' then int_q <= "00000000";
elsif cten = '0' then int_q <= int_q+1;
else int_q <= int_q;
end if;
end if;
end process;
end architecture moore;
Several issues:
If rst is unasserted on the rising edge of clk1Hz, then int_q will remain in an unknown state.
clk1Hz is never initialized, so the not operation does nothing.
cnt is never initialized, so incrementing it does nothing.
int_q is being driven in 2 places: both inside and outside a process.
signal d is unused, did you want to connect it to q?
You're only counting to 25_000, but if your source clock is 50 MHz, you need to count to 25_000_000.
If you want a synchronous reset, (which given the name "Moore", I bet this is homework), it's good practice to create a new process specifically to internally synchronize that async reset signal to the system clock, maybe through a 2FF synchronizer for one idea.
If I understood the question correctly, this should get you in the ballpark:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity counter is
port(
clk, rst, cten: in std_logic;
q: out std_logic_vector(7 downto 0)
);
end entity counter;
architecture moore of counter is
signal int_q: std_logic_vector(7 downto 0);
signal cnt: integer range 0 to 25_000_000;
signal clk1Hz: std_logic;
begin
-- indicate when at 255
q <= '1' when int_q = 255 else '0';
process(rst, clk)
begin
if rst = '1' then
-- need to assign initial values
clk1Hz <= '0';
cnt <= 0;
elsif rising_edge(clk) then
if cnt = 25_000_000 then
clk1Hz <= not clk1Hz;
cnt <= 0;
else
cnt <= cnt+1;
end if;
end if;
end process;
-- register process
process(rst, clk1Hz)
begin
if rst = '1' then
int_q <= (others => '0');
elsif rising_edge(clk1Hz) then
if cten = '0' then
int_q <= int_q+1; -- rolls over
end if;
end if;
end process;
end architecture moore;
If you want to map this in an FPGA you cannot generate a clock like you do. Clocks are very special signals with strict electrical requirements. If you need a 1Hz frequency clock and the frequency of your master clock is 50MHz there are basically two options:
Use a clock manager/generator hard macro of your FPGA if it has some, and configure it to generate a 1Hz clock from your master clock. Explicitly pass the output through a clock buffer if your tools don't do it automatically.
Do not generate a 1Hz clock, use an enable signal that you assert high once every 50M clock periods. Or use a rescaler and increment your counter only when the rescaler reaches a predefined value.
As the first option depends on your FPGA, your tools, etc. let's investigate the second:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter is
generic(freqHz: positive := 50000000);
port(clk, rst, cten: in std_ulogic;
q: out std_ulogic_vector(7 downto 0));
end entity counter;
architecture moore of counter is
signal rescaler: integer range 0 to freqHz - 1;
signal cnt: integer range 0 to 255;
begin
q <= std_ulogic_vector(to_unsigned(cnt, 8));
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
rescaler <= freqHz - 1;
cnt <= 0;
elsif cnt /= 255 then
if rescaler /= 0 then
rescaler <= rescaler - 1;
else
rescaler <= freqHz - 1;
cnt <= cnt + 1;
end if;
end if;
end if;
end process;
end architecture moore;
Remarks:
Use ieee.std_logic_unsigned or ieee.numeric_std but not both. And as noted by #JHBonarius, do not use ieee.std_logic_unsigned at all. It is not standard and deprecated. Use ieee.numeric_std_unsigned, instead.
I added a generic parameter (freqHz) with a default value such that you can easily adapt to different clock frequencies.
The 50Mhz to 1Hz rescaler is decremented instead of incremented because a hardware zero detector is frequently slightly smaller and faster than an arbitrary value detector.
If you do not know the difference between std_logic and std_ulogic, always use std_ulogic, never std_logic (and use std_ulogic_vector instead of std_logic_vector, u_unsigned instead of unsigned...) One day or another you will really need std_logic and this day you will understand the difference, and why you should (almost) never use it. And do not listen to people who tell you that std_logic is more standard or better supported by the tools or whatever. They are wrong. The only exception is your teacher or your boss: even if they are wrong, it might be better to obey.

Why does the output signals post-synthesis not work as usual?

I had written a small VHD file for simulating the behavior of a quadrature decoder, enclosed below. Simulating the design with a generic testbench works as expected. But after generating a synthesizable design with Quartus, I run into one of two problems (while playing with using unsigned, for example)
1. The position and direction signal are always at a constant 0 value throughout the post-synthesis simulation.
2. The position value seems to jump 10 values every 3-4 clock cycles, which I attribute to some jitter in data.
Does anyone have any recommendations to solve this issue? Is this mainly a timing problem or is there a major flaw in my design?
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.NUMERIC_STD.ALL;
entity quad_decoder is
port(rst : in std_logic;
clk : in std_logic;
a : in std_logic;
b : in std_logic;
direction : out std_logic;
position : out std_logic_vector(8 DOWNTO 0));
end quad_decoder;
architecture behavioral of quad_decoder is
begin
process(clk)
variable counter : integer range 0 to 360 := 0;
variable chanA,chanB : std_logic;
variable int_direction : std_logic;
begin
if (rst = '0') then
int_direction := '0';
counter := 0;
elsif (rising_edge(clk)) then
chanA := a;
chanB := b;
if (chanA = '1') and (chanB = '0') then
if (counter = 360) then
counter := 0;
else
counter:= counter + 1;
end if;
int_direction := '1';
elsif (chanA = '0') and (chanB = '1') then
if (counter = 0) then
counter := 360;
else
counter := counter-1;
end if;
int_direction := '0';
else
counter := counter;
int_direction := int_direction;
end if;
position <= std_logic_vector(to_unsigned(counter,9));
direction <= int_direction;
end if;
end process;
end behavioral;
The expected pre-synthesis snap is here.
I've linked an example snap of the post-synthesis simulation here. As seen, no change to position nor direction in multiple clock cycles.
If anyone is inquisitive, doing assignments right at the clock edge as well as turning the reset signal high proved to introduce all kinds of timing issues, which passed the multi-corner timing analysis test, but failed other tests in Quartus that I had failed to notice.
I can go into more details if my answer is vague.

Vhdl, is there a way, to use modulo on larger than 64 bits unsigned?

I've got two 115bits unsigned vectors. I have to do some mod calculations on them, but Quartus shows those errors.
Error: In lpm_divide megafunction, LPM_WIDTHN must be less than or equals to 64
Error: In lpm_divide megafunction, LPM_WIDTHD must be less than or equal to 64
Error: Can't elaborate inferred hierarchy "lpm_divide:Mod0"
I fully understand, that numbers are too large to perform mod. Is there a way/library/any idea how to solve this problem? I would love to avoid using any "substracting loop", and be as simple as possible. VHDL is not my world, and after academic project I will abandon it with pleasure :P
Application has to calculate modulo inversion. As far as I am not master from VHDL, I've tried doing it using fast powering + mod alghoritm. Application can sucks, it just has to work :d
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.all;
library altera;
use altera.altera_primitives_components.all;
entity inwersja is
port(
a: in unsigned(114 downto 0);
clk: in std_logic;
start: in std_logic;
reset: in std_logic;
c: out unsigned(114 downto 0);
ready: out std_logic);
end inwersja;
architecture i1 of inwersja is
begin
process(clk)
variable tempOutput : unsigned(114 downto 0) := "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
variable temp : unsigned (114 downto 0):= a;
variable modul: unsigned(114 downto 0) := "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101011";
variable power: unsigned(114 downto 0) := "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101001";
variable counter: integer := 0;
begin
if reset='1' then
tempOutput := "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
ready <= '0';
elsif clk'event and clk='1' then
if start='0' then
ready<='0';
else
if (counter < 115) then
if (power(counter) /= '0') then
tempOutput := (tempOutput * temp) mod modul;
end if;
temp := (temp * temp) mod modul;
counter := counter + 1;
elsif (counter = 115) then
ready <= '1';
end if;
end if;
end if;
c <= tempOutput;
end process;
end i1;

Unwanted one clock delay vhdl

can someone explain me why I have one clock delay on my simulation of the following and how can I fix it, it shouldnt be there cause I am missing a bit on the output....
entity outBit is
port( clk1 : in STD_LOGIC;
clk2 : in STD_LOGIC;
-- reset : in STD_LOGIC;
int_in : in INTEGER;
bit_out : out STD_LOGIC); --_VECTOR of 32
end outBit ;
Is my entity and every rising edge of clk 1 it takes an integer. According to what integer it is(1, 2, 3, 4...) it chooses the corresponding line of an array. That line is of 32 bits. I want to output one bit of the 32 each clk2. For example if clk1 = 100 then clk2 = 100/32.
architecture Behavioral of outBit is
signal temp : array; --the array is fixed
signal output_bits : std_logic_vector(31 downto 0);
signal bit_i : integer := 31; --outputting a single bit out of 32 each time
begin
temp(0) <= "11111111111111111111111111111111";
temp(1) <= "11111111111111111111111111111110";
temp(2) <= "11111111111111111111111111111100";
-- etc
output_bits <= temp(int_in);
process(clk2)
--outputting a single bit out of 32 each time
--variable bit_i : integer := 31;
begin
if rising_edge(clk2) then
bit_out <= output_bits(bit_i);
if bit_i = 0 then
bit_i <= 31;
else
bit_i <= bit_i - 1;
end if;
end if;
end process;
end Behavioral;
The unwanted delay is shown below. I would like each 32 cycles to read the new line (according to the input integer) and so on....
BY the way the firstclock (in code),(second clock in picture) is not really relative to the question is just to get the idea when the integer is coming
If you want to get rid of the bit_out delay don't make it a flip flop:
library ieee; -- add missing context clause
use ieee.std_logic_1164.all;
entity outbit is
port (
-- clk1: in std_logic; -- not relevant
clk2: in std_logic;
-- reset: in std_logic;
int_in: in integer;
bit_out: out std_logic --_vector of 32
);
end entity outbit;
architecture behavioral of outbit is
type bit_array is array (0 to 3) of std_logic_vector(0 to 31); -- added
signal temp : bit_array; --the array is fixed -- non_reserved word name
signal output_bits : std_logic_vector(31 downto 0);
subtype index_int is integer range 0 to 31; -- changed bit_i type
signal bit_i: index_int := 31; --outputting a single bit out of 32 each time
begin
temp(0) <= "11111111111111111111111111111111";
temp(1) <= "11111111111111111111111111111110";
temp(2) <= "11111111111111111111111111111100";
temp(3) <= "11011001110000110101001000101110"; -- added
-- etc
output_bits <= temp(int_in);
process(clk2)
--outputting a single bit out of 32 each time
--variable bit_i : integer := 31;
begin
if rising_edge(clk2) then
-- bit_out <= output_bits(bit_i); -- moved
if bit_i = 0 then
bit_i <= 31;
else
bit_i <= bit_i - 1;
end if;
end if;
end process;
bit_out <= output_bits(bit_i); -- moved to here
end architecture behavioral;
Move the bit_out assignment outside the clock conditioned if statement. (It can be a concurrent signal assignment and represents a 32:1 multiplexer).
Add a test bench to complete a Minimal, Complete, and Verifiable example:
library ieee;
use ieee.std_logic_1164.all;
entity outbit_tb is
end entity;
architecture foo of outbit_tb is
signal clk2: std_logic := '1';
subtype temp_index is integer range 0 to 3;
signal int_in: temp_index := 3;
signal bit_out: std_logic;
begin
CLOCK:
process
begin
wait for 5 ns; -- so can multiply clocks in my head to get stop time
clk2 <= not clk2;
if now > 360 ns then
wait;
end if;
end process;
DUT:
entity work.outbit
port map (
clk2 => clk2,
int_in => int_in,
bit_out => bit_out
);
end architecture;
And the delay is gone:

Bit shift register vhdl varying size

I'm trying to get two outputs (pulse(0) and pulse(1)) to deliver a short one clock pulse. The latency between these pulses needs to be controlled by some input value. So 0x1 = 1 clock cycle etc.
At the moment, once the trigger switches on, it stays on
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use work.ipbus.all;
<...snip>
architecture rtl of trig_latency is
signal ack : std_logic;
signal s_level : unsigned(pulse'range);
signal s_level_d1 : std_logic;
signal bit_shift : std_logic_vector(addr_width downto 0);
signal latency: integer:=5;
begin
latency <= to_integer(unsigned(in_data(addr_width -1 downto 0))) when addr_width > 0 else 0;
process(clk)
begin
if rising_edge(clk) then
if ipbus_in.ipb_strobe='1' and ipbus_in.ipb_write = '1' then
s_level <= s_level + 1;
s_level_d1<=s_level(s_level'left);
else
s_level<=(others=>'0);
end if;
bit_shift <= bit_shift(bit_shift'high-1 downto 0) & (s_level(s_level'left) and (not s_level_d1));
ipbus_out.ipb_rdata <= (others => '0');
ack <= ipbus_in.ipb_strobe and not ack;
pulse(0) <= s_level(s_level'left) and (not s_level_d1);
pulse(1)<=bit_shift(latency);
end if;
end process;
ipbus_out.ipb_ack <= ack;
ipbus_out.ipb_err <= '0';
end rtl;
Why can't you just shift your bits the whole way and ignore the fact that they go above N. The usual VHDL shifter uses the & to concatenate the shifted register with the new value:
bit_shift <= bit_shift(bit_shift'high-1 downto 0) & s_level;
That should produce your shift register just fine.
The pulse(1) <= bit_shift(N) ought to work fine.

Resources