I've written code for a binary divider that takes in an 8 bit dividend, 3 bit divisor, and gives a 5 bit quotient (3 bit remainder). I've literally spent hours trying to fix a bug that gives incorrect results but I haven't been able to identify it. Any help would be GREATLY appreciated! I basically get wrong answers for my inputs but I can't figure out why. There is a bus that takes in values and on the first clock cycle where st is 1, the dividend register is loaded. On the second clock cycle after, the divisor register is loaded and the calculation is made for the next three clock cycles.
The V signal is the output to signify that an overflow has occured (the result can't be fit into the five bits of the quotient), my st is the start signal to start the process, sh is the shift signal for the shift register, su is the subtract signal for the subtractor.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity Divider is
Port (bus_in: in std_logic_vector(8 downto 0);
St, Clk, reset: in std_logic;
Quotient: out std_logic_vector(4 downto 0);
Remainder: out std_logic_vector(2 downto 0);
v: out std_logic);
end Divider;
architecture Behavioral of Divider is
signal State, NextState: integer range 0 to 5;
signal C, Ld1, Ld2, Su, Sh: std_logic;
signal Divisor: std_logic_vector(2 downto 0);
signal Subout: std_logic_vector(3 downto 0);
signal Dividend: std_logic_vector(8 downto 0);
begin
Subout <= Dividend(8 downto 5) - ('0' & divisor);
C <= not Subout (3);
Remainder <= Dividend(7 downto 5);
Quotient <= Dividend(4 downto 0);
State_Graph: process (State, St, C)
begin
Ld1 <= '0';
Ld2<='0';
v <= '0';
Sh <= '0';
Su <= '0';
case State is
when 0 =>
if (St = '1') then
Ld1 <= '1';
NextState <= 1;
else
NextState <= 0;
end if;
when 1 =>
if (St = '1') then
Ld2 <= '1';
NextState <= 2;
else
Ld2<='1';
NextState <= 2;
end if;
when 2 =>
if (C = '1') then
v <= '1';
NextState <= 0;
else
Sh <= '1';
NextState <= 3;
end if;
when 3 | 4 =>
if (C = '1') then
Su <= '1';
NextState <= State;
else
Sh <= '1';
NextState <= State + 1;
end if;
when 5 =>
if (C = '1') then
Su <= '1';
end if;
NextState <= 0;
end case;
end process State_Graph;
Update: process (Clk)
begin
if Clk'event and Clk = '1' then
State <= NextState;
--if Load = '1' then
-- Dividend <= '0' & bus_in;
--end if;
if Ld1 = '1' then
Dividend <= '0'&Bus_in(7 downto 0);
end if;
if Ld2 = '1' then
Divisor <= Bus_in(2 downto 0);
end if;
if Su = '1' then
Dividend(8 downto 5) <= Subout;
Dividend(0) <= '1';
end if;
if Sh = '1' then --94
Dividend <= Dividend(7 downto 0) & '0';
end if;
end if;
end process update;
end Behavioral;
Here's my input and outputs:
[Signals]: http://imgur.com/fqfiYJZ 1
The picture shows that my registers for the divisor and dividend is loading correctly. So I think the issue is with the actual division code. The state machine also seems to be working correctly.
Don't write this yourself. You are re-inventing the wheel.
Either write q <= a / b;
or use an IP core from your FPGA vendor.
Related
I made a counter 1-30. but I got this
My schematic here. I remove counter0-3
and It's here I found the problem here. It's the clock connected with a new loop
So I want to increase the size of the clock. Like this
I'm a rookie here, I don't know how to do that. Please give me an idea, thanks
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity counter0_9x is
port(
clk : in std_logic;
clk_B : in std_logic;
reset : in std_logic;
counter : out std_logic_vector(3 downto 0);
clk_o : out std_logic
);
end counter0_9x;
architecture Behavioral of counter0_9x is
signal counter_up : std_logic_vector(3 downto 0);
begin
process(clk,reset)
variable num : integer := 0;
begin
if(reset='1')then
counter_up <= "0000";
elsif(clk'event and clk = '1')then
if clk_B = '0' then
if num <= 2 then
if counter_up = "1001" then
counter_up <= "0000";
num := num + 1;
clk_o <= '1';
else
counter_up <= counter_up + '1';
clk_o <= '0';
end if;
else
if counter_up = "0000" then
counter_up <= "0000";
num := 0;
clk_o <= '1';
else
counter_up <= counter_up + '1';
clk_o <= '0';
end if;
end if;
end if;
end if;
end process;
counter <= counter_up;
end Behavioral;
Update!!!
I have tried combinational but I still can't shrink "clk_o"
architecture Behavioral of counter0_9x is
signal counter_up : std_logic_vector(3 downto 0);
begin
process(clk,reset)
variable num : integer range 0 to 2 := 0;
begin
if(reset='1')then
counter_up <= "0000";
elsif(clk'event and clk = '1')then
if clk_B = '0' then
if num <= 1 then
if counter_up = "1001" then
counter_up <= "0000";
num := num + 1;
else
counter_up <= counter_up + '1';
end if;
else
if counter_up = "0000" then
counter_up <= "0000";
num := 0;
else
counter_up <= counter_up + '1';
end if;
end if;
end if;
end if;
end process;
counter <= counter_up;
with counter_up select
clk_o <= '1' when "0000",
'0' when others;
end Behavioral;
At firth sight this is caused by assigning the signal ("clk_o") insight a sequential process (process that is (edge) triggered by your clock).
This creates a flipflop that stores the signal value until the next rising edge of the clock.
You want to achive combinational logic. You have to create a separate process for the assignment of signal "clk_o" without any clock. (Don't forget to add the necessary signals to the sensitivity list.)
It might also be helpful to visualize the synthesis of your vhdl code using pen and paper to better predict the extracted logic.
I'm trying to implement an alarm module for the digital clock in VHDL. I have written architecture for it, but when I run Compilation I get too many Adaptive Logic Modules (around 2000), which I think is too much. I will post my code below.
I think division and modulus operation could be causing it, in this line of code.
alarm_hour1 <= std_logic_vector(to_unsigned(savedHours/10,alarm_hour1'length));
alarm_hour0 <= std_logic_vector(to_unsigned(savedHours mod 10,alarm_hour0'length));
alarm_minute1 <= std_logic_vector(to_unsigned(savedMinutes/10,alarm_minute1'length));
alarm_minute0 <= std_logic_vector(to_unsigned(savedMinutes mod 10,alarm_minute0'length));
Still, I'm not sure how can I work around this.
Also, I would be very grateful if You give more comments on my design, and point out some mistakes, and ways how I can improve my design. I'm fairly new to VHDL so any advice is appreciated.
Thanks a lot.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity alarm is
port(
--INPUTS
reset : in std_logic;
clock : in std_logic;
alarm_enable : in std_logic;
alarm_set : in std_logic;
alarm_increment : in std_logic;
alarm_decrement : in std_logic;
currentTime_hour1 : in std_logic_vector(3 downto 0);
currentTime_hour0 : in std_logic_vector(3 downto 0);
currentTime_minute1 : in std_logic_vector(3 downto 0);
currentTime_minute0 : in std_logic_vector(3 downto 0);
--OUTPUTS
alarm_buzzer : out std_logic;
alarm_hour1 : buffer std_logic_vector(3 downto 0) := "0000";
alarm_hour0 : buffer std_logic_vector(3 downto 0) := "0000";
alarm_minute1 : buffer std_logic_vector(3 downto 0) := "0000";
alarm_minute0 : buffer std_logic_vector(3 downto 0) := "0000"
);
end alarm;
architecture alarmBehaviour of alarm is
--ALARM TIME
signal savedHours : integer := 0;
signal savedMinutes : integer := 0;
signal incrementDecrementbuttonDetect : std_logic;
signal set_lastButtonState : std_logic := '0';
signal setButtonDetect : std_logic := '0';
--STATE MACHINE
type state_type is (idle, setHour, setMinute);
signal state_reg, state_next : state_type;
begin
incrementDecrementbuttonDetect <= alarm_increment or alarm_decrement;
--STATE REGISTER
process(clock, reset)
begin
if (reset = '1') then
state_reg <= idle;
elsif rising_edge(clock) then
state_reg <= state_next;
end if;
end process;
--SET BUTTON PRESSED
process(clock)
begin
if(rising_edge(clock)) then
if(alarm_set = '1' and set_lastButtonState = '0') then
setButtonDetect <= '1';
else
setButtonDetect <= '0';
end if;
set_lastButtonState <= alarm_set;
end if;
end process;
--NEXT STATE
process(state_reg, setButtonDetect)
begin
case state_reg is
when idle =>
if setButtonDetect = '1' then
state_next <= setHour;
else
state_next <= idle;
end if;
when setHour =>
if setButtonDetect = '1' then
state_next <= setMinute;
else
state_next <= setHour;
end if;
when setMinute =>
if setButtonDetect = '1' then
state_next <= idle;
else
state_next <= setMinute;
end if;
end case;
end process;
process (incrementDecrementbuttonDetect, state_reg)
begin
if rising_edge(incrementDecrementbuttonDetect) then
case state_reg is
when idle =>
when setHour =>
if alarm_increment = '1' then
if savedHours = 23 then
savedHours <= 0;
else
savedHours <= savedHours + 1;
end if;
else null;
end if;
if alarm_decrement = '1' then
if savedHours = 0 then
savedHours <= 23;
else
savedHours <= savedHours - 1;
end if;
else null;
end if;
when setMinute =>
if alarm_increment = '1' then
if savedMinutes = 59 then
savedMinutes <= 0;
else
savedMinutes <= savedMinutes + 1;
end if;
else null;
end if;
if alarm_decrement = '1' then
if savedMinutes = 0 then
savedMinutes <= 59;
else
savedMinutes <= savedMinutes - 1;
end if;
else null;
end if;
end case;
end if;
end process;
alarm_hour1 <= std_logic_vector(to_unsigned(savedHours/10,alarm_hour1'length));
alarm_hour0 <= std_logic_vector(to_unsigned(savedHours mod 10,alarm_hour0'length));
alarm_minute1 <= std_logic_vector(to_unsigned(savedMinutes/10,alarm_minute1'length));
alarm_minute0 <= std_logic_vector(to_unsigned(savedMinutes mod 10,alarm_minute0'length));
--ALARM BUZZER CONDITION
process (currentTime_hour1, currentTime_hour0, currentTime_minute1, currentTime_minute0,
alarm_enable, alarm_hour1, alarm_hour0, alarm_minute1, alarm_minute0)
begin
if((alarm_hour1 = currentTime_hour1) and (alarm_hour0 = currentTime_hour0)
and (alarm_minute1 = currentTime_minute1) and (alarm_minute0 = currentTime_minute0) and alarm_enable = '1') then
alarm_buzzer <= '1';
else
alarm_buzzer <= '0';
end if;
end process;
end alarmBehaviour;
Consider keeping the alarm time in Binary-Coded Decimal (BCD) format instead of binary format, whereby you can compare it directly with the current time, that is provided in BCD format.
This is a good example of how using the appropriate internal data format can reduce the computational problem significantly, since you can simply eliminate the costly division and modulo operations by keeping just one data format (BCD) instead of mixing BCD and binary data formats.
The range of signals savedHours and savedMinutes is not specified, so Quartus assumes they are 32 bits wide. Inference of a divider with one 32-bit operand results into a large tree of conditional subtractions.
Updating your code to something like
--ALARM TIME
signal savedHours : natural range 0 to 23 := 0;
signal savedMinutes : natural range 0 to 59 := 0;
will very likely result into less ALM usage.
Also, please note that rising_edge should be used for clock signals only (at VHDL starter level). Instead of connecting logic to the clock input of a register, what you probably want is some button debounce logic.
I am trying to realize a communication between my FPGA and the HPS on the Altera DE10nano development board. To edit the vhdl i use the Quartus Prime software.
While the communication is working in general (as in i can get some data form the fpga to the hps), i have the issue of creating a proper state-machine which can add a new value to the FIFO with a different clock (in this case 12500Hz) than the base clock of 50MHz. The other clocks (100kHz and 12500Hz) are generated in a different vhdl-module.
The general idea is to write one sample every cycle of the 12,5kHz-Clock. Each cycle i've got a counter that increases as well as some data from a upstream FFT.
I'm using a simple C-Code in the HPS to read my fifo and save the read value into a .csv-file.
Now, the problem: When im using my board to load my design, I'm not getting the proper sample number. I get random values (from "counter_sample") in the .csv-file, while the simulation (with ModelSim) of the state-machine is doing what i want it to do.
Also, the design does work good when i use the 100kHz-Clock to trigger the process, but i've been told that's bad practice, since the clocks are not generated by a pll. This also leads me to thinking it is not an issue with the used C-Code.
The random values i get are not successively, but rather 200-300 counter-values apart of each other.
I'm not a veteran in programming vhdl (as you can probably tell) but will copy my state-machine below. I'm happy to hear your input and will provide further information if needed.
The fft_sop and fft_eop signals are start- and endofpacket signal from the upstream fft.
Thanks!
process(Clk_50MHz, in_reset)
begin
if (in_reset = '1') then
f2h_state <= f2h_idle;
counter_sample <=0;
counter_wait <=0;
out_fifo_write <='0';
out_fifo_writedata <= (others => '0');
fft_sop_old <= '0';
fft_eop_old <= '0';
Clk_12500Hz_alt<='0';
elsif(rising_edge(Clk_50MHz)) then
fft_sop_old <= in_fft_sop;
fft_eop_old <= in_fft_eop;
Clk_12500Hz_old <= Clk_12500Hz;
case f2h_state is
when f2h_idle =>
if ((Clk_12500Hz = '1') and (Clk_12500Hz_old = '0')) then
counter_wait <= counter_wait + 1;
if counter_wait = 8190 then
f2h_state <= f2h_wait_start;
else
f2h_state <= f2h_idle;
end if;
else
f2h_state <= f2h_idle;
end if;
when f2h_wait_start =>
out_fifo_write <= '0';
if ((in_fft_sop = '1') and (fft_sop_old = '0')) then
out_fifo_write <= '1';
out_fifo_writedata(10 downto 0) <= conv_std_logic_vector(1, 11);
counter_sample <= 2;
out_fifo_writedata(22 downto 11) <= in_fft_real(11 downto 0);
out_fifo_writedata(34 downto 23) <= in_fft_imag(11 downto 0);
out_fifo_writedata(63 downto 35) <= (others => '0');
f2h_state <= f2h_writesample;
end if;
when f2h_writesample =>
if ((Clk_12500Hz = '1') and (Clk_12500Hz_old = '0')) then
out_fifo_write <= '1';
counter_sample <= counter_sample + 1;
out_fifo_writedata(10 downto 0) <= conv_std_logic_vector(counter_sample, 11);
out_fifo_writedata(22 downto 11) <= in_fft_real(11 downto 0);
out_fifo_writedata(34 downto 23) <= in_fft_imag(11 downto 0);
out_fifo_writedata(63 downto 35) <= (others => '0');
if in_fft_eop = '1' then
f2h_state <= f2h_wait_start;
end if;
f2h_state <= f2h_writesample;
else
out_fifo_write <= '0';
end if;
end case;
end if;
end process;
All three states are rightly synchronised to the system clock clk_50MHz, but the first and third states, F2H_IDLE and F2H_WRITESAMPLE, are looking for the rising edge of clk_12500Hz while your second state F2H_WAIT_START isn't. Instead, it's only looking for the rising edge of in_fft_sop. This means that the first and third states are synchronised to the rising edge of the clk_12500Hz signal, but the second state is not synchronised to the clk_12500Hz signal (only the in_fft_sop signal). Is this what you intended? This could explain why you are getting random values on counter_sample.
I've restructured the logic so that all the states are synchronised to both the system clock clk_50MHz and the clk_12500Hz signal, which is what I understood from your question, and I've assumed that new data is simply clocked into the FIFO when out_fifo_write is high.
I've also added three edge detectors to make the code more readable, and changed the level detector in the third state to a rising edge detector.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity FPGA2HPS is
port
(
clk_50MHz: in std_logic;
clk_12500Hz: in std_logic;
in_reset: in std_logic;
in_fft_sop: in std_logic;
in_fft_eop: in std_logic;
in_fft_real: in std_logic_vector(11 downto 0);
in_fft_imag: in std_logic_vector(11 downto 0);
out_fifo_write: out std_logic;
out_fifo_writedata: out std_logic_vector(63 downto 0)
);
end entity;
architecture V1 of FPGA2HPS is
type F2H_STATES is (F2H_IDLE, F2H_WAIT_START, F2H_WRITESAMPLE);
signal f2h_state: F2H_STATES;
signal rising_edge_clk_12500Hz: std_logic;
signal rising_edge_in_fft_sop: std_logic;
signal rising_edge_in_fft_eop: std_logic;
signal clk_12500Hz_old: std_logic;
signal fft_sop_old: std_logic;
signal fft_eop_old: std_logic;
signal clk_12500Hz_alt: std_logic;
signal counter_sample: integer;
signal counter_wait: integer;
begin
--
-- Rising edge detectors
--
rising_edge_clk_12500Hz <= clk_12500Hz and not clk_12500Hz_old;
rising_edge_in_fft_sop <= in_fft_sop and not fft_sop_old;
rising_edge_in_fft_eop <= in_fft_eop and not fft_eop_old;
process(clk_50MHz, in_reset)
begin
if in_reset then
f2h_state <= F2H_IDLE;
counter_sample <= 0;
counter_wait <= 0;
out_fifo_write <= '0';
out_fifo_writedata <= (others => '0');
fft_sop_old <= '0';
fft_eop_old <= '0';
clk_12500Hz_alt <= '0';
elsif rising_edge(clk_50MHz) then
-- Ensure all the state machine logic works on the rising edge of the clk_12500Hz signal while also synchronised to the clk_50MHz clock.
if rising_edge_clk_12500Hz then
fft_sop_old <= in_fft_sop;
fft_eop_old <= in_fft_eop;
clk_12500Hz_old <= clk_12500Hz;
case f2h_state is
when F2H_IDLE =>
f2h_state <= F2H_IDLE;
counter_wait <= counter_wait + 1;
if counter_wait = 8190 then
f2h_state <= F2H_WAIT_START;
end if;
when F2H_WAIT_START =>
f2h_state <= F2H_WAIT_START;
out_fifo_write <= '0';
if rising_edge_in_fft_sop then
out_fifo_write <= '1';
out_fifo_writedata(10 downto 0) <= std_logic_vector(to_unsigned(1, 11)); -- CHANGED
counter_sample <= 2;
out_fifo_writedata(22 downto 11) <= in_fft_real(11 downto 0);
out_fifo_writedata(34 downto 23) <= in_fft_imag(11 downto 0);
out_fifo_writedata(63 downto 35) <= (others => '0');
f2h_state <= F2H_WRITESAMPLE;
end if;
when F2H_WRITESAMPLE =>
f2h_state <= F2H_WRITESAMPLE;
counter_sample <= counter_sample + 1;
out_fifo_writedata(10 downto 0) <= std_logic_vector(to_unsigned(counter_sample, 11)); -- CHANGED
out_fifo_writedata(22 downto 11) <= in_fft_real(11 downto 0);
out_fifo_writedata(34 downto 23) <= in_fft_imag(11 downto 0);
out_fifo_writedata(63 downto 35) <= (others => '0');
if rising_edge_in_fft_eop then -- CHANGED: Should this be on the rising edge of in_fft_eop?
out_fifo_write <= '0'; -- ADDED: End of write mode?
f2h_state <= F2H_WAIT_START;
end if;
end case;
end if;
end if;
end process;
end architecture;
I hope that helps, but without the timing diagrams of the FFT and FIFO nor a test bench, I haven't been able to simulate it.
I am trying to write a program to detect if a given input is a prime number or not. When I run the test bench I get correct results however when I run it on the FPGA it only recognizes numbers that are divisible 3 or even as not prime. Any number such as 25 which is divisible by 5 will result in isPrime being 1. What could be causing this inconsistent result?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE IEEE.std_logic_unsigned.all;
USE IEEE.numeric_std.all;
entity PrimeNumber is
Port ( clk: in std_logic;
rst : in std_logic;
input: in std_logic_vector(15 downto 0);
isPrime: out std_logic:= '0';
testOut: out std_logic_vector(31 downto 0)
);
end PrimeNumber;
architecture Behavioral of PrimeNumber is
SIGNAL current_state: std_logic_vector(2 downto 0);
signal next_state: std_logic_vector(2 downto 0):= "000";
signal max: integer;
signal temp: integer;
signal x: integer;
signal nextX:integer;
signal localPrime : std_logic:= '0';
signal current : integer;
signal update: std_logic := '0';
begin
nextX <= x +2;
process(current_state,input)
begin
case (current_state) is
when "000" => --Initial State
update <= '0';
localPrime <= '0';
if(input < x"0004")then
next_state <= "111";
else
max <= to_integer(unsigned(input(15 downto 1)));
current <=to_integer(unsigned(input));
if(input(0) = '0')then
next_state <= "110";
else
next_state <= "001";
end if;
end if;
when "001" => -- Computation State
localPrime <= '0';
temp <= current mod x;
if(x > max) then
next_state <= "111";
else
next_state <= "010";
end if;
update <= '1';
when "010" => -- Checking State
update <= '0';
localPrime <= '0';
if(temp = 0) then
next_state <= "110";
else
next_state <= "001";
end if;
when "110" =>
localPrime <= '0'; -- Not Prime State
next_state <= "110";
when "111" =>
update <= '0';
localPrime <= '1'; --Prime State
next_state <= "111";
when others =>
temp <= 0;
localPrime <= '0';
next_state <= "000";
end case;
end process;
Update_Registers: process(clk)
begin
if(clk'event and clk = '1') then
if ( rst = '1') then
current_state <= "000";
isPrime <= '0';
x<=3;
else
if(update = '1') then
x <= nextX;
end if;
current_state <= next_state;
isPrime <= localPrime;
end if;
end if;
end process;
end Behavioral;
To quickly check sim/syn mismatch, with the visibility you need outside of HW: output the mod result to a port, sim, should still "work"... syn, compile your (hopefully, verilog) netlist for TB, point to compiled netlist, sim, check the mod result against RTL/expected results.
I have to do UART with vhdl on the Xilinx which will send 16 chars string. I wrote such code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.ALL;
entity uartByJackob is
Port ( CLK, A, B, C : in STD_LOGIC;
RESET : in STD_LOGIC;
TxD, TxDOSC : out STD_LOGIC);
end uartByJackob;
architecture Behavioral of uartByJackob is
signal K: std_logic_vector(14 downto 0);
signal Q: std_logic_vector(3 downto 0);
signal CLK_Txd: std_logic;
signal ENABLE: std_logic;
signal QTxD: std_logic_vector(9 downto 0);
signal DATA : STD_LOGIC_VECTOR(7 downto 0);
-- freq of clock
begin
process(CLK, RESET)
begin
if rising_edge(CLK) then
if(A = '1' and K < 10416) then
K <= K + 1;
CLK_Txd <= K(13);
elsif(B = '1' and K < 5208) then
K <= K + 1;
CLK_Txd <= K(12);
elsif(C = '1' and K < 20832) then
K <= K + 1;
CLK_Txd <= K(14);
else
K <= (others => '0');
end if;
end if;
end process;
--counter
process(CLK_Txd, RESET, ENABLE)
begin
if(RESET = '1' and ENABLE = '0') then
Q <= "0000";
elsif (rising_edge(CLK_Txd)) then
Q <= Q + 1;
end if;
end process;
--comparator
ENABLE <= '1' when (Q > 4) else '0';
--transcoder
process(Q, CLK_Txd)
begin
if (rising_edge(CLK_Txd)) then
case Q is
when "0001" => DATA <= x"40";
when "0010" => DATA <= x"41";
when "0011" => DATA <= x"42";
when "0100" => DATA <= x"43";
when "0101" => DATA <= x"44";
when "0110" => DATA <= x"45";
when "0111" => DATA <= x"46";
when "1000" => DATA <= x"47";
when "1001" => DATA <= x"48";
when "1010" => DATA <= x"49";
when "1011" => DATA <= x"50";
when "1100" => DATA <= x"51";
when "1101" => DATA <= x"52";
when "1110" => DATA <= x"53";
when "1111" => DATA <= x"54";
when others => DATA <= x"55";
end case;
end if;
end process;
--uart
process(CLK_Txd, ENABLE, DATA)
begin
if(ENABLE = '0') then
QTxD <= DATA & "01";
elsif rising_edge(CLK_Txd) then
QTxD <= '1'&QTxD(9 downto 1);
end if;
end process;
TxD <= QTxD(0);
TxDOSC <= QTxD(0);
end Behavioral;
It's send data completely not connected with that what i have in transcoder and realy dont know why. Do you have any ideas what is wrong with my code, or do you have any diffrent examples of it how to send your own 16 chars with uart? I suppose that something is wrong with my counter or comparator.
--EDIT
Thans for your effort, i can't try your code at the Xilinx right now couse I am workin on it at my university. I see that you made a lot of changes in my code. Of course first i try to do it like you show and i hope this will be acceptable, but I propably have to do it with transcoder according to this picture.
From last time i made such changes i my code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.ALL;
entity uartByJackob is
Port ( CLK, A, B, C : in STD_LOGIC;
RESET : in STD_LOGIC;
TxD, TxDOSC : out STD_LOGIC);
end uartByJackob;
architecture Behavioral of uartByJackob is
signal K: std_logic_vector(14 downto 0);
signal Q: std_logic_vector(7 downto 0);
signal CLK_Txd: std_logic;
signal ENABLE: std_logic;
signal QTxD: std_logic_vector(7 downto 0);
signal DATA : STD_LOGIC_VECTOR(7 downto 0);
signal QPrim: std_logic_vector(3 downto 0);
begin
process(CLK, RESET)
begin
CLK_Txd <= CLK;
end process;
process(CLK_Txd, RESET, ENABLE)
begin
if(ENABLE = '0') then
Q <= "00000000";
elsif (rising_edge(CLK_Txd)) then
Q <= Q + 1;
end if;
end process;
ENABLE <= '1' when (Q <= 255) else '0';
process(Q(7 downto 4))
begin
case Q(7 downto 4) is
when "0000" => DATA <= x"40";
when "0001" => DATA <= x"41";
when "0010" => DATA <= x"42";
when "0011" => DATA <= x"43";
when "0100" => DATA <= x"44";
when "0101" => DATA <= x"45";
when "0110" => DATA <= x"46";
when "0111" => DATA <= x"47";
when "1000" => DATA <= x"48";
when "1001" => DATA <= x"49";
when "1010" => DATA <= x"50";
when "1011" => DATA <= x"51";
when "1100" => DATA <= x"52";
when "1101" => DATA <= x"53";
when "1110" => DATA <= x"54";
when "1111" => DATA <= x"55";
when others => DATA <= x"56";
end case;
end process;
process(CLK_Txd, ENABLE, DATA)
begin
if(ENABLE = '1') then
QTxD <= DATA;
elsif rising_edge(CLK_Txd) then
QTxD <= '1'&QTxD(7 downto 1);
end if;
end process;
TxD <= QTxD(0);
TxDOSC <= QTxD(0);
end Behavioral;
According to that i send MSB to transcoder and LSB to comparator but my program all the time still send x"40" to DATA and it is propably connected with this counter which you were talking about.
There is my simulation efect. I becoming upset with that couse i don't have enough skills in vhdl to do it by my self. I hope that you will help me to do rebuild my project. On simulation it looks good i dont know how it looks on Xilinx.
Can you show me a piece of code? - Stefan
The entire purpose to providing the link to Adrian Adamcyzk's code (Altera FPGA hardware (has an issue) vs ModelSim simulation (ok) - self implemented UART) was to provide an example with a bit (baud) counter and flip flop used to control sending the message once.
Here's Jackob's modified:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity uartbyjackob is
port (
clk, a, b, c: in std_logic;
reset: in std_logic;
txd, txdosc: out std_logic
);
end entity uartbyjackob;
architecture foo of uartbyjackob is
-- signal k: unsigned(14 downto 0); -- FOR simulation
-- note if k were used in simulation it would require initialization
signal q: unsigned (3 downto 0); -- WAS std_logic_vector
signal clk_txd: std_logic;
signal enable: std_logic;
signal qtxd: std_logic_vector(9 downto 0);
-- signal data: std_logic_vector(7 downto 0);
-- added:
signal bdcnt: unsigned (3 downto 0);
signal ldqtxd: std_logic;
signal davl: std_logic;
type data_lut is array (0 to 15) of std_logic_vector (7 downto 0);
constant data: data_lut := (
x"40", x"41", x"42", x"43", x"44", x"45", x"46", x"47",
x"48", x"49", x"50", X"51", x"52", X"53", x"54", x"55"
);
signal datalut: std_logic_vector (7 downto 0); -- FOR SIMULATION visibility
begin
-- -- freq of clock -- NOTE k never in known binary state for simulation
-- process (clk, reset)
-- begin
-- if rising_edge(clk) then
-- if a = '1' and k < 10416 then
-- k <= k + 1;
-- clk_txd <= k(13);
-- elsif b = '1' and k < 5208 then
-- k <= k + 1;
-- clk_txd <= k(12);
-- elsif c = '1' and k < 20832 then
-- k <= k + 1;
-- clk_txd <= k(14);
-- else
-- k <= (others => '0');
-- end if;
-- end if;
-- end process;
clk_txd <= clk; -- SHORTENS SIMULATION
DAVL_FF: -- DATA_AVAILABLE to send
process (clk_txd, reset)
begin
if reset = '1' then
davl <= '0';
elsif rising_edge (clk_txd) then
if q = 15 and bdcnt = 9 then -- a JK FF equivalent
davl <= '0';
elsif q = 0 then
davl <= '1'; -- one clock holderover from reset
-- else
-- davl <= davl;
end if;
end if;
end process;
-- process(clk_txd, reset, enable)
-- begin
-- if reset = '1' and enable = '0' then
-- q <= "0000";
-- elsif rising_edge(clk_txd) then
-- q <= q + 1;
-- end if;
-- end process;
QCNT:
process (clk_txd, reset)
begin
if reset = '1' then
q <= (others => '0');
elsif rising_edge (clk_txd) then
if enable = '1' then
q <= q + 1;
end if;
end if;
end process;
BAUD_COUNTER:
process (clk_txd, reset)
begin
if reset = '1' then
bdcnt <= (others => '0');
elsif rising_edge (clk_txd) then
if davl = '0' or bdcnt = 9 then
bdcnt <= (others => '0');
else
bdcnt <= bdcnt + 1;
end if;
end if;
end process;
-- comparator
-- enable <= '1' when (q > 4) else '0';
enable <= '1' when bdcnt = 9 and davl = '1' and q /= 15 else
'0';
-- q latches at 15;
ldqtxd <= '1' when bdcnt = 9 and davl = '1' else
'0';
datalut <= data(to_integer(q)); -- FOR SIMULATION VISIBILITIY
--transcoder
-- process(q, clk_txd)
-- begin
-- if rising_edge(clk_txd) then
-- case q is
-- when "0001" => data <= x"40";
-- when "0010" => data <= x"41";
-- when "0011" => data <= x"42";
-- when "0100" => data <= x"43";
-- when "0101" => data <= x"44";
-- when "0110" => data <= x"45";
-- when "0111" => data <= x"46";
-- when "1000" => data <= x"47";
-- when "1001" => data <= x"48";
-- when "1010" => data <= x"49";
-- when "1011" => data <= x"50";
-- when "1100" => data <= x"51";
-- when "1101" => data <= x"52";
-- when "1110" => data <= x"53";
-- when "1111" => data <= x"54";
-- when others => data <= x"55";
-- end case;
-- end if;
-- end process;
-- uart
-- process (clk_txd, enable, data)
-- begin
-- if enable = '0' then
-- qtxd <= data & "01";
-- elsif rising_edge(clk_txd) then
-- qtxd <= '1' & qtxd(9 downto 1);
-- end if;
-- end process;
TX_SHIFT_REG:
process (clk_txd, reset) -- shift regiseter Tx UART
begin
if reset = '1' then
qtxd <= (others => '1'); -- output mark by default
elsif rising_edge (clk_txd) then
if ldqtxd = '1' then
qtxd <= '1' & data(to_integer(q)) & '0';
-- STOP & Data(q) 7 downto 0 & START , a MUX and expansion
else
qtxd <= '1' & qtxd(9 downto 1); -- shift out;
end if;
end if;
end process;
txd <= qtxd(0);
txdosc <= qtxd(0);
end architecture foo;
library ieee;
use ieee.std_logic_1164.all;
entity uartbyjackob_tb is
end entity;
architecture foo of uartbyjackob_tb is
signal clk: std_logic := '0';
signal reset: std_logic := '0';
signal txd: std_logic;
begin
DUT:
entity work.uartbyjackob
port map (
clk => clk, -- clk_txd driven by clk
a => 'X',
b => 'X',
c => 'X', -- a, b, c aren't used
reset => reset,
txd => txd,
txdosc => open
);
CLOCK:
process
begin
wait for 52.35 us;
clk <= not clk;
if now > 20000 us then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 104.7 us;
reset <= '1';
wait for 104.7 us;
reset <= '0';
wait;
end process;
end architecture;
The model has been modified for faster simulation, ignoring the baud rate clock generator.
There's an added flip flop (davl) for enabling the UART to run. There's an added baud (bit) counter bdcnt.
I changed the order of the start, stop and data values loaded into QTxD so the start bit came out first, followed by 8 data bits and the stop bit.
You can read off TxD from left to right start bit, data(q)(0) ... data(q(7), stop bit. The enable or ldqtxd will occur at the same time as a stop bit.
There's only one observable draw back to this implementation, if you reset while a value in the shift register hasn't finished loading you'll cause a framing error for the receiver. Don't reset it for 10 baud times after davl goes false.
The simulation is shown with a 9600 baud clk_txd, the characters go out back to back.
It has fewer flip flops than the original (disregarding k). There is no data register separate from QTxD ( - 8 FFs) plus bdcnt (+ 4) plus davl (+ 1). There are two comparisons (optimized to two) bdcnt = 9, q =, /= 9. Those could be expressed separately so it doesn't require optimization during synthesis.
I changed the look up table style, a matter of personal preference also the excuse for changing counters to type unsigned and using only package numeric_std for arithmetic.
The little testbench likewise doesn't expect the k counter to generate the baud clock.
Running the testbench gives:
Where there's an added signal datalut to show the value being shifted out after ldqtxd.
After your change making the q counter (7 downto 0)
We still see from your waveform that it doesn't work.
This is due to the enable and the shift register.
If you use a single counter with the upper four bits indexing the output character your character is transmitted in 10 out of the 16 clk_txd times indexed by the lower four bits of the counter. The remaining clock times TxD should be '1' (idle line marks in RS-232 parlance).
The order for data to be transmitted will be a space (the start bit), data(0) through data(7) and a mark (the stop bit). (Shown left to right on TxD).
For simulation the k counter is not used. I included it commented out below.
I made several changes for proper simulation. These include synchronously loading the shift register containing QTxD, synchronously clearing the rightmost bit of QTxD to provide a full width and moving enable to occur once every sixteen clocks (clk_txd). The enable is preceded by a new clear for the start bit and both been offset to prevent it from occurring during reset which has the effect of causing a framing error on the first character for any receiver.
Simulation is done with the same testbench I provide above.
The changes to your new code are shown by comments:
architecture behavioral of uartbyjackob is
-- signal k: std_logic_vector(14 downto 0);
signal q: unsigned (7 downto 0); -- std_logic_vector(7 downto 0);
signal clk_txd: std_logic;
signal enable: std_logic;
signal qtxd: std_logic_vector(7 downto 0);
-- using an 8 bit shift register requires a method of outputting a
-- synchronous start bit (the width is important for receive framing)
-- and synchronous stop bit
signal data: std_logic_vector(7 downto 0);
signal qprim: std_logic_vector(3 downto 0);
signal clear: std_logic; -- synchronous clear for start bit
begin
-- let's keep this here for when you put it the FPGA
-- -- freq of clock -- NOTE k never in known binary state for simulation
-- process (clk, reset)
-- begin
-- if rising_edge(clk then
-- if a = '1' and k < 10416 then
-- k <= k + 1;
-- clk_txd <= k(13);
-- elsif b = '1' and k < 5208 then
-- k <= k + 1;
-- clk_txd <= k(12);
-- elsif c = '1' and k < 20832 then
-- k <= k + 1;
-- clk_txd <= k(14);
-- else
-- k <= (others => '0');
-- end if;
-- end if;
-- end process;
process (clk) -- , reset)
begin
clk_txd <= clk; -- if simply a concurrent assignment statement this
end process; -- would look similar to the elaborated equivalent
-- process. The difference, no sensitivity list and
-- an explict wait on clk statement at the end.
-- This process wants to be removed and replaced by
-- the above commented out process for synthesis
process (clk_txd, reset) -- , reset, enable) -- enable a reset?
begin
-- if enable = '0' then
if reset = '1' then -- puts q counter in known state for simulation
q <= "00000000";
elsif rising_edge(clk_txd) then
if q /= 255 then -- stop after sending once
q <= q + 1;
end if;
end if;
end process;
-- enable <= '1' when q <= 255 else '0'; -- this appears incorrect
enable <= '1' when q(3 downto 0) = "0010" else
'0';
clear <= '1' when q(3 downto 0) = "0001" else
'0';
-- USING ONE COUNTER requires some clocks output MARKS
-- (idle bits) each 16 clocks. It requires the load (enable)
-- occur once every 16 clocks.
-- q(3 downto 0) is selected for enable to prevent outputting spaces
-- TxD during reset (q is reset to all '0's). This would cause a receive
-- framing error.
process (q(7 downto 4))
begin
case q(7 downto 4) is
when "0000" => data <= x"40";
when "0001" => data <= x"41";
when "0010" => data <= x"42";
when "0011" => data <= x"43";
when "0100" => data <= x"44";
when "0101" => data <= x"45";
when "0110" => data <= x"46";
when "0111" => data <= x"47";
when "1000" => data <= x"48";
when "1001" => data <= x"49";
when "1010" => data <= x"50";
when "1011" => data <= x"51";
when "1100" => data <= x"52";
when "1101" => data <= x"53";
when "1110" => data <= x"54";
when "1111" => data <= x"55";
when others => data <= x"56";
end case;
end process;
process (clk_txd) -- , enable, data) -- synchronous enable and clear
begin
-- if enable = '1' then -- this appears incorrect
-- qtxd <= data;
if reset = '1' then
qtxd <= (others => '1'); -- outputs mark after reset
elsif rising_edge(clk_txd) then
if clear = '1' then -- synchronous clear for start bit
qtxd(0) <= '0';
elsif enable = '1' then -- synchronous load
qtxd <= data;
else
qtxd <= '1' & qtxd(7 downto 1); -- shift right
end if;
end if;
end process;
-- the synchronous load prevents the first start bit from being stretched
-- q(3 downto 0) the following in hex notation
-- q(3 downto 0) = 2 is the start bit
-- = 3 is data(0)
-- ...
-- = A is data(7)
-- = B is the stop bit
-- = C - 1 are mark (idle) bits (q(3 downto 0) rolls over)
-- = 1 enable occurs loading qtxd
--
-- The offset is caused by synchronous load (1 clk_txd) and the load point
-- (q(3 downto 0) = 1 in enable term).
--
-- The load point wants to occur in the first 6 counts of q(3 downto 0) to
-- insure a trailing mark when q is stopped.
--
-- q(3 downto 0) = 1 is selected for enable to prevent spurious spaces
-- during reset from causing a receive framing error.
txd <= qtxd(0);
txdosc <= qtxd(0);
end architecture behavioral;
The comment table:
-- the synchronous load prevents the first start bit from being stretched
-- q(3 downto 0) the following in hex notation
-- q(3 downto 0) = 2 is the start bit
-- = 3 is data(0)
-- ...
-- = A is data(7)
-- = B is the stop bit
-- = C - 1 are mark (idle) bits (q(3 downto 0) rolls over)
-- = 1 enable occurs loading qtxd
--
-- The offset is caused by synchronous load (1 clk_txd) and the load point
-- (q(3 downto 0) = 1 in enable term).
--
-- The load point wants to occur in the first 6 counts of q(3 downto 0) to
-- insure a trailing mark when q is stopped.
--
-- q(3 downto 0) = 1 is selected for enable to prevent spurious spaces
-- during reset from causing a receive framing error.
tells you where to find bits of the data(q(7 downto 0)) selected character. In the following waveform q is shown as hex to match:
You'll find with the fixes the first character transmitted is 0x40, the second 0x41,...