I'm trying to move a robot arm via FPGA board. The communication is working just fine but I want to make an automated sequence that I would be able to modify on fly. Basically what I need is to be able to code sequentially what follows:
PA0 <= PA1; (for 2s)
PA2 <= PA5; (for 3,5s)
PA4 <= PA3; (for 3s)
PA2 <= PA1; (for 2s)
in a form of data vector or in a case block just to keep it simple and be able to add/change signals and time for which those signals will be propagated.
I've tried this with simple timer and if statements but it's nowhere near perfect and I'm not able to change signal's propagation time without conversing it to binary and adding to existing time counter. It simply looks messy. And I can't change states in case based on time passed.
EDIT:
As asked I'm including piece of code with declarations (LEDs are just for tests).
CODE:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
entity abra is
port
(
PA0 : out std_logic ;
PA2 : out std_logic;
PA4 : out std_logic;
PA6 : out std_logic;
PA1 : in std_logic;
PA3 : in std_logic;
PA5 : in std_logic;
PA7 : in std_logic;
LED: out std_logic_vector(7 downto 0);
RST: in std_logic; --ROT_CENTER--
CLK : in std_logic --50MHz clock--
);
end abra;
architecture Behavioral of abra is
signal TIME_COUNTER : std_logic_vector (31 downto 0) := (others => '0');
signal CNTR : std_logic_vector (7 downto 0) := (others => '0');
begin
control: process(CLK)
begin
if rising_edge(CLK) then
if(TIME_COUNTER = b"00000000101111101011110000100000") then
CNTR <= CNTR + 1; --should inc every 1s--
TIME_COUNTER <= (others => '0');
else
TIME_COUNTER <= TIME_COUNTER + 1;
end if;
if( RST = '1' ) then
CNTR <= (others => '0');
LED <= "11111111";
end if;
PA0 <= '0';
PA2 <= '0';
PA4 <= '0';
PA6 <= '0';
-----------------
if( CNTR >= "00000000" AND CNTR < "00000100") then
PA6 <= PA5; --servo 1 / side up--
LED <= b"00000001";
end if;
if( CNTR >= "00000100" AND CNTR < "00001011") then
PA4 <= PA3; --servo 3 / side down--
LED <= b"00000010";
end if;
if( CNTR >= "00001011" AND CNTR < "00110000") then
PA2 <= PA1; -- servo 6 / side down--
LED <= b"00000100";
end if;
if ( CNTR >= "00100000") then
LED <= b"00000000";
end if;
------------------
end if;
end process control;
end Behavioral;
UCF declarations:
NET "PA0" LOC = "A13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
NET "PA2" LOC = "B13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
NET "PA4" LOC = "A14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
NET "PA6" LOC = "B15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
NET "PA1" LOC = "A15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
NET "PA3" LOC = "A16" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
NET "PA5" LOC = "A17" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
NET "PA7" LOC = "B17" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ;
NET "RST" LOC = "R13" | IOSTANDARD = LVCMOS33 | PULLDOWN ;
NET "CLK" LOC = "E12"| IOSTANDARD = LVCMOS33 ;
NET "LED<0>" LOC = "W21" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | Drive = 8 ;
NET "LED<1>" LOC = "Y22" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | Drive = 8 ;
NET "LED<2>" LOC = "V20" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | Drive = 8 ;
NET "LED<3>" LOC = "V19" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | Drive = 8 ;
NET "LED<4>" LOC = "U19" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | Drive = 8 ;
NET "LED<5>" LOC = "U20" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | Drive = 8 ;
NET "LED<6>" LOC = "T19" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | Drive = 8 ;
NET "LED<7>" LOC = "R20" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | Drive = 8 ;
Related
I have always been told it is bad design to have anything but a reset in your reset clause. For instance, see the two circuits below:
process (CLK)
begin
if rising_edge(CLK) then
if (RST = '1') then
Q0 <= '0';
else
if (CLR = '1') then
Q0 <= '0';
else
Q0 <= D;
end if;
end if;
end if;
end process;
process (CLK)
begin
if rising_edge(CLK) then
if (RST = '1' or CLR = '1') then
Q1 <= '0';
else
Q1 <= D;
end if;
end if;
end process;
I've been told the first is more correct, but...
Ive tested them and they appear to be equivalent logically:
They appear equivalent in synthesis and implementation (in fact Vivado synthesizes them as the second case more accurately):
So where is the disconnect? Did older tools not synthesize this properly? Is it actually bad design to do the second case?
The accepted answer below made me wonder how it would look if the resets were asynchronous:
process (CLK, RST)
begin
if (RST = '1') then
Q0 <= '0';
else
if rising_edge(CLK) then
if (CLR = '1') then
Q0 <= '0';
else
Q0 <= D;
end if;
end if;
end if;
end process;
process (CLK, RST, CLR)
begin
if (RST = '1' or CLR = '1') then
Q1 <= '0';
else
if rising_edge(CLK) then
Q1 <= D;
end if;
end if;
end process;
Synthesis results are very different for the asynchronous case. This makes more sense now from a timing perspective as now you'd have an asynchronous signal running around, thank you.
Minimum reproducible example (synchronous case):
top.vhd
library IEEE;
use IEEE.std_logic_1164.all;
entity top is
port (
CLK : in std_logic;
RST : in std_logic;
CLR : in std_logic;
D : in std_logic;
Q0 : out std_logic;
Q1 : out std_logic
);
end top;
architecture rtl of top is
begin
process (CLK)
begin
if rising_edge(CLK) then
if (RST = '1') then
Q0 <= '0';
else
if (CLR = '1') then
Q0 <= '0';
else
Q0 <= D;
end if;
end if;
end if;
end process;
process (CLK)
begin
if rising_edge(CLK) then
if (RST = '1' or CLR = '1') then
Q1 <= '0';
else
Q1 <= D;
end if;
end if;
end process;
end architecture rtl;
tb.vhd
library IEEE;
use IEEE.std_logic_1164.all;
library std;
use std.env.all;
entity tb is
end entity tb;
architecture behav of tb is
constant CLK_FREQ : real := 100.0e6;
constant CLK_HALF_P : time := (((1.0/CLK_FREQ)*10.0e8)/2.0) * 1 ns;
signal clk : std_logic;
signal rst : std_logic;
signal clr : std_logic;
signal d : std_logic;
signal q0 : std_logic;
signal q1 : std_logic;
begin
dut : entity work.top(rtl)
port map (
CLK => clk,
RST => rst,
CLR => clr,
D => d,
Q0 => q0,
Q1 => q1
);
sysClkProc : process ---------------------------------------------------------
begin
clk <= '1';
wait for CLK_HALF_P;
clk <= '0';
wait for CLK_HALF_P;
end process sysClkProc; ------------------------------------------------------
stimulusProc : process -------------------------------------------------------
begin
report ("Starting Simulation");
rst <= '1';
d <= '0';
clr <= '0';
wait for 100 ns;
rst <= '0';
for i in 1 to 10 loop
wait until rising_edge(clk);
end loop;
d <= '1';
for i in 1 to 10 loop
wait until rising_edge(clk);
end loop;
d <= '0';
for i in 1 to 10 loop
wait until rising_edge(clk);
end loop;
d <= '1';
for i in 1 to 5 loop
wait until rising_edge(clk);
end loop;
clr <= '1';
for i in 1 to 5 loop
wait until rising_edge(clk);
end loop;
clr <= '0';
for i in 1 to 5 loop
wait until rising_edge(clk);
end loop;
d <= '0';
wait for 100 ns;
finish(0);
end process stimulusProc; ----------------------------------------------------
end architecture behav;
constr.xdc - Target Nexys A7-100T (xc7a100tcsg324-1)
create_clock -period 10.000 -name sys_clock [get_ports CLK]
set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS18} [get_ports CLK]
set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS18} [get_ports RST]
set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVCMOS18} [get_ports CLR]
set_property -dict {PACKAGE_PIN M13 IOSTANDARD LVCMOS18} [get_ports D ]
set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS18} [get_ports Q0 ]
set_property -dict {PACKAGE_PIN K15 IOSTANDARD LVCMOS18} [get_ports Q1 ]
There are 2 different concepts: Asynchronous reset and synchronous reset. You are working with synchronous reset (getting active only at clock edges), which does not have any restrictions. So both versions of your design are ok, I would chose the first solution with "or", because it is easier to read. At asynchronous reset you do not have so much freedom, at many places in the design flow (static timing analysis, synthesis, layout) the tools do not like logic in the reset path, because it makes the situation more complicated. But of course, if logic in the asynchronous is really needed, you can implement it but you must live with more work effort.
It appears that you are using Xilinx tools and writing VHDL that describes what Xilinx calls an FDRE (D Flip-Flop with Clock Enable and Synchronous Reset).
You have two signals (RST and CLR) that can cause the FDRE to reset. Since the FDRE has only one reset (R) input then RST and CLR must be combined using combinatorial logic before being sent to the FDRE. Xilinx devices use a component called a LUT to perform combinatorial logic.
So, if you are trying to write VHDL that more directly
describes the hardware, then you should write:
R <= RST or CLR; --maps to a LUT
process(C) --maps to a FDRE
begin
if rising_edge(C) then
if (R = '1') then
Q <= '0';
else
Q <= D;
end if;
end if;
end process;
I have a project in which I need to send data from a Windows 10 computer to a BASYS 3 board(ARTIX7 FPGA). I use UART to do so. The data to send is entered in a PuTTY serial console.
For testing purposes, I decided to display the received data using 8 LEDs on the board.
I am using Vivado 2016.4.
The problem I have is that the data I get on the LEDs is totally different from what it should be. I suppose it's a problem of synchronization between PuTTY's baud rate and my VHDL module.
Please find hereafter the .vhd file and the .xdc file of this project :
The .vhd is based on a finite state machine (FSM), and there are two signals allowing the synchronization :
tick_UART : it ticks every 10417 clock period. Since the clock period is 10 ns, tick_UART rises 9600 times per second (I intend a use at 9600 bauds).
double_tick_UART : twice the frequency of tick_UART, used to sample the bits in the middle.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_RX is
Port ( RxD : in STD_LOGIC;
clk : in STD_LOGIC;
RAZ : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR (7 downto 0));
end UART_RX;
architecture Behavioral of UART_RX is
signal tick_UART : STD_LOGIC; -- Signal "top" passage d'un état à l'autre selon vitesse connexion série
signal double_tick_UART : STD_LOGIC; -- Signal précédent, fréquence * 2
signal compteur_tick_UART : integer range 0 to 10420; -- Compteur pour tick_UART
signal double_compteur_tick_UART : integer range 0 to 5210; -- Compteur pour demi-périodes
type state_type is (idle, start, demiStart, b0, b1, b2, b3, b4, b5, b6, b7, stop); -- Etats de la FSM
signal state :state_type := idle; -- Etat par défaut
signal RAZ_tick_UART : STD_LOGIC; -- RAZ du signal tick_UART;
begin
process(clk, RAZ, state, RAZ_tick_UART) -- Compteur classique (tick_UART)
begin
if (raz='1') or (state = idle) or (RAZ_tick_UART = '1') then
compteur_tick_UART <= 0;
tick_UART <= '0';
elsif clk = '1' and clk'event then
if compteur_tick_UART = 10417 then
tick_UART <= '1';
compteur_tick_UART <= 0;
else
compteur_tick_UART <= compteur_tick_UART + 1;
tick_UART <= '0';
end if;
end if;
end process;
process(clk, RAZ, state) -- Compteur demi-périodes (double_tick_UART car fréquence double)
begin
if (raz='1') or (state = idle) then
double_compteur_tick_UART <= 0;
double_tick_UART <= '0';
elsif clk = '1' and clk'event then
if double_compteur_tick_UART = 5209 then
double_tick_UART <= '1';
double_compteur_tick_UART <= 0;
else
double_compteur_tick_UART <= double_compteur_tick_UART + 1;
double_tick_UART <= '0';
end if;
end if;
end process;
fsm:process(clk, RAZ) -- Machine à état
begin
if (RAZ = '1') then
state <= idle;
data_out <= "00000000";
RAZ_tick_UART <= '1';
elsif clk = '1' and clk'event then
case state is
when idle => if RxD = '0' then -- Si front descendant de RxD et en idle
state <= start;
RAZ_tick_UART <= '1';
end if;
when start => if double_tick_UART = '1' then
state <= demiStart;
RAZ_tick_UART <= '0';
end if;
data_out <= "00000000";
when demiStart => if tick_UART = '1' then
state <= b0;
RAZ_tick_UART <= '0';
end if;
data_out(0) <= RxD; -- Acquisition bit 0
when b0 => if tick_UART = '1' then
state <= b1;
end if;
data_out(1) <= RxD; -- Acquisition bit 1
when b1 => if tick_UART = '1' then
state <= b2;
end if;
data_out(2) <= RxD; -- Acquisition bit 2
when b2 => if tick_UART = '1' then
state <= b3;
end if;
data_out(3) <= RxD; -- Acquisition bit 3
when b3 => if tick_UART = '1' then
state <= b4;
end if;
data_out(4) <= RxD; -- Acquisition bit 4
when b4 => if tick_UART = '1' then
state <= b5;
end if;
data_out(5) <= RxD; -- Acquisition bit 5
when b5 => if tick_UART = '1' then
state <= b6;
end if;
data_out(6) <= RxD; -- Acquisition bit 6
when b6 => if tick_UART = '1' then
state <= b7;
end if;
data_out(7) <= RxD; -- Acquisition bit 7
when b7 => if tick_UART = '1' then
state <= stop;
end if;
when stop => if tick_UART = '1' then
state <= idle; -- Renvoi en idle
end if;
end case;
end if;
end process;
end Behavioral;
XDC file :
## Clock signal
set_property PACKAGE_PIN W5 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
## LEDs
set_property PACKAGE_PIN U16 [get_ports data_out[0]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[0]]
set_property PACKAGE_PIN E19 [get_ports data_out[1]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[1]]
set_property PACKAGE_PIN U19 [get_ports data_out[2]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[2]]
set_property PACKAGE_PIN V19 [get_ports data_out[3]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[3]]
set_property PACKAGE_PIN W18 [get_ports data_out[4]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[4]]
set_property PACKAGE_PIN U15 [get_ports data_out[5]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[5]]
set_property PACKAGE_PIN U14 [get_ports data_out[6]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[6]]
set_property PACKAGE_PIN V14 [get_ports data_out[7]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[7]]
##Buttons
set_property PACKAGE_PIN T18 [get_ports RAZ]
set_property IOSTANDARD LVCMOS33 [get_ports RAZ]
##USB-RS232 Interface
set_property PACKAGE_PIN B18 [get_ports RxD]
set_property IOSTANDARD LVCMOS33 [get_ports RxD]
Do you spot any mistake ?
I also tried to use another .vhd (not written by myself and supposed to work).
This didn't work either: https://www.nandland.com/vhdl/modules/module-uart-serial-port-rs232.html
(I well modified the generic g_CLKS_PER_BIT in accordance with my clock & baud rate)
The issue could come from PuTTY but I've set a baud rate of 9600 baud, 8 data bits, 1 stop bit, no parity, so I don't see what could be wrong !
If you have further ideas / comments, because I can't find what's wrong !
Thank you very much !
EDIT March 16, 2017 :
Following #J.H.Bonarius & #user1155120 recommandations, I added a 2 stage flip flop synchronizer to synchronize the RxD incoming signal with my 100 MHz clock domain.
I also modified modified some asynchronous resets.
Nevertheless, I still have the same issue (LEDs not corresponding to what's sent via PuTTY).
Find hearafter the new .vhd code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_RX is
Port ( RxD_in : in STD_LOGIC;
clk : in STD_LOGIC;
RAZ : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR (7 downto 0));
end UART_RX;
architecture Behavioral of UART_RX is
signal tick_UART : STD_LOGIC; -- Signal "top" passage d'un état à l'autre selon vitesse connexion série
signal double_tick_UART : STD_LOGIC; -- Signal précédent, fréquence * 2
signal compteur_tick_UART : integer range 0 to 10420; -- Compteur pour tick_UART
signal double_compteur_tick_UART : integer range 0 to 5210; -- Compteur pour demi-périodes
type state_type is (idle, start, demiStart, b0, b1, b2, b3, b4, b5, b6, b7); -- Etats de la FSM
signal state :state_type := idle; -- Etat par défaut
signal RAZ_tick_UART : STD_LOGIC; -- RAZ du signal tick_UART;
signal RxD_temp : STD_LOGIC; -- RxD provisoire entre deux FF
signal RxD_sync : STD_LOGIC; -- RxD synchronisé sur l'horloge
begin
D_flip_flop_1:process(clk) -- Clock crossing
begin
if clk = '1' and clk'event then
RxD_temp <= RxD_in;
end if;
end process;
D_flip_flop_2:process(clk) -- Clock crossing
begin
if clk = '1' and clk'event then
RxD_sync <= RxD_temp;
end if;
end process;
tickUART:process(clk, RAZ, state, RAZ_tick_UART) -- Compteur classique (tick_UART)
begin
if clk = '1' and clk'event then
if (RAZ='1') or (state = idle) or (RAZ_tick_UART = '1') then
compteur_tick_UART <= 0;
tick_UART <= '0';
elsif compteur_tick_UART = 10417 then
tick_UART <= '1';
compteur_tick_UART <= 0;
else
compteur_tick_UART <= compteur_tick_UART + 1;
tick_UART <= '0';
end if;
end if;
end process;
doubleTickUART:process(clk, RAZ, state) -- Compteur demi-périodes (double_tick_UART car fréquence double)
begin
if clk = '1' and clk'event then
if (RAZ='1') or (state = idle) then
double_compteur_tick_UART <= 0;
double_tick_UART <= '0';
elsif double_compteur_tick_UART = 5209 then
double_tick_UART <= '1';
double_compteur_tick_UART <= 0;
else
double_compteur_tick_UART <= double_compteur_tick_UART + 1;
double_tick_UART <= '0';
end if;
end if;
end process;
fsm:process(clk, RAZ) -- Machine à état
begin
if (RAZ = '1') then
state <= idle;
data_out <= "00000000";
RAZ_tick_UART <= '1';
elsif clk = '1' and clk'event then
case state is
when idle => if RxD_sync = '0' then -- Si front descendant de RxD (= bit de start) et en idle
state <= start;
RAZ_tick_UART <= '1';
end if;
when start =>if double_tick_UART = '1' then -- Demi période écoulée (pour échantillonage)
state <= demiStart;
RAZ_tick_UART <= '0'; -- Le compteur tick_UART commence à compter
end if;
data_out <= "00000000"; -- Reset des anciennes données
when demiStart => if tick_UART = '1' then
state <= b0;
RAZ_tick_UART <= '0';
end if;
data_out(0) <= RxD_sync; -- Acquisition bit 0
when b0 => if tick_UART = '1' then
state <= b1;
end if;
data_out(1) <= RxD_sync; -- Acquisition bit 1
when b1 => if tick_UART = '1' then
state <= b2;
end if;
data_out(2) <= RxD_sync; -- Acquisition bit 2
when b2 => if tick_UART = '1' then
state <= b3;
end if;
data_out(3) <= RxD_sync; -- Acquisition bit 3
when b3 => if tick_UART = '1' then
state <= b4;
end if;
data_out(4) <= RxD_sync; -- Acquisition bit 4
when b4 => if tick_UART = '1' then
state <= b5;
end if;
data_out(5) <= RxD_sync; -- Acquisition bit 5
when b5 => if tick_UART = '1' then
state <= b6;
end if;
data_out(6) <= RxD_sync; -- Acquisition bit 6
when b6 => if tick_UART = '1' then
state <= b7;
end if;
data_out(7) <= RxD_sync; -- Acquisition bit 7
when b7 => if tick_UART = '1' then
state <= idle; -- state <= stop;
end if;
end case;
end if;
end process;
end Behavioral;
Do you have any idea about the origin of my problem ?
Thank you very much !
First if (raz='1') or (state = idle) or (RAZ_tick_UART = '1') then don't put so many things in an asynchronous reset input. Actually: don't use asynchronous resets at all. They will introduce logic into the clock path.
Second thing: it's probably a good idea to put some clock domain synchronizations on your UART RxD. Just a two stage synchronizer. Else when idle => if RxD = '0' then will be affected by glitches.
I'm trying to write a very simple program on a Spartan-3E development board. I want to read the slide switches and use the LED next to the slide switches to indicate which switch is in the on position.
Here is my code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Switch is
PORT(a,b,c,d: IN std_logic;
a_ON,a_Off,b_ON,b_Off,c_ON,c_Off,d_ON,d_Off: OUT std_logic);
end Switch;
architecture Behavioral of Switch is
begin
PROCESS (a)
begin
if a = '1' then
a_ON <= '1';
else
a_OFF <= '1';
end if;
END PROCESS;
end Behavioral;
Here is my *.ucf file:
NET "a" LOC = "L13" | IOSTANDARD = LVTTL | PULLUP ;
NET "b" LOC = "L14" | IOSTANDARD = LVTTL | PULLUP ;
NET "c" LOC = "H18" | IOSTANDARD = LVTTL | PULLUP ;
NET "d" LOC = "N17" | IOSTANDARD = LVTTL | PULLUP ;
NET "d_OFF" LOC = "F9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
NET "d_ON" LOC = "E9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
NET "c_OFF" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
NET "c_ON" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
NET "b_OFF" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
NET "b_ON" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
NET "a_OFF" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
NET "a_ON" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
Here is the errors I get:
PhysDesignRules:368 - The signal is incomplete. The signal
is not driven by any source pin in the design.
ERROR:PhysDesignRules:368 - The signal is incomplete. The
signal is not driven by any source pin in the design.
ERROR:PhysDesignRules:368 - The signal is incomplete. The
signal is not driven by any source pin in the design.
ERROR:PhysDesignRules:368 - The signal is incomplete. The
signal is not driven by any source pin in the design.
ERROR:PhysDesignRules:368 - The signal is incomplete. The
signal is not driven by any source pin in the design.
ERROR:PhysDesignRules:368 - The signal is incomplete. The
signal is not driven by any source pin in the design.
WARNING:PhysDesignRules:367 - The signal is incomplete. The
signal does not drive any load pins in the design.
WARNING:PhysDesignRules:367 - The signal is incomplete. The
signal does not drive any load pins in the design.
WARNING:PhysDesignRules:367 - The signal is incomplete. The
signal does not drive any load pins in the design.
WARNING:PhysDesignRules:367 - The signal is incomplete. The
signal does not drive any load pins in the design.
The following output ports in your design are not connected to any logic or driven in any way:
b_ON,b_Off,c_ON,c_Off,d_ON,d_Off
You need to drive them with at least '0' to pass DRC. for example:
b_ON <= '0';
If for some reason you really don't want to drive these signals, you could set them to mode inout, and drive them with 'Z':
port (
b_ON : inout std_logic
);
...
b_ON <= 'Z';
I'm implementing a simple SPI master in VHDL. The problem I'm facing is that during the synthesising two flip flops are created for ss and data_rdy. I thought that the output to those ports is always specified, so why are these registers created, and how can I get rid of them?
My code is below, with the states that don't have ss or data_rdy in them omitted.
entity:
library IEEE;
use IEEE.std_logic_1164.ALL;
entity mcu is
port(clk : in std_logic;
res : in std_logic;
pc : in std_logic_vector(7 downto 0);
pc_new : in std_logic;
data_ack : in std_logic;
miso : in std_logic;
data : out std_logic_vector(12 downto 0);
data_rdy : out std_logic;
mosi : out std_logic;
sclk : out std_logic;
ss : out std_logic);
end mcu;
Architecture:
library IEEE;
use IEEE.std_logic_1164.ALL;
architecture behaviour of mcu is
-- r: send read command
-- a: send address
-- rx: receive data
type state_t is (r0, r1, r2, r3, r4, r5, r6, r7,
a0, a1, a2, a3, a4, a5, a6, a7,
rx0, rx1, rx2, rx3, rx4, rx5, rx6, rx7, rx8, rx9, rx10, rx11, rx12,
idle, starting, done);
signal state : state_t := idle;
signal datasig : std_logic_vector(12 downto 0);
begin
sclk <= clk;
mosi <= datasig(12);
sync : process(clk) is
begin
if rising_edge(clk) then
data_rdy <= '0';
ss <= '0';
if res = '1' then
state <= idle;
else
datasig <= datasig(11 downto 0) & miso;
if pc_new = '1' then
state <= starting;
else
case state is
when idle =>
ss <= '1';
datasig <= (others => '0');
state <= idle;
...
when rx12 =>
data <= datasig;
data_rdy <= '1';
state <= done;
when done =>
if data_ack = '1' then
state <= idle;
else
state <= done;
end if;
end case;
end if;
end if;
end if;
end process sync;
end behaviour;
The relevant synthesiser output:
===============================================================================
| Register Name | Type | Width | Bus | MB | AR | AS | SR | SS | ST |
===============================================================================
| data_rdy_reg | Flip-flop | 1 | N | N | N | N | Y | N | N |
| ss_reg | Flip-flop | 1 | N | N | N | N | Y | N | N |
| data_reg | Flip-flop | 13 | Y | N | N | N | N | N | N |
| state_reg | Flip-flop | 3 | Y | N | N | N | N | Y | N |
| state_reg | Flip-flop | 2 | N | N | N | N | Y | Y | N |
| datasig_reg | Flip-flop | 13 | Y | N | N | N | N | N | N |
===============================================================================
Also, why is state split into two registers?
Registering your outputs is normally a Good Thing : it allows much better defined timings, which can translate to more reliable operation, especially with external devices like SPI peripherals.
The problem (I think) you are facing is that when you want an output to be true whenever you are in a certain state, assigning that output while you are in that state (within the clocked process) will introduce a clock cycle delay.
David Koontz gives one answer : move all the assignments to that output out of the clocked part - or indeed out of that process altogether, dependent only on the "state" signal.
But another way will preserve the register for clean timings, and still eliminate that cycle delay.
That is to advance the output assignment to any condition in any state that transitions into that state, or (once in it) doesn't transition out of it. So for example, modify
when rx12 =>
data <= datasig;
data_rdy <= '1';
state <= done;
and the transition into state rx12
when rx11 =>
if ready_to_go_to_rx12 then
data_rdy <= '1'; -- keep data_rdy synched with rx12
state <= rx12;
end if;
when rx12 =>
data <= datasig;
-- data_rdy <= '1'; -- no, because we leave state rx12 immediately
state <= done;
and likewise for other outputs with the same problem.
In all probability this doesn't create extra logic, because the synth tool can usually identify that data_rdy and rx12 are always asserted at the same time, and share a register for them.
EDIT : I came back for another look, and noticed that data <= datasig; is also registered, and therefore also a cycle late : while I only considered data_rdy as one of the signals you mentioned, you need to consider if other assignments like data <= datasig; should also be advanced. (I would guess so : it's counterintuitive to signal data_rdy in the cycle before new data!)
The problem I'm facing is that during the synthesising two flip flops are created for ss and data_rdy. I thought that the output to those ports is always specified, so why are these registers created, and how can I get rid of them?
The registers for data_rdy and ss are created right here:
if rising_edge(clk) then
data_rdy <= '0';
ss <= '0';
The way to get rid of them is only assign to data_rdy and ss outside of the if statement evaluating clk.
Also, why is state split into two registers?
You have 32 states, so 5 flip flops sounds right. If you look at the last two columns in the report for those two sets of flip flops you'll find that three of them are synchronously set and both sets of flip flops are synchronously reset.
This comes about:
if rising_edge(clk) then
data_rdy <= '0';
ss <= '0';
if res = '1' then
state <= idle;
else
datasig <= datasig(11 downto 0) & miso;
if pc_new = '1' then
state <= starting;
else
case state is
when idle =>
ss <= '1';
datasig <= (others => '0');
state <= idle;
because your synchronously jamming state to idle, to start, or using an input multiplexer driven by state.
If you have the capability to see a schematic representation of the mapped design it would be enlightening.
I would like to probe a tristate signal using chipscope.
According to this answer record, it can't be done, so this is what I started with (only relevant code included):
-- Tristate signals
FPGA_SMB0_SDA <= sysmon_iic_data;
FPGA_SMB0_SCL <= sysmon_iic_clk;
-- Output signals
DEBUG_LED0 <= '0';
DEBUG_LED1 <= '0';
Which builds fine with no errors.
Attempt 1:
This is my first attempt at generating a debug signal for probing that's just an out:
-- Tristate signals
FPGA_SMB0_SDA <= sysmon_iic_data;
FPGA_SMB0_SCL <= sysmon_iic_clk;
-- Generating new output signals using tristate (tristate signals are either '0' or 'X' for IIC)
sysmon_iic_data_debug <= '0' when (sysmon_iic_data = '0') else '1';
sysmon_iic_clk_debug <= '0' when (sysmon_iic_clk = '0') else '1';
-- connecting debug outs to debug leds (so that the debug signals aren't optimized out)
DEBUG_LED0 <= sysmon_iic_data_debug;
DEBUG_LED1 <= sysmon_iic_clk_debug;
The above code passes synthesis but NGDbuild gives the following errors:
ERROR:ConstraintSystem:59 - Constraint <IOSTANDARD = LVCMOS25 ;>
[frm121401u1r1.ucf(333)]: NET "FPGA_SMB0_SDA"
not found. Please verify that:
1. The specified design element actually exists in the original design.
2. The specified object is spelled correctly in the constraint source file.
The above is repeated 8 times, twice for each net.
Attempt 2:
Second thing I tried was using a process:
FPGA_SMB0_SDA <= sysmon_iic_data;
FPGA_SMB0_SCL <= sysmon_iic_clk;
gen_sysmon_debug : process(refclk_10m,refclk_10m_rst)
begin
if (refclk_10m_rst = '1') then
sysmon_iic_data_debug <= '0';
sysmon_iic_clk_debug <= '0';
elsif (rising_edge(refclk_10m)) then
if (sysmon_iic_clk = '0') then
sysmon_iic_clk_debug <= '0';
else
sysmon_iic_clk_debug <= '1';
end if;
if (sysmon_iic_data = '0') then
sysmon_iic_data_debug <= '0';
else
sysmon_iic_data_debug <= '1';
end if;
end if;
end process;
DEBUG_LED0 <= sysmon_iic_data_debug;
DEBUG_LED1 <= sysmon_iic_clk_debug;
That gave me this NGDbuild error:
ERROR:NgdBuild:924 - bidirect pad net 'FPGA_SMB0_SDA' is driving non-buffer primitives:
pin D on block sysmon_iic_data with type FDC,
Two of those, one for SDA and one for SCL
More Info:
This is what's in my UCF:
NET "DEBUG_LED0" LOC = "AK33" | IOSTANDARD = LVCMOS25 ;
NET "DEBUG_LED1" LOC = "AK34" | IOSTANDARD = LVCMOS25 ;
...
NET "FPGA_SMB0_SCL" LOC = "G13" | IOSTANDARD = LVCMOS25 ;
NET "FPGA_SMB0_SDA" LOC = "H13" | IOSTANDARD = LVCMOS25 ;
And top-level vhdl net definitions:
DEBUG_LED0 : out std_logic;
DEBUG_LED1 : out std_logic;
FPGA_SMB0_SCL : inout std_logic;
FPGA_SMB0_SDA : inout std_logic;
and in uBlaze .mhs:
PORT xps_iic_1_Sda_pin = xps_iic_1_Sda, DIR = IO, BUFFER_TYPE = NONE
PORT xps_iic_1_Scl_pin = xps_iic_1_Scl, DIR = IO, BUFFER_TYPE = NONE
I'm completely at a loss why I'm getting these NGDbuild errors, anyone have any ideas?
Your net is probably getting renamed now you've connected another signal to it :(
Take the constraints out, let it build.
Load the NCD file into FPGA editor and see what the net ends up being called, and use that in your UCF.
Or instantiate all the IOBs yourself in the top level VHDL file, then you know the nae of the net between the IOB "pin" and the real pin won't change and you can constrain that net.