kureigu
Member level 2
- Joined
- Jan 14, 2013
- Messages
- 49
- Helped
- 0
- Reputation
- 0
- Reaction score
- 0
- Trophy points
- 1,286
- Location
- Scotland
- Activity points
- 1,779
Hey all,
I was wondering if someone might be able to help me rid my code of an unusual bug…
I wrote an SPI slave component to receive and decode incoming commands from a microcontroller. I've tested it on it's own and it works perfectly.
However, when I include it in my top level design and try to make it pass some data out to act upon, something unusual happens; The LSB of the 'target_new' signal (unsigned, 4 bits) is flipped.
Now I know that the SPI slave is still receiving the correct data because it's required to echo the command back to the master where it is verified. So this leads me to believe it's something to do with passing the signal back from the component…
Here's the SPI slave/decoding component:
And here is what uses the commands in the top level:
There's obviously more in the top level than just this, but I omitted some chunks for clarity.
I was wondering if someone might be able to help me rid my code of an unusual bug…
I wrote an SPI slave component to receive and decode incoming commands from a microcontroller. I've tested it on it's own and it works perfectly.
However, when I include it in my top level design and try to make it pass some data out to act upon, something unusual happens; The LSB of the 'target_new' signal (unsigned, 4 bits) is flipped.
Now I know that the SPI slave is still receiving the correct data because it's required to echo the command back to the master where it is verified. So this leads me to believe it's something to do with passing the signal back from the component…
Here's the SPI slave/decoding component:
Code:
-- SPI Slave
-- Tailored to work with netduino
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity netduino_bridge is
generic( data_width: integer := 8
);
port( -- Hard ports
clk: in std_logic;
SCLK, MOSI, CS: in std_logic;
MISO: out std_logic := '0';
-- Soft ports
target_out: out unsigned(3 downto 0);
target_in: in unsigned(3 downto 0);
status: in unsigned(3 downto 0);
cmd: out unsigned(7 downto 0)
);
end netduino_bridge;
architecture behavioural of netduino_bridge is
type state is (IDLE, Rx, Tx);
signal SPI_state: state := IDLE;
signal Rx_data, Tx_data: unsigned(data_width-1 downto 0);
signal Rx_count, Tx_count: integer := 0;
signal latch_data: std_logic := '0';
signal target_reg: unsigned(3 downto 0) := "0001";
begin
target_out <= target_reg;
-- Command decoding process
process(latch_data)
variable lock, search: std_logic := '0';
begin
if rising_edge(latch_data) then
case Rx_data(7 downto 4) is
-- Set new target
when x"1" =>
Tx_data <= Rx_data;
target_reg <= Rx_data(3 downto 0);
-- Query current target/status
when x"2" =>
Tx_data <= status & target_in;
-- Find 'real' zero
-- A command to set the inclination to real zero level
-- rather than zero relative to last position (based on step count)
-- Echo
when x"4" =>
Tx_data <= x"4" & Rx_data(3 downto 0);
when others =>
Tx_data <= x"E0";
end case;
end if;
end process;
-- Communication process
process(CS, SCLK, Rx_count, Tx_count) is
begin
if(CS = '0') then
if rising_edge(SCLK) then
-- Receive
if(Rx_count < data_width) then
Rx_count <= Rx_count + 1;
Rx_data(data_width-1-Rx_count) <= MOSI; -- Shift in data on MOSI
end if;
-- Flag new data (Latch asynchronously)
if(Rx_count = data_width-1) then
latch_data <= '1';
end if;
-- Hopefully time in here to decode the command and provide a reply.
end if;
if falling_edge(SCLK) AND Rx_count = data_width then
-- Transmit
if(Tx_count < data_width) then
Tx_count <= Tx_count + 1;
MISO <= Tx_data(data_width-1-Tx_count);
end if;
end if;
else
-- Stop latching data_out to Rx_data
Latch_data <= '0';
-- Reset counters
Tx_count <= 0;
Rx_count <= 0;
end if;
end process;
end behavioural;
And here is what uses the commands in the top level:
There's obviously more in the top level than just this, but I omitted some chunks for clarity.
Code:
-- Signals and constants
-- Positional
signal azimuth, elevation: integer := 0;
signal target_new: unsigned(3 downto 0) := x"1";
signal target_set: unsigned(3 downto 0) := x"0";
signal cmd: unsigned(7 downto 0) := x"00";
-- Status flags
signal Az_idle, El_idle: std_logic;
signal status: unsigned(3 downto 0); -- ? zeroed, search, lock
-- Netduino interface
netduino: entity work.netduino_bridge port map(mclk, net_SCLK, net_MOSI, net_CS, net_MISO, target_new, target_set, status, cmd);
------ PROCESSES ------
-- Deal with netduino commands
process(target_fix) is
begin
-- if both axes are idling, accept new position.
if(Az_idle = '1' and El_idle = '1') then
case target_new is
-- zero position
when "0000" =>
azimuth <= 0;
elevation <= 0;
-- Sat 1
when "0001" =>
azimuth <= 50;
elevation <= 50;
-- Sat 2
when "0010" =>
azimuth <= 100;
elevation <= 300;
-- Sat 3
when "0011" =>
azimuth <= 200;
elevation <= 180;
-- Sat 4
when "0100" =>
azimuth <= 300;
elevation <= 100;
-- Unrecognised; do nothing
when others =>
null;
end case;
end if;
-- wait until pointing is finished and report lack of lock
if (Az_idle = '0' AND El_idle = '0') then
status(0) <= '0';
else
-- once pointing finished, update status
target_set <= target_new;
status(0) <= '1';
end if;
end process;
Last edited: