Friday 21 December 2018

swapping char VHDL FPGA



I want to develop an application that is able to get and store two input values, swap from lower case to upper case only the first value and finally output the two stored values. E.g.: if the input string is "john", then the output string should be "JoHn". The application should get "j" from user_w_write_8_data and store it into my_buffer_a, swap "j" into "J", then get "o" store it into my_buffer_b, then output "J", then output "o". After that the application should get "h" from user_w_write_8_data, swap "h" into "H", and store it into my_buffer_a, then get "n" store it into my_buffer_b, then output "H", then output "n". Basically, the application should store two characters, swap the first one and then output these two, store other two characters, swap the first one and then output these two characters etc. The problem of my application does not swap lower to upper characters that is stored into my_buffer_a. Instead of outputing "JoHn", my application outputs blank line and input random char. My app is based on this code link but I opened a new topic because this logic is quite different! As suggested, I control signals like wr_en , din and full of the XillyBus as well. One more thing, unfortunately I cannot run the simulation but only generate the bitfile and test it right away on my FPGA.



Thanks.


Here the code:


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

entity xillydemo is
port (
PCIE_PERST_B_LS : IN std_logic;

PCIE_REFCLK_N : IN std_logic;
PCIE_REFCLK_P : IN std_logic;
PCIE_RX_N : IN std_logic_vector(3 DOWNTO 0);
PCIE_RX_P : IN std_logic_vector(3 DOWNTO 0);
GPIO_LED : OUT std_logic_vector(3 DOWNTO 0);
PCIE_TX_N : OUT std_logic_vector(3 DOWNTO 0);
PCIE_TX_P : OUT std_logic_vector(3 DOWNTO 0));
end xillydemo;

architecture sample_arch of xillydemo is

component xillybus
port (
PCIE_PERST_B_LS : IN std_logic;
PCIE_REFCLK_N : IN std_logic;
PCIE_REFCLK_P : IN std_logic;
PCIE_RX_N : IN std_logic_vector(3 DOWNTO 0);
PCIE_RX_P : IN std_logic_vector(3 DOWNTO 0);
GPIO_LED : OUT std_logic_vector(3 DOWNTO 0);
PCIE_TX_N : OUT std_logic_vector(3 DOWNTO 0);
PCIE_TX_P : OUT std_logic_vector(3 DOWNTO 0);

bus_clk : OUT std_logic;
quiesce : OUT std_logic;
user_r_mem_8_rden : OUT std_logic;
user_r_mem_8_empty : IN std_logic;
user_r_mem_8_data : IN std_logic_vector(7 DOWNTO 0);
user_r_mem_8_eof : IN std_logic;
user_r_mem_8_open : OUT std_logic;
user_w_mem_8_wren : OUT std_logic;
user_w_mem_8_full : IN std_logic;
user_w_mem_8_data : OUT std_logic_vector(7 DOWNTO 0);

user_w_mem_8_open : OUT std_logic;
user_mem_8_addr : OUT std_logic_vector(4 DOWNTO 0);
user_mem_8_addr_update : OUT std_logic;
user_r_read_32_rden : OUT std_logic;
user_r_read_32_empty : IN std_logic;
user_r_read_32_data : IN std_logic_vector(31 DOWNTO 0);
user_r_read_32_eof : IN std_logic;
user_r_read_32_open : OUT std_logic;
user_r_read_8_rden : OUT std_logic;
user_r_read_8_empty : IN std_logic;

user_r_read_8_data : IN std_logic_vector(7 DOWNTO 0);
user_r_read_8_eof : IN std_logic;
user_r_read_8_open : OUT std_logic;
user_w_write_32_wren : OUT std_logic;
user_w_write_32_full : IN std_logic;
user_w_write_32_data : OUT std_logic_vector(31 DOWNTO 0);
user_w_write_32_open : OUT std_logic;
user_w_write_8_wren : OUT std_logic;
user_w_write_8_full : IN std_logic;
user_w_write_8_data : OUT std_logic_vector(7 DOWNTO 0);

user_w_write_8_open : OUT std_logic);
end component;

component fifo_8x2048
port (
clk: IN std_logic;
srst: IN std_logic;
din: IN std_logic_VECTOR(7 downto 0);
wr_en: IN std_logic;
rd_en: IN std_logic;

dout: OUT std_logic_VECTOR(7 downto 0);
full: OUT std_logic;
empty: OUT std_logic);
end component;

component fifo_32x512
port (
clk: IN std_logic;
srst: IN std_logic;
din: IN std_logic_VECTOR(31 downto 0);

wr_en: IN std_logic;
rd_en: IN std_logic;
dout: OUT std_logic_VECTOR(31 downto 0);
full: OUT std_logic;
empty: OUT std_logic);
end component;

-- Synplicity black box declaration
attribute syn_black_box : boolean;
attribute syn_black_box of fifo_32x512: component is true;

attribute syn_black_box of fifo_8x2048: component is true;

type demo_mem is array(0 TO 31) of std_logic_vector(7 DOWNTO 0);
signal demoarray : demo_mem;

signal bus_clk : std_logic;
signal quiesce : std_logic;

signal reset_8 : std_logic;
signal reset_32 : std_logic;


signal ram_addr : integer range 0 to 31;

signal user_r_mem_8_rden : std_logic;
signal user_r_mem_8_empty : std_logic;
signal user_r_mem_8_data : std_logic_vector(7 DOWNTO 0);
signal user_r_mem_8_eof : std_logic;
signal user_r_mem_8_open : std_logic;
signal user_w_mem_8_wren : std_logic;
signal user_w_mem_8_full : std_logic;

signal user_w_mem_8_data : std_logic_vector(7 DOWNTO 0);
signal user_w_mem_8_open : std_logic;
signal user_mem_8_addr : std_logic_vector(4 DOWNTO 0);
signal user_mem_8_addr_update : std_logic;
signal user_r_read_32_rden : std_logic;
signal user_r_read_32_empty : std_logic;
signal user_r_read_32_data : std_logic_vector(31 DOWNTO 0);
signal user_r_read_32_eof : std_logic;
signal user_r_read_32_open : std_logic;
signal user_r_read_8_rden : std_logic;

signal user_r_read_8_empty : std_logic;
signal user_r_read_8_data : std_logic_vector(7 DOWNTO 0);
signal user_r_read_8_eof : std_logic;
signal user_r_read_8_open : std_logic;
signal user_w_write_32_wren : std_logic;
signal user_w_write_32_full : std_logic;
signal user_w_write_32_data : std_logic_vector(31 DOWNTO 0);
signal user_w_write_32_open : std_logic;
signal user_w_write_8_wren : std_logic;
signal user_w_write_8_full : std_logic;

signal user_w_write_8_data : std_logic_vector(7 DOWNTO 0);
signal user_w_write_8_open : std_logic;

signal wr_en : std_logic := '0';
signal rd_en : std_logic := '0';
signal full : std_logic := '0';
signal empty : std_logic := '0';

signal my_buffer_a : std_logic_vector(7 downto 0) := (others => '0');
signal my_buffer_b : std_logic_vector(7 downto 0) := (others => '0');

signal counter : integer := 0;



begin
xillybus_ins : xillybus
port map (
-- Ports related to /dev/xillybus_mem_8
-- FPGA to CPU signals:
user_r_mem_8_rden => user_r_mem_8_rden,

user_r_mem_8_empty => user_r_mem_8_empty,
user_r_mem_8_data => user_r_mem_8_data,
user_r_mem_8_eof => user_r_mem_8_eof,
user_r_mem_8_open => user_r_mem_8_open,
-- CPU to FPGA signals:
user_w_mem_8_wren => user_w_mem_8_wren,
user_w_mem_8_full => user_w_mem_8_full,
user_w_mem_8_data => user_w_mem_8_data,
user_w_mem_8_open => user_w_mem_8_open,
-- Address signals:

user_mem_8_addr => user_mem_8_addr,
user_mem_8_addr_update => user_mem_8_addr_update,

-- Ports related to /dev/xillybus_read_32
-- FPGA to CPU signals:
user_r_read_32_rden => user_r_read_32_rden,
user_r_read_32_empty => user_r_read_32_empty,
user_r_read_32_data => user_r_read_32_data,
user_r_read_32_eof => user_r_read_32_eof,
user_r_read_32_open => user_r_read_32_open,


-- Ports related to /dev/xillybus_read_8
-- FPGA to CPU signals:
user_r_read_8_rden => user_r_read_8_rden,
user_r_read_8_empty => user_r_read_8_empty,
user_r_read_8_data => user_r_read_8_data,
user_r_read_8_eof => user_r_read_8_eof,
user_r_read_8_open => user_r_read_8_open,

-- Ports related to /dev/xillybus_write_32

-- CPU to FPGA signals:
user_w_write_32_wren => user_w_write_32_wren,
user_w_write_32_full => user_w_write_32_full,
user_w_write_32_data => user_w_write_32_data,
user_w_write_32_open => user_w_write_32_open,

-- Ports related to /dev/xillybus_write_8
-- CPU to FPGA signals:
user_w_write_8_wren => user_w_write_8_wren,
user_w_write_8_full => user_w_write_8_full,

user_w_write_8_data => user_w_write_8_data,
user_w_write_8_open => user_w_write_8_open,

-- General signals
PCIE_PERST_B_LS => PCIE_PERST_B_LS,
PCIE_REFCLK_N => PCIE_REFCLK_N,
PCIE_REFCLK_P => PCIE_REFCLK_P,
PCIE_RX_N => PCIE_RX_N,
PCIE_RX_P => PCIE_RX_P,
GPIO_LED => GPIO_LED,

PCIE_TX_N => PCIE_TX_N,
PCIE_TX_P => PCIE_TX_P,
bus_clk => bus_clk,
quiesce => quiesce
);

-- A simple inferred RAM

ram_addr <= conv_integer(user_mem_8_addr);


process (bus_clk)

begin
if (bus_clk'event and bus_clk = '1') then

wr_en <= user_w_write_8_wren;
full <= user_w_write_8_full;
if (user_w_write_8_wren='1' and counter = 0) then
my_buffer_a <= user_w_write_8_data;
counter <= 1;

elsif (user_w_write_8_wren='1' and counter = 1) then
my_buffer_b <= user_w_write_8_data;
counter <= 2;
elsif (counter = 2) then
full <= '1';
din <= my_buffer_a;
counter <= 3;
elsif (counter = 3) then
full <= '1';
din <= my_buffer_b;

counter <= 0;
end if;
end if;

end process;

user_r_mem_8_empty <= '0';
user_r_mem_8_eof <= '0';
user_w_mem_8_full <= '0';


-- 32-bit loopback

fifo_32 : fifo_32x512
port map(
clk => bus_clk,
srst => reset_32,
din => user_w_write_32_data,
wr_en => user_w_write_32_wren,
rd_en => user_r_read_32_rden,
dout => user_r_read_32_data,

full => user_w_write_32_full,
empty => user_r_read_32_empty
);

reset_32 <= not (user_w_write_32_open or user_r_read_32_open);

user_r_read_32_eof <= '0';

-- 8-bit loopback


fifo_8 : fifo_8x2048
port map(
clk => bus_clk,
srst => reset_8,
din => din,
wr_en => wr_en,
rd_en => user_r_read_8_rden,
dout => user_r_read_8_data,
full => full,
empty => user_r_read_8_empty

);

reset_8 <= not (user_w_write_8_open or user_r_read_8_open);

user_r_read_8_eof <= '0';

end sample_arch;

EDIT: Now, counter and buffers are signals instead of variables, so I'm sure they'll be sampled on the next clock cycle. Here, I would like to put some comments about my logic because I do not understand why it does not work.


begin 

if (bus_clk'event and bus_clk = '1') then
wr_en <= user_w_write_8_wren; --initialize wr_en
full <= user_w_write_8_full; --initialize full
if (user_w_write_8_wren='1' and counter = 0) then --there data on write device file
my_buffer_a <= user_w_write_8_data; --move the input data on buffer_a
counter <= 1;
elsif (user_w_write_8_wren='1' and counter = 1) then --there data on write device file
my_buffer_b <= user_w_write_8_data; --move the input data on buffer_b
counter <= 2;
elsif (counter = 2) then

full <= '1'; --do not accept more data
din <= my_buffer_a; --take data stored in buffer_a and move it into read_device_file
counter <= 3;
elsif (counter = 3) then
full <= '1'; --do not accept more data
din <= my_buffer_b; --take data stored in buffer_b and move it into read_device_file
counter <= 0;
end if;
end if;
end process;


1-Why should I have to initialize rd_en and empty? Well, I don't understand where I have to use them in my logic. I think I do not need information about read_device_file such as no more data can be read or there is valid data on read_device_file.


2-Why does wr_en contain the old value of user_w_write_8_wren? Since I do wr_en <= user_w_write_8_wren;, wr_en should contain the actual value of user_w_write_8_wren, isn't it?



Answer




1-Why should I have to initialize rd_en and empty?



You have not to "initialize" this signals. Just connect them properly to the XillyBus.


The output empty of the FIFO indicates whether data is available in the FIFO. If it's low, then more data can be read from the FIFO. This output should be connected to the signal user_r_read_8_empty which is connected to the same-named input of the XillyBus.


The input rd_en of the FIFO should be connected to the signal user_r_read_8_rden which is connected to the same-named output of the XillyBus. This signal is driven high by the XillyBus, if it wants to read data from the FIFO.



For you intended design, you have to replace the FIFO as described at the end of this answer.



2-Why does wr_en contain the old value of user_w_write_8_wren?



Because signal assigments in a process (with operator <=) are delayed until the next wait statement. Only variable assigments (with operator :=) have an immediate effect.


Your process(bus_clk) does not have an explicit wait statement. But, it has an implicit one, because a process with a sensitivity list (the (bus_clock)) is equal to a process without a sensitivity list with a wait on statement at the end. Thus, your code equals:


process
begin
if (bus_clk'event and bus_clk = '1') then
wr_en <= user_w_write_8_wren;

full <= user_w_write_8_full;
if (user_w_write_8_wren='1' and counter = 0) then
...
end if;
end if;
wait on bus_clock;
end process;

The signal assignments to wr_en and full (as well as all other signal assigments in this process) are applied at the end of the process. Thus, if you would check the value of wr_en in the if conditions, always the still valid old value would be used.


For example, in hardware the signal wr_en would be implemented with a D flip-flop which is triggered by the rising edge of bus_clk here. The signal wr_en would be the output of the D flip-flop and the expression on the right side of the signal assignment (user_w_write_8_wren) the input of this D flip-flop. Thus, wr_en is user_w_write_8_wren delayed by one clock cycle in this example.



How you should proceed:


I recommend to restart from the XillyBus loopback demo (xillydemo). Then you should encapsulate your own logic into a separaty entity which replaces the FIFO fifo_8. More on this topic, I have written in an answer to the other question.


No comments:

Post a Comment

arduino - Can I use TI&#39;s cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...