Hello everyone,
I'm relatively new to working with FPGAs, and while I've managed projects without real-time communication needs, I'm now faced with a task that requires communication between three FPGAs. One of these FPGAs will act as the master, controlling the clock and other essential functions of the system. The other two FPGAs will essentially duplicate tasks simultaneously, allowing one to take over if the other fails.
Each FPGA has three connection lines available for communication. In my setup, I've designated one line for the clock, one for SDO (Serial Data Out), and the remaining one for SDI (Serial Data In), thus enabling full-duplex communication. To check whether I receive messages from both FPGAs, I've implemented a test pin that I monitor using an oscilloscope. However, I've noticed that there's a half-cycle phase difference between the test pins of the two FPGAs.
I'm seeking guidance on resolving this issue and ensuring proper synchronization between the FPGAs for reliable communication. Any help or suggestions would be greatly appreciated.
This is my controller code for both of the slave FPGAs
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity FPGAKONE_CONTROLLER is
Port ( reset: in STD_LOGIC;
CLK : in STD_LOGIC; -- Clock line
SDI : in STD_LOGIC; -- Serial Data In
SDO : out STD_LOGIC; -- Serial Data Out
SCK : out STD_LOGIC; -- Clock output
shift_reg_in : out STD_LOGIC_VECTOR(7 DOWNTO 0)
);
end FPGAKONE_CONTROLLER;
architecture Behavioral of FPGAKONE_CONTROLLER is
signal shift_reg_out : std_logic_vector(7 downto 0):= "10101010";
--signal shift_reg_in : std_logic_vector(7 downto 0); -- Input shift register
signal bit_counter : integer range 0 to 15 := 0; -- Bit counter
type state_type is (IDLE, TRANSFER);
signal state : state_type := IDLE;
begin
-- Process for FSM
process(CLK)
begin
if CLK'event and CLK = '1' then
case state is
when IDLE =>
if reset = '0' then
state <= TRANSFER;
else
shift_reg_in <= "00000000";
state <= IDLE;
end if;
when TRANSFER =>
if bit_counter = 0 then
SDO <= shift_reg_out(7);
SCK <= '1';
shift_reg_in(7) <= SDI;
bit_counter <= bit_counter + 1;
elsif bit_counter = 1 then
SCK <= '0';
bit_counter <= bit_counter + 1;
elsif bit_counter = 2 then
SDO <= shift_reg_out(6);
SCK <= '1';
shift_reg_in(6) <= SDI;
bit_counter <= bit_counter + 1;
elsif bit_counter = 3 then
SCK <= '0';
bit_counter <= bit_counter + 1;
elsif bit_counter = 4 then
SDO <= shift_reg_out(5);
SCK <= '1';
shift_reg_in(5) <= SDI;
bit_counter <= bit_counter + 1;
elsif bit_counter = 5 then
SCK <= '0';
bit_counter <= bit_counter + 1;
elsif bit_counter = 6 then
SDO <= shift_reg_out(4);
SCK <= '1';
shift_reg_in(4) <= SDI;
bit_counter <= bit_counter + 1;
elsif bit_counter = 7 then
SCK <= '0';
bit_counter <= bit_counter + 1;
elsif bit_counter = 8 then
SDO <= shift_reg_out(3);
SCK <= '1';
shift_reg_in(3) <= SDI;
bit_counter <= bit_counter + 1;
elsif bit_counter = 9 then
SCK <= '0';
bit_counter <= bit_counter + 1;
elsif bit_counter = 10 then
SDO <= shift_reg_out(2);
SCK <= '1';
shift_reg_in(2) <= SDI;
bit_counter <= bit_counter + 1;
elsif bit_counter = 11 then
SCK <= '0';
bit_counter <= bit_counter + 1;
elsif bit_counter = 12 then
SDO <= shift_reg_out(1);
SCK <= '1';
shift_reg_in(1) <= SDI;
bit_counter <= bit_counter + 1;
elsif bit_counter = 13 then
SCK <= '0';
bit_counter <= bit_counter + 1;
elsif bit_counter = 14 then
SDO <= shift_reg_out(0);
SCK <= '1';
shift_reg_in(0) <= SDI;
bit_counter <= bit_counter + 1;
elsif bit_counter = 15 then
SCK <= '0';
bit_counter <= 0;
state <= IDLE;
else
SDO <= '0';
bit_counter <= 0;
state <= IDLE;
end if;
end case;
end if;
end process;
end Behavioral;
and this is my code for the slaves, which is also the same for both of the FPGAs:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity FPGAH_SLAVE is
Port ( reset: in STD_LOGIC;
OSC_K : in STD_LOGIC;
SDI : in STD_LOGIC; -- Serial Data In
SDO : out STD_LOGIC; -- Serial Data Out
SCK : in STD_LOGIC; -- Clock output
shift_reg_in : out std_logic_vector(7 downto 0)
);
end FPGAH_SLAVE;
architecture Behavioral of FPGAH_SLAVE is
type state_type is (IDLE, TRANSFER);
signal state : state_type := IDLE;
signal shift_reg_out : std_logic_vector(7 downto 0):="01010101"; -- Output shift register
signal bit_counter : integer range 0 to 7 := 0; -- Bit counter
begin
-- Process for FSM
process(OSC_K)
begin
if rising_edge(OSC_K) then
case state is
when IDLE =>
if reset = '0' then
state <= TRANSFER;
else
shift_reg_in <= "00000000";
state <= IDLE;
end if;
when TRANSFER =>
if SCK = '1' then
if bit_counter = 0 then
SDO <= shift_reg_out(7);
shift_reg_in(7) <= SDI;
elsif bit_counter = 1 then
SDO <= shift_reg_out(6);
shift_reg_in(6) <= SDI;
elsif bit_counter = 2 then
SDO <= shift_reg_out(5);
shift_reg_in(5) <= SDI;
elsif bit_counter = 3 then
SDO <= shift_reg_out(4);
shift_reg_in(4) <= SDI;
elsif bit_counter = 4 then
SDO <= shift_reg_out(3);
shift_reg_in(3) <= SDI;
elsif bit_counter = 5 then
SDO <= shift_reg_out(2);
shift_reg_in(2) <= SDI;
elsif bit_counter = 6 then
SDO <= shift_reg_out(1);
shift_reg_in(1) <= SDI;
elsif bit_counter = 7 then
SDO <= shift_reg_out(0);
shift_reg_in(0) <= SDI;
else
SDO <= '0';
state <= IDLE;
bit_counter <= 0;
end if;
else
bit_counter <= bit_counter + 1;
end if;
end case;
end if;
end process;
end Behavioral;