How to read STD_LOGIC_VECTOR from SPI Bus - linux-kernel

I am working on a custom PCBA and attempting to figure out how to read a defined value from the CPLD from Linux. I have an SPI bus connected between an AM335x processor and a MAX V CPLD, wherein the following is defined within the CPLD:
version : STD_LOGIC_VECTOR := x"0100"); --data width in bits
COMPONENT spi_slave
GENERIC ( cpol : STD_LOGIC := '0'; cpha : STD_LOGIC := '1'; d_width : INTEGER := 16 );
PORT
(
data : IN STD_LOGIC_VECTOR(d_width-1 DOWNTO 0);
sclk : IN STD_LOGIC;
ss_n : IN STD_LOGIC;
mosi : IN STD_LOGIC;
miso : OUT STD_LOGIC
);
END COMPONENT;
And the following is the configuration in the device tree:
spi#481a0000 {
compatible = "ti, omap4-mcspi;
#address-cells = <0x1>;
#size-cells = <0x0>;
reg = <0x481a0000 0x400>;
interrupts = <0x7d>;
ti, spi-num-cs = <0x2>;
ti, hwmods = "spi1";
dmas = <0x2c 0x2a 0x0 0x2c 0x2b 0x0 0x2c 0x2c 0x0 0x2c 0x2d 0x0>;
dma-names = "tx0", "rx0", "tx1", "rx1";
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <0x3c>;
ti,pindir-d0-out-d1-in;
cpld_spidev#0 {
status = "okay";
compatible = "linux,spidev";
spi-max-frequency = <0xf4240>;
reg = <0x0>;
};
};
I have been able to send messages to spidev0.0, but most of what I have been getting back is garbage. How do I get 0x0100 back from the SPI slave?

Related

4-bit counter in AHDL

I have to write 4 bit counter in AHDL.
I haven't had contact with AHDL before.
The task is:
Please implement a 4 digit counter (BCD counting) in the circuit
Cyclone IV EP3CE115F29C7 FPGA being the heart of the commissioning
system De2-115 from terasic.
The counter should work with a 1Hz clock to be able to observe the change of states
display in development kit.
The outputs of the seven-segment decoders should be connected to the appropriate
FPGA pins to enable display control.
The final program should allow FPGA programming and observations
counter counting.
I have something similar in VHDL. Can you guys can help me how to rewrite this to altera?
Is there any converter maybe? I saw something like this but only from AHDL to VHDL.
I will be grateful for all the tips.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bcd_counter is
generic (
width : integer := 4
);
port (
clk : in std_logic;
enable : in std_logic;
reset : in std_logic;
output : out std_logic_vector(width - 1 downto 0)
);
end entity bcd_counter;
architecture behaviour of bcd_counter is
signal state : unsigned (2 ** width - 1 downto 0);
begin
output <= std_logic_vector(state);
count : process(clk, reset, enable)
begin
if(reset = '0') then
state <= (others=> '0');
elsif(rising_edge(clk) and enable = '1') then
state <= state + 1;
end if;
end process count;
end architecture behaviour;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter_logic is
generic (
digits : integer := 4
);
port (
clk : in std_logic;
reset : in std_logic;
output : out std_logic_vector (4 * digits - 1 downto 0)
);
end entity counter_logic;
architecture behaviour of counter_logic is
constant digitWidth : integer := 4;
signal state : std_logic_vector(digitWidth * digits -1 downto 0);
signal resetLines : std_logic_vector(digits - 1 downto 0);
signal enableLines : std_logic_vector(digits - 1 downto 0);
component bcd_counter is
generic (
width : integer := 4
);
port (
clk : in std_logic;
enable : in std_logic;
reset : in std_logic;
output : out std_logic_vector(width - 1 downto 0)
);
end component;
begin
counters: for i in digits - 1 downto 0 generate
nthCounter : bcd_counter
generic map (width => digitWidth)
port map (
clk => clk,
enable => enableLines(i),
reset => resetLines(i),
--przypisanie wyjść liczników do linii
output => state((i + 1) * digitWidth - 1 downto i * digitWidth)
);
resetLines(i) <= (not state(i * digitWidth) and state(i * digitWidth + 1) and state(i * digitWidth + 2) and not state(i * digitWidth + 3)) or reset;
end generate counters;
--TODO: add if generate for case of single digit counter
enableLinesCondition: if digitWidth > 1 generate
lines: for i in digits - 2 downto 0 generate
enableLines(i + 1) <= not state(i * digitWidth) and state(i * digitWidth + 1) and state(i * digitWidth + 2) and not state(i * digitWidth + 3);
end generate lines;
end generate enableLinesCondition;
enableLines(0) <= '1';
output <= state;
end architecture behaviour;

using UART in VHDL

I'm trying to use UART communication with a Lattice machox3 and a ft232R. I am trying to use the VHDL file I found on eewiki(Here). For some reason I am not being able to get tx to work when I simulate it. what am I doing wrong? Is there a simple uart implementation I could use? I tried making it myself, scine I just want to transmit, but I wasnt unsuccessful.
here is the waveform Active hdl gives me
this is the top file I am using to get this component to work.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--library machXO3;
--use machXO3.all;
entity UART_TOP is generic (
divisor : integer := 2604 -- Set the Baud Rate Divisor here.
-- Some common values: 300 Baud = 83333, 9600 Baud = 2604, 115200 Baud = 217, 921600 Baud = 27
);
PORT(
reset_n : IN STD_LOGIC; --ascynchronous reset
tx_ena : IN STD_LOGIC; --initiate transmission load on H
tx_busy : OUT STD_LOGIC; --transmission in progress
tx : OUT STD_LOGIC;
CLOCK_UART : in STD_LOGIC;
DIN : IN STD_LOGIC_VECTOR(15 downto 0)
);
end UART_TOP;
architecture Behavior of UART_TOP is
SIGNAL INTERNAL_CLOCK : STD_LOGIC;
SIGNAL MUX_0 : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL MUX_1 : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL MUX_S : STD_LOGIC_VECTOR(1 downto 0);
SIGNAL txEN: STD_LOGIC_VECTOR(0 downto 0);
SIGNAL counter : STD_LOGIC;
SIGNAL DATAsnd : STD_LOGIC_VECTOR(7 downto 0);
SIGNAL LOAD : STD_LOGIC;
---------------------------------------------------
-- Buffer Input --
---------------------------------------------------
COMPONENT NOTM is
PORT(
Input : in STD_LOGIC;
Output : out STD_LOGIC
);
END COMPONENT;
---------------------------------------------------
-- Buffer Input --
---------------------------------------------------
COMPONENT InputBuffer is
generic(n: natural);
PORT(
clk : in STD_LOGIC;
En : in STD_LOGIC; -- 0 is enabled
Input : in STD_LOGIC_VECTOR (n-1 downto 0);
Output : out STD_LOGIC_VECTOR (n-1 downto 0)
);
END COMPONENT;
---------------------------------------------------
-- MUX04_2_1 --
---------------------------------------------------
COMPONENT MUX421 is
generic (
DATAWIDTH : natural := 8
);
port(
A : in STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0);
B : in STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0);
C : in STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0);
D : in STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0);
S : in STD_LOGIC_VECTOR(1 downto 0);
O : OUT STD_LOGIC_VECTOR(DATAWIDTH-1 downto 0)
);
END COMPONENT;
---------------------------------------------------
-- Binary Counter --
---------------------------------------------------
COMPONENT binary_counter is
generic(
MIN_COUNT : natural := 0;
MAX_COUNT : natural := 17
);
port(
clk : in std_logic;
reset : in std_logic;
enable : in std_logic; -- 0 is enabled
q : out STD_LOGIC_VECTOR(MAX_COUNT-1 downto 0)
);
END COMPONENT;
---------------------------------------------------
-- UART. Mach0X3 --
---------------------------------------------------
COMPONENT uart_c IS
GENERIC(
clk_freq : INTEGER := 50_000_000; --frequency of system clock in Hertz
baud_rate : INTEGER := 19_200; --data link baud rate in bits/second
os_rate : INTEGER := 16; --oversampling rate to find center of receive bits (in samples per baud period)
d_width : INTEGER := 8; --data bus width
parity : INTEGER := 1; --0 for no parity, 1 for parity
parity_eo : STD_LOGIC := '0'); --'0' for even, '1' for odd parity
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --ascynchronous reset
tx_ena : IN STD_LOGIC; --initiate transmission load on H
tx_data : IN STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data to transmit
rx : IN STD_LOGIC; --receive pin
rx_busy : OUT STD_LOGIC; --data reception in progress
rx_error : OUT STD_LOGIC; --start, parity, or stop bit error detected
rx_data : OUT STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data received
tx_busy : OUT STD_LOGIC; --transmission in progress
tx : OUT STD_LOGIC); --transmit pin
END COMPONENT;
begin
-- UART
DATAOUT: UART_c
PORT MAP ( CLK => CLOCK_UART, --system clock
reset_n =>reset_n, --ascynchronous reset
tx_ena => tx_ena,--txEN(0), --initiate transmission
tx_data => DIN(7 downto 0), --data to transmit
rx =>'0' , --receive pin
tx => tx, --transmit pin
tx_busy => tx_busy
);
--UART LOAD
--LOADER: NOTM
--PORT MAP (INPUT => LOAD, OUTPUT => counter);
-- DATA to MUX
--MUX: MUX421
--PORT MAP (s => MUX_S, A => MUX_0, B => MUX_1, C => X"0D", D => X"0A", O => DO-- DATAsnd
--); -- C => X"0D", D => X"0A" cartidge return and line feed
-- Counter to mux
--cntr: binary_counter
--generic map (MAX_COUNT => 2)
--PORT MAP (
--clk => counter,
--reset => RESET,
--enable => ENABLE,
--q => MUX_S
--);
-- Counter to load
--Load_UART: binary_counter
--generic map (MAX_COUNT => 1)
--PORT MAP (
--clk => CLOCK_UART,
--reset => RESET,
--enable => LOAD,
--q => txEN
--);
--DATA to UART
--UARTBUFFER_0: InputBuffer
--generic map (N => 8)
--PORT MAP ( clk => CLOCK_UART, En =>ENABLE, Input => DIN(15 downto 8), OUTPUT => MUX_0);
--DATA to UART
--UARTBUFFER_1: InputBuffer
--generic map (N => 8)
--PORT MAP ( clk => CLOCK_UART, En =>ENABLE, Input => DIN(7 downto 0), OUTPUT => MUX_1);
end Behavior;
this is the UART itself
--------------------------------------------------------------------------------
--
-- FileName: uart_c.vhd
-- Dependencies: none
-- Design Software: Quartus II 64-bit Version 13.1.0 Build 162 SJ Web Edition
--
-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
--
-- Version History
-- Version 1.0 5/26/2017 Scott Larson
-- Initial Public Release
--
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY uart_c IS
GENERIC(
clk_freq : INTEGER := 50_000_000; --frequency of system clock in Hertz
baud_rate : INTEGER := 19_200; --data link baud rate in bits/second
os_rate : INTEGER := 16; --oversampling rate to find center of receive bits (in samples per baud period)
d_width : INTEGER := 8; --data bus width
parity : INTEGER := 1; --0 for no parity, 1 for parity
parity_eo : STD_LOGIC := '0'); --'0' for even, '1' for odd parity
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --ascynchronous reset
tx_ena : IN STD_LOGIC; --initiate transmission
tx_data : IN STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data to transmit
rx : IN STD_LOGIC; --receive pin
rx_busy : OUT STD_LOGIC; --data reception in progress
rx_error : OUT STD_LOGIC; --start, parity, or stop bit error detected
rx_data : OUT STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data received
tx_busy : OUT STD_LOGIC; --transmission in progress
tx : OUT STD_LOGIC); --transmit pin
END uart_c;
ARCHITECTURE logic OF uart_c IS
TYPE tx_machine IS(idle, transmit); --tranmit state machine data type
TYPE rx_machine IS(idle, receive); --receive state machine data type
SIGNAL tx_state : tx_machine; --transmit state machine
SIGNAL rx_state : rx_machine; --receive state machine
SIGNAL baud_pulse : STD_LOGIC := '0'; --periodic pulse that occurs at the baud rate
SIGNAL os_pulse : STD_LOGIC := '0'; --periodic pulse that occurs at the oversampling rate
SIGNAL parity_error : STD_LOGIC; --receive parity error flag
SIGNAL rx_parity : STD_LOGIC_VECTOR(d_width DOWNTO 0); --calculation of receive parity
SIGNAL tx_parity : STD_LOGIC_VECTOR(d_width DOWNTO 0); --calculation of transmit parity
SIGNAL rx_buffer : STD_LOGIC_VECTOR(parity+d_width DOWNTO 0) := (OTHERS => '0'); --values received
SIGNAL tx_buffer : STD_LOGIC_VECTOR(parity+d_width+1 DOWNTO 0) := (OTHERS => '1'); --values to be transmitted
BEGIN
--generate clock enable pulses at the baud rate and the oversampling rate
PROCESS(reset_n, clk)
VARIABLE count_baud : INTEGER RANGE 0 TO clk_freq/baud_rate-1 := 0; --counter to determine baud rate period
VARIABLE count_os : INTEGER RANGE 0 TO clk_freq/baud_rate/os_rate-1 := 0; --counter to determine oversampling period
BEGIN
IF(reset_n = '0') THEN --asynchronous reset asserted
baud_pulse <= '0'; --reset baud rate pulse
os_pulse <= '0'; --reset oversampling rate pulse
count_baud := 0; --reset baud period counter
count_os := 0; --reset oversampling period counter
ELSIF(clk'EVENT AND clk = '1') THEN
--create baud enable pulse
IF(count_baud < clk_freq/baud_rate-1) THEN --baud period not reached
count_baud := count_baud + 1; --increment baud period counter
baud_pulse <= '0'; --deassert baud rate pulse
ELSE --baud period reached
count_baud := 0; --reset baud period counter
baud_pulse <= '1'; --assert baud rate pulse
count_os := 0; --reset oversampling period counter to avoid cumulative error
END IF;
--create oversampling enable pulse
IF(count_os < clk_freq/baud_rate/os_rate-1) THEN --oversampling period not reached
count_os := count_os + 1; --increment oversampling period counter
os_pulse <= '0'; --deassert oversampling rate pulse
ELSE --oversampling period reached
count_os := 0; --reset oversampling period counter
os_pulse <= '1'; --assert oversampling pulse
END IF;
END IF;
END PROCESS;
--receive state machine
PROCESS(reset_n, clk)
VARIABLE rx_count : INTEGER RANGE 0 TO parity+d_width+2 := 0; --count the bits received
VARIABLE os_count : INTEGER RANGE 0 TO os_rate-1 := 0; --count the oversampling rate pulses
BEGIN
IF(reset_n = '0') THEN --asynchronous reset asserted
os_count := 0; --clear oversampling pulse counter
rx_count := 0; --clear receive bit counter
rx_busy <= '0'; --clear receive busy signal
rx_error <= '0'; --clear receive errors
rx_data <= (OTHERS => '0'); --clear received data output
rx_state <= idle; --put in idle state
ELSIF(clk'EVENT AND clk = '1' AND os_pulse = '1') THEN --enable clock at oversampling rate
CASE rx_state IS
WHEN idle => --idle state
rx_busy <= '0'; --clear receive busy flag
IF(rx = '0') THEN --start bit might be present
IF(os_count < os_rate/2) THEN --oversampling pulse counter is not at start bit center
os_count := os_count + 1; --increment oversampling pulse counter
rx_state <= idle; --remain in idle state
ELSE --oversampling pulse counter is at bit center
os_count := 0; --clear oversampling pulse counter
rx_count := 0; --clear the bits received counter
rx_busy <= '1'; --assert busy flag
rx_state <= receive; --advance to receive state
END IF;
ELSE --start bit not present
os_count := 0; --clear oversampling pulse counter
rx_state <= idle; --remain in idle state
END IF;
WHEN receive => --receive state
IF(os_count < os_rate-1) THEN --not center of bit
os_count := os_count + 1; --increment oversampling pulse counter
rx_state <= receive; --remain in receive state
ELSIF(rx_count < parity+d_width) THEN --center of bit and not all bits received
os_count := 0; --reset oversampling pulse counter
rx_count := rx_count + 1; --increment number of bits received counter
rx_buffer <= rx & rx_buffer(parity+d_width DOWNTO 1); --shift new received bit into receive buffer
rx_state <= receive; --remain in receive state
ELSE --center of stop bit
rx_data <= rx_buffer(d_width DOWNTO 1); --output data received to user logic
rx_error <= rx_buffer(0) OR parity_error OR NOT rx; --output start, parity, and stop bit error flag
rx_busy <= '0'; --deassert received busy flag
rx_state <= idle; --return to idle state
END IF;
END CASE;
END IF;
END PROCESS;
--receive parity calculation logic
rx_parity(0) <= parity_eo;
rx_parity_logic: FOR i IN 0 to d_width-1 GENERATE
rx_parity(i+1) <= rx_parity(i) XOR rx_buffer(i+1);
END GENERATE;
WITH parity SELECT --compare calculated parity bit with received parity bit to determine error
parity_error <= rx_parity(d_width) XOR rx_buffer(parity+d_width) WHEN 1, --using parity
'0' WHEN OTHERS; --not using parity
--transmit state machine
PROCESS(reset_n, clk)
VARIABLE tx_count : INTEGER RANGE 0 TO parity+d_width+3 := 0; --count bits transmitted
BEGIN
IF(reset_n = '0') THEN --asynchronous reset asserted
tx_count := 0; --clear transmit bit counter
tx <= '1'; --set tx pin to idle value of high
tx_busy <= '1'; --set transmit busy signal to indicate unavailable
tx_state <= idle; --set tx state machine to ready state
ELSIF(clk'EVENT AND clk = '1') THEN
CASE tx_state IS
WHEN idle => --idle state
IF(tx_ena = '1') THEN --new transaction latched in
tx_buffer(d_width+1 DOWNTO 0) <= tx_data & '0' & '1'; --latch in data for transmission and start/stop bits
IF(parity = 1) THEN --if parity is used
tx_buffer(parity+d_width+1) <= tx_parity(d_width); --latch in parity bit from parity logic
END IF;
tx_busy <= '1'; --assert transmit busy flag
tx_count := 0; --clear transmit bit count
tx_state <= transmit; --proceed to transmit state
ELSE --no new transaction initiated
tx_busy <= '0'; --clear transmit busy flag
tx_state <= idle; --remain in idle state
END IF;
WHEN transmit => --transmit state
IF(baud_pulse = '1') THEN --beginning of bit
tx_count := tx_count + 1; --increment transmit bit counter
tx_buffer <= '1' & tx_buffer(parity+d_width+1 DOWNTO 1); --shift transmit buffer to output next bit
END IF;
IF(tx_count < parity+d_width+3) THEN --not all bits transmitted
tx_state <= transmit; --remain in transmit state
ELSE --all bits transmitted
tx_state <= idle; --return to idle state
END IF;
END CASE;
tx <= tx_buffer(0); --output last bit in transmit transaction buffer
END IF;
END PROCESS;
--transmit parity calculation logic
tx_parity(0) <= parity_eo;
tx_parity_logic: FOR i IN 0 to d_width-1 GENERATE
tx_parity(i+1) <= tx_parity(i) XOR tx_data(i);
END GENERATE;
END logic;
and this is the test bench
-- VHDL Test Bench Created from source file UART_TOP.vhd -- Sun Aug 19 12:41:55 2018
--
-- Notes:
-- 1) This testbench template has been automatically generated using types
-- std_logic and std_logic_vector for the ports of the unit under test.
-- Lattice recommends that these types always be used for the top-level
-- I/O of a design in order to guarantee that the testbench will bind
-- correctly to the timing (post-route) simulation model.
-- 2) To use this template as your testbench, change the filename to any
-- name of your choice with the extension .vhd, and use the "source->import"
-- menu in the ispLEVER Project Navigator to import the testbench.
-- Then edit the user defined section below, adding code to generate the
-- stimulus for your design.
-- 3) VHDL simulations will produce errors if there are Lattice FPGA library
-- elements in your design that require the instantiation of GSR, PUR, and
-- TSALL and they are not present in the testbench. For more information see
-- the How To section of online help.
--
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY testbench IS
END testbench;
ARCHITECTURE behavior OF testbench IS
COMPONENT UART_TOP
PORT(
reset_n : IN std_logic;
tx_ena : IN std_logic;
CLOCK_UART : IN std_logic;
DIN : IN std_logic_vector(15 downto 0);
tx_busy : OUT std_logic;
tx : OUT std_logic
);
END COMPONENT;
SIGNAL reset_n : std_logic;
SIGNAL tx_ena : std_logic;
SIGNAL tx_busy : std_logic;
SIGNAL tx : std_logic;
SIGNAL CLOCK_UART : std_logic;
SIGNAL DIN : std_logic_vector(15 downto 0);
constant half_period : time := 10 ns;
BEGIN
-- Please check and add your generic clause manually
uut: UART_TOP PORT MAP(
reset_n => reset_n,
tx_ena => tx_ena,
tx_busy => tx_busy,
tx => tx,
CLOCK_UART => CLOCK_UART,
DIN => DIN
);
-- *** Test Bench - User Defined Section ***
tb : PROCESS
BEGIN
reset_n <= '1';
tx_ena <= '0';
DIN <= B"0101010101010101";
CLOCK_UART <= '1';
wait for half_period ;
CLOCK_UART <= '0';
wait for half_period ;
CLOCK_UART <= '1';
wait for half_period ;
CLOCK_UART <= '0';
wait for half_period ;
tx_ena <= '1';
loop
CLOCK_UART <= '1';
wait for half_period ;
tx_ena <= '0';
CLOCK_UART <= '0';
wait for half_period ;
end loop;
END PROCESS;
-- *** End Test Bench - User Defined Section ***
END;

problems writing to an avalon slave module

I'm woring on a project for an assingment where I need to be able write data to an avalon slave module to select data from 2 different inputs on a nios system running on a DE0 board. After much toiling, I've been unable to write data from the C app running on the nios core to the avalon slave. I have verified that I'm able to read data from the slave by using some hard coded values. I have also verified that my app is running because I'm seeing the messages I expect over the jtag uart, and the push buttons, LEDs and LED display work as expected.
I have simplified my slave so that data I write to it is then read straight back. The VHDL code is:
library ieee;
use ieee.std_logic_1164.all;
USE IEEE.NUMERIC_STD.ALL;
entity FIFO_Control is
port (clk : IN std_logic;
reset : IN std_logic;
read : IN std_logic;
readdata : OUT std_logic_vector(7 DOWNTO 0);
write : IN std_logic;
writedata : IN std_logic_vector(7 DOWNTO 0);
din1 : in std_logic_vector(4 DOWNTO 0);
din2 : in std_logic_vector(4 DOWNTO 0)
);
end FIFO_Control;
architecture FIFO_CTRL of FIFO_Control is
signal int_data : std_logic_vector(7 DOWNTO 0) := "00000000"; -- a hard coded test value to check the read works
begin
with (write) SELECT
int_data <= writedata when '1',
"01010101" when others;
readdata <= int_data;
end FIFO_CTRL;
The C code is
#include "sys/alt_stdio.h"
#include <altera_avalon_timer_regs.h>
#include <altera_avalon_pio_regs.h>
#include <system.h>
#include "Sch51.h"
#include "serial.h"
#include "seven_seg.h"
#define SEVEN_SEGMENT_0_BASE 0x1001080
#define LED_BASE (0x01001070)
#define LED0_pin (0x01)
#define LED1_pin (0x01 << 1)
#define LED2_pin (0x01 << 2)
#define LED3_pin (0x01 << 3)
#define PIO_1_BASE 0x0
#define BUTTON_BASE PIO_1_BASE
#define BUTTON0 0x01
#define BUTTON1 0x02
#define FIFO_CTRL_0_BASE 0x1001090
void LED_Flash_Update(void)
{
static count = 0;
alt_u8 read;
IOWR_8DIRECT(FIFO_CTRL_0_BASE, 0, 0);
read = IORD_8DIRECT(FIFO_CTRL_0_BASE, 0);
Serial_Printf("FIFO1: %d\r\n", read);
IOWR_8DIRECT(FIFO_CTRL_0_BASE, 0, 1);
read = IORD_8DIRECT(FIFO_CTRL_0_BASE, 0);
Serial_Printf("FIFO1: %d\r\n", read);
// Change the LED from OFF to ON (or vice versa)
IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,
IORD_ALTERA_AVALON_PIO_DATA(LED_BASE) ^ LED3_pin);
if (count < 10)
{
count++;
}
else if ((count >= 10) && (count < 100))
{
count += 10;
}
else if ((count >= 100) && (count < 1000))
{
count += 100;
}
else if ((count >= 1000) && (count < 10000))
{
count += 1000;
}
else
{
count = 0;
}
seven_seg_store_number(SEVEN_SEGMENT_0_BASE, 0, 9999, 10, count);
if ((IORD_ALTERA_AVALON_PIO_DATA(BUTTON_BASE) & BUTTON0) == 0)
{
IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,
IORD_ALTERA_AVALON_PIO_DATA(LED_BASE) | LED0_pin);
}
else
{
IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,
IORD_ALTERA_AVALON_PIO_DATA(LED_BASE) & ~LED0_pin);
}
if ((IORD_ALTERA_AVALON_PIO_DATA(BUTTON_BASE) & BUTTON1) == 0)
{
IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,
IORD_ALTERA_AVALON_PIO_DATA(LED_BASE) | LED1_pin);
}
else
{
IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,
IORD_ALTERA_AVALON_PIO_DATA(LED_BASE) & ~LED1_pin);
}
}
int alt_main()
{
alt_u8 read;
SCH_Init_T0();
serial_Init();
SCH_Add_Task(serial_Update, 0, 10);
SCH_Add_Task(LED_Flash_Update, 0, 1000);
// Start the scheduler
SCH_Start();
Serial_Puts("EHMC AJE System Running\n");
/* Event loop never exits. */
while (1)
{
SCH_Dispatch_Tasks();
}
return 0;
}
I'm not able to see why I'm not able to write anything to the avalon slave "Fifo_control". Can someone suggest what the problem is please?
If you look at the port declarations on your entity/component and then at your code, you can already see that you are doing something wrong, as you are not using all the port.
So your problem states that you want to write data to your Avalon slave. So you want the component to remember the data you've written (i.e. memory). But there is no memory component in your code. There's just a combinatorial expression.
When designing an Avalon component, you should read the Avalon Interface Specification.
So reading the document, you see that you should have a process/statement for the write port and a process for the read port. Each takes a clock cycle to process (if the read latency is 1). E.g.
write_proc: process(clk) begin
if rising_edge(clk) then
if write = '1' then
int_data <= writedata;
end if;
-- reset statement
if reset = '1' then
int_data <= (others => '0');
end if;
end if;
end process;
read_proc: process(clk) begin
if rising_edge(clk) then
if read = '1' then
readdata <= int_data;
end if;
-- reset statement
if reset = '1' then
readdata <= (others => '0');
end if;
end if;
end process;

DMA PCIe read transfer from PC to FPGA

I'm trying to get DMA transfer working between an FPGA and an x86_64 Linux machine.
On the PC side I'm doing this initialization:
//driver probe
...
pci_set_master(dev); //set endpoint as master
result = pci_set_dma_mask(dev, 0xffffffffffffffff); //set as 64bit capable
...
//read
pagePointer = __get_free_page(__GFP_HIGHMEM); //get 1 page
temp_addr = dma_map_page(&myPCIDev->dev,pagePointer,0,PAGE_SIZE,DMA_TO_DEVICE);
printk(KERN_WARNING "[%s]Page address: 0x%lx Bus address: 0x%lx\n",DEVICE_NAME,pagePointer,temp_addr);
writeq(cpu_to_be64(temp_addr),bar0Addr); //send address to FPGA
wmb();
writeq(cpu_to_be64(1),bar1Addr); //start trasnfer
wmb();
The bus address is a 64bits address.
On the FPGA side the TLP I'm sending out for the read of 1 DW:
Fmt: "001"
Type: "00000"
R|TC|R|Attr|R|TH : "00000000"
TD|EP|Attr|AT : "000000"
Length : "0000000001"
Requester ID
Tag : "00000000"
Byte Enable : "00001111";
Address : (address from dma map page)
The completion that I get back from the PC is :
Fmt: "000"
Type: "01010"
R|TC|R|Attr|R|TH : "00000000"
TD|EP|Attr|AT : "000000"
Length : "0000000000"
Completer ID
Compl Status|BCM : "0010"
Length : "0000000000";
Requester ID
Tag : "00000000"
R|Lower address : "00000000"
so basically a completion without data and with the status Unsupported Request.
I don't think there is something wrong on the construction of the TLP but I cannot see any problem on the driver side either.
The kernel I'm using has the PCIe error reporting enabled but I see nothing in the dmesg output.
What's wrong? Or, is there a way to find why I get that Unsupported Request
Completion?
Marco
This is an extract from one of my designs (that works!). It's VHDL and slightly different but hopefully it will help you:
-- First dword of TLP Header
tlp_header_0(31 downto 30) <= "01"; -- Format = MemWr
tlp_header_0(29) <= '0' when pcie_addr(63 downto 32) = 0 else '1'; -- 3DW header or 4DW header
tlp_header_0(28 downto 24) <= "00000"; -- Type
tlp_header_0(23) <= '0'; -- Reserved
tlp_header_0(22 downto 20) <= "000"; -- Default traffic class
tlp_header_0(19) <= '0'; -- Reserved
tlp_header_0(18) <= '0'; -- No ID-based ordering
tlp_header_0(17) <= '0'; -- Reserved
tlp_header_0(16) <= '0'; -- No TLP processing hint
tlp_header_0(15) <= '0'; -- No TLP Digest
tlp_header_0(14) <= '0'; -- Not poisoned
tlp_header_0(13 downto 12) <= "00"; -- No PCI-X relaxed ordering, no snooping
tlp_header_0(11 downto 10) <= "00"; -- No address translation
tlp_header_0( 9 downto 0) <= "00" & X"20"; -- Length = 32 dwords
-- Second dword of TLP Header
-- Bits 31 downto 16 are Requester ID, set by hardware PCIe core
tlp_header_1(15 downto 8) <= X"00"; -- Tag, it may have to increment
tlp_header_1( 7 downto 4) <= "1111"; -- Last dword byte enable
tlp_header_1( 3 downto 0) <= "1111"; -- First dword byte enable
-- Third and fourth dwords of TLP Header, fourth is *not* sent when pcie_addr is 32 bits
tlp_header_2 <= std_logic_vector(pcie_addr(31 downto 0)) when pcie_addr(63 downto 32) = 0 else std_logic_vector(pcie_addr(31 downto 0));
tlp_header_3 <= std_logic_vector(pcie_addr(31 downto 0));
Let's ignore the obvious difference that I was performing MemWr of 32 dwords instead of reading a dword. The other difference, which caused me trouble the first time I did this, is that you have to use 3DW header if the address is below 4GB.
That means you have to check the address you get from the host and determine if you need to use the 3DW header (with only LSBs of address) or the full 4DW header mode.
Unless you need to transfer ungodly amount of data, you can set the dma address mask to 32 bits to be always in the 3DW case, Linux should reserve plenty of memory location below 4GB by default.

Cant display a static image through VGA using handel-c and VHDL

Hi I am having problem to display a static image using handel-c create a test pattern through the DE2-115 VGA.
For some reason I can't output the image to the monitor.
This is my tpad.hcc code:
#include "tpad.hch"
macro proc lcd_driver( lcd ) {
unsigned 24 colour;
unsigned 1 de;
interface bus_out() tpad_RGB( unsigned 24 clr = colour )
//Post pin for RGB color
//with {data = {"V27","U28","U27","R28","R27","V26",
//"T22","T21","R23","R22","R21","P21",
//"J26","L28","V25","V22","U22","V28"},
with {data = {"D12","D11","C12","A11","B11","C11","A10","B10", //BLUE
"C9","F10","B8","C8","H12","F8","G11","G8", //GREEN
"H10","H8","J12","G10","F12","D10","E11","E12"}, //RED
standard = "LVCMOS33"};
interface bus_out() tpad_control( unsigned 3 ctrl = (!__clock) # 1 #de)
with {data = {"C13","F11","A12", "G13","C10"},
standard = "LVCMOS33"};
//VHDL driver
//entity vga_controller is
//port (
// pixel_clk : IN STD_LOGIC; --pixel clock at frequency of VGA mode being used
// reset_n : IN STD_LOGIC; --active low asycnchronous reset
// h_sync : OUT STD_LOGIC; --horiztonal sync pulse
// v_sync : OUT STD_LOGIC; --vertical sync pulse
// disp_ena : OUT STD_LOGIC; --display enable ('1' = display time, '0' = blanking time)
// column : OUT INTEGER; --horizontal pixel coordinate
// row : OUT INTEGER; --vertical pixel coordinate
// n_blank : OUT STD_LOGIC; --direct blacking output to DAC
// n_sync : OUT STD_LOGIC --sync-on-green output to DAC
// );
//END vga_controller;
interface vga_controller( unsigned 11 row, unsigned 11 column, unsigned 1 disp_ena,
unsigned 1 h_sync, unsigned 1 v_sync, unsigned 1 n_sync,
unsigned 1 n_blank)
tpad_lcd( unsigned 1 pixel_clk = __clock, unsigned 1 reset_n = 0)
with {busformat = "B[I]"};
do par {
colour = lcd.r # lcd.g # lcd.b; // Synchronise LCD output signals
//de = !lcd.nb;
de = 1;
lcd.x = tpad_lcd.row;
lcd.y = tpad_lcd.column;
lcd.hs = tpad_lcd.h_sync;
lcd.vs = tpad_lcd.v_sync;
lcd.ns = tpad_lcd.n_sync;
lcd.nb = tpad_lcd.n_blank;
lcd.de = 1;
} while (1);
}
my tpad.hch:
typedef struct {
signal unsigned 11 x, y; // Position on display
signal unsigned 8 r, g, b; // Colour to display
signal unsigned 1 hs, vs, ns, nb, de; // syncronisation signals
} lcd_data;
macro proc lcd_driver( lcd );
This is my demo.hcc:
#include "tpad.hch"
set family = AlteraCycloneIII; /* Really a Cyclone IV */
set part = "EP4CE115F29C7";
interface bus_in (unsigned 1 pin) clock_pin () with {data = {"Y2"}};
interface altpll (unsigned 5 clk with {clockport = 1})
pll (unsigned 2 inclk = 0 # clock_pin.pin)
with {
busformat = "B[N:0]",
properties = {
{"bandwidth_type", "AUTO"},
{"clk0_divide_by", "5"},
{"clk0_duty_cycle", "50"},
{"clk0_multiply_by", "4"},
{"clk0_phase_shift", "0"},
{"compensate_clock", "CLK0"},
{"inclk0_input_frequency", "20000"},
{"intended_device_family", "Cyclone IV E"},
{"lpm_hint", "CBX_MODULE_PREFIX=pll"},
{"lpm_type", "altpll"},
{"operation_mode", "NORMAL"},
{"pll_type", "AUTO"},
{"port_clk0", "PORT_USED"},
{"width_clock", "5"}},
bind = 1};
set clock = internal pll.clk[0];
void main( void ) {
lcd_data lcd;
par {
lcd_driver( lcd );
do par {
lcd.r = lcd.x[7:0]; // Generate a simple test pattern
lcd.g = lcd.y[7:0];
lcd.b = (lcd.x + lcd.y)[9:2];
} while (1);
}
}
This is my VHDL code:
--------------------------------------------------------------------------------
--
-- FileName: vga_controller.vhd
-- Dependencies: none
-- Design Software: Quartus II 64-bit Version 12.1 Build 177 SJ Full Version
--
-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
--
-- Version History
-- Version 1.0 05/10/2013 Scott Larson
-- Initial Public Release
--
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY vga_controller IS
GENERIC(
h_pulse : INTEGER := 128; --horiztonal sync pulse width in pixels
h_bp : INTEGER := 88; --horiztonal back porch width in pixels
h_pixels : INTEGER := 800; --horiztonal display width in pixels
h_fp : INTEGER := 40; --horiztonal front porch width in pixels
h_pol : STD_LOGIC := '1'; --horizontal sync pulse polarity (1 = positive, 0 = negative)
v_pulse : INTEGER := 4; --vertical sync pulse width in rows
v_bp : INTEGER := 23; --vertical back porch width in rows
v_pixels : INTEGER := 600; --vertical display width in rows
v_fp : INTEGER := 1; --vertical front porch width in rows
v_pol : STD_LOGIC := '1'); --vertical sync pulse polarity (1 = positive, 0 = negative)
PORT(
pixel_clk : IN STD_LOGIC; --pixel clock at frequency of VGA mode being used
reset_n : IN STD_LOGIC; --active low asycnchronous reset
h_sync : OUT STD_LOGIC; --horiztonal sync pulse
v_sync : OUT STD_LOGIC; --vertical sync pulse
disp_ena : OUT STD_LOGIC; --display enable ('1' = display time, '0' = blanking time)
column : OUT STD_LOGIC_vector (10 downto 0); --horizontal pixel coordinate
row : OUT STD_LOGIC_vector (10 downto 0); --vertical pixel coordinate
n_blank : OUT STD_LOGIC; --direct blacking output to DAC
n_sync : OUT STD_LOGIC); --sync-on-green output to DAC
END vga_controller;
ARCHITECTURE behavior OF vga_controller IS
CONSTANT h_period : INTEGER := h_pulse + h_bp + h_pixels + h_fp; --total number of pixel clocks in a row
CONSTANT v_period : INTEGER := v_pulse + v_bp + v_pixels + v_fp; --total number of rows in column
BEGIN
n_blank <= '1'; --no direct blanking
n_sync <= '0'; --no sync on green
PROCESS(pixel_clk, reset_n)
VARIABLE h_count : INTEGER RANGE 0 TO h_period - 1 := 0; --horizontal counter (counts the columns)
VARIABLE v_count : INTEGER RANGE 0 TO v_period - 1 := 0; --vertical counter (counts the rows)
--VARIABLE h_count : unsigned (7 downto 0) := "00000000";
--VARIABLE v_count : unsigned (7 downto 0) := "00000000";
BEGIN
IF(reset_n = '0') THEN --reset asserted
h_count := 0; --reset horizontal counter
v_count := 0; --reset vertical counter
h_sync <= NOT h_pol; --deassert horizontal sync
v_sync <= NOT v_pol; --deassert vertical sync
disp_ena <= '0'; --disable display
column <= "00000000000"; --reset column pixel coordinate
row <= "00000000000"; --reset row pixel coordinate
ELSIF(pixel_clk'EVENT AND pixel_clk = '1') THEN
--counters
IF(h_count < h_period - 1) THEN --horizontal counter (pixels)
h_count := h_count + 1;
ELSE
h_count := 0;
IF(v_count < v_period - 1) THEN --veritcal counter (rows)
v_count := v_count + 1;
ELSE
v_count := 0;
END IF;
END IF;
--horizontal sync signal
IF(h_count < h_pixels + h_fp OR h_count > h_pixels + h_fp + h_pulse) THEN
h_sync <= NOT h_pol; --deassert horiztonal sync pulse
ELSE
h_sync <= h_pol; --assert horiztonal sync pulse
END IF;
--vertical sync signal
IF(v_count < v_pixels + v_fp OR v_count > v_pixels + v_fp + v_pulse) THEN
v_sync <= NOT v_pol; --deassert vertical sync pulse
ELSE
v_sync <= v_pol; --assert vertical sync pulse
END IF;
--set pixel coordinates
IF(h_count < h_pixels) THEN --horiztonal display time
--column <= h_count; --set horiztonal pixel coordinate
column <= std_logic_vector(to_unsigned(h_count, column'length)); --set horiztonal pixel coordinate
END IF;
IF(v_count < v_pixels) THEN --vertical display time
--row <= v_count; --set vertical pixel coordinate
row <= std_logic_vector(to_unsigned(v_count, column'length)); --set vertical pixel coordinate
END IF;
--set display enable output
IF(h_count < h_pixels AND v_count < v_pixels) THEN --display time
disp_ena <= '1'; --enable display
ELSE --blanking time
disp_ena <= '0'; --disable display
END IF;
END IF;
END PROCESS;
END behavior;

Resources