How to switch between datasamples in VHDL? - vhdl

I have written a code for my I2S interface. this interface has a PISO function (parallel in and serial out). In my testbench, I've added 2 x 24 bits datasamples (left / right channel). Now I would like to switch between this sample and the new second sample (something like: Left1, Right1 , Left2, Right2 , Left1, Right1).
elsif rising_edge(BCLK) then
PDL_BUF <= PDL1;
PDR_BUF <= PDR1;
READY <= '1';
VALID <= '1';
bitcounter := bitcounter + 1;
if bitcounter = 1 then
WSP <= '1';
else
WSP <= '0';
end if;
if bitcounter >= 0 and bitcounter <= 23 then
WS <= '0';
elsif bitcounter > 24 then -- and bitcounter <= 48
WS <= '1';
WSP <= '0';
end if;
if WS = '0' then
SD <= PDL_BUF(23);
PDL_BUF <= PDL_BUF(22 downto 0) & '0';
else --if WS = '1' then
SD <= PDR_BUF(23);
PDR_BUF <= PDR_BUF(22 downto 0) & '0';
end if;
if bitcounter = 48 then
bitcounter := 0;
end if;
end if;
end process;

this is a block that is repeated twice for two channels, it is clear that you can't access the other channel in that.
you need to add a block let's call it a merging block.
in merging block consider both samples as input then you can have both of them in your code.

Related

VHDL Pulse Generation with External Trigger and Trigger Out

I am stuck in this program to create a custom pulse from external trigger and internal trigger.
Here is my program for external trigger. It will take a trigger signal from "trig_in" input port to generate a custom pulse:
if state_trig = extrig then
if (trig_in = '1') then
counter1 <= "000000";
if(counter >= 1 and counter <= 2) then
pwm_out1 <= '1';
pwm_out2 <= '0';
end if;
if(counter > 2 and counter <= 600) then
pwm_out1 <= '0';
pwm_out2 <= '0';
end if;
if(counter > 600 and counter <= 3000) then
pwm_out1 <= '1';
pwm_out2 <= '1';
end if;
counter <= counter + 1;
else if (trig_in = '0') then
counter <= "000000";
counter1 <= counter1 + 1;
if (counter1 >= 2100) then
pwm_out1 <= '0';
pwm_out2 <= '0';
end if;
end if;
end if;
end if;
And here is the program for internal trigger. It will generate a 1kHz repetition pulse to trigger out on "trig_out" output port:
if state_trig = intrig then
--1kHz
if(i >= 1 and i <= 2) then
pwm_out1 <= '1';
pwm_out2 <= '0';
end if;
if(i > 2 and i <= 600) then
pwm_out1 <= '0';
pwm_out2 <= '0';
end if;
if(i > 600 and i <= 3000) then
pwm_out1 <= '1';
pwm_out2 <= '1';
end if;
if(i > 3000) then
pwm_out1 <= '0';
pwm_out2 <= '0';
end if;
if(i = 300000) then i := 0; end if;
i := i + 1;
end if;
end if;
I use the fsm state to determine for "extrig" and "intrig" state.
type fsm_trig is (none, intrig, extrig);
signal state_trig : fsm_trig := none;
Two programs work separately perfect. But when i put both of them in one process (clock). The pulse which is generated in each trigger program conflicts each other.
I am using UART to determine the state of trigger.
Two signal "pwm_out1" and "pwm_out2" are assigned to output ports to generate the pulse:
out_clk1 <= pwm_out1;
out_clk2 <= pwm_out2;
Here are ports for two programs:
sys_clk : in STD_LOGIC; --system clock
rx : in STD_LOGIC; --receive for UART
trig_in : in STD_LOGIC; --External trigger
trig_out : out STD_LOGIC; --Internal trigger
out_clk1 : out STD_LOGIC; --Pulse out1
out_clk2 : out STD_LOGIC; --Pulse out2
Please give me any idea to avoid the conflicts between two programs.
Thanks in advance.

Interfacing output to a DAC - VHDL

I am trying to interface the output of my FPGA onto a DAC. I am using the PmodDA2 DAC. The trouble I am having is working out how to output the data from a 16bit register into 1 bit per clock cycle.
I have studied the timing diagram and understand that CS needs to send a pulse before data transmission begins.
I have tried using the necessary resets and other features as applicable within my design as a whole.
I tried implementing a count to cycle between 0 to 16/17 and when it was at the beginning it would set CS to high and begin transmission. However I did not believe this would be at all the correct way to do it.
architecture Behavioral of DAC is
signal count : integer range 0 to 15;
signal selected : std_logic;
signal data_storage : std_logic_vector(15 downto 0);
begin
process(D_DAC, CE_DAC, RES_DAC, RES_DAC, data_storage)
begin
if RES_DAC = '1' then
data_storage <= "0000000000000000";
end if;
if rising_edge(CLK_DAC) then
if CE_DAC = '1' then
data_storage <= D_DAC;
end if;
end if;
end if;
end process ;
CS_DAC <= CE_DAC;
SCLK_DAC <= CLK_DAC;
DATA1_DAC <= data_storage;
end Behavioral;
I'm getting myself very confused over this.
I'd appreciate any help.
************************EDIT************************
I have had another go at implementing the counter...
process(D_DAC, CE_DAC, CLK_DAC, RES_DAC, data_storage)
begin
if RES_DAC = '1' then
data_storage <= "0000000000000000";
cound <= 0;
selected <= '0';
elsif rising_edge(CLK_DAC) then
if CE_DAC = '1' then
if count = 0 then
selected <= '1';
end if;
if selected = 1 then
if count = 15 then
count <= 0;
selected <= '0';
else
count <= count + 1;
data_storage <= D_DAC;
end if;
end if;
end if;
end if;
end process ;
CS_DAC <= CE_DAC;
SCLK_DAC <= CLK_DAC;
DATA1_DAC <= data_storage;
end Behavioral;

ERROR:Xst:827 = Signal count cannot be synthesized, bad synchronous description

I am trying to simulate an elevator and as a result i get the error
ERROR:Xst:827 = Signal count cannot be synthesized, bad synchronous description
I am following the code from this source [https://www.youtube.com/watch?v=i03_-NMwmDs] since mine is very similar,(i have 7 floors and two more elevators). At first i am working with the code mentioned on the video and later i am going to implement two more elevators to work together in this simulation.
Thanks in advance.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity elevator is
port (clk: in std_logic;
sensors1: out std_logic:='0'; --sensors at each level for elevator 1
a1, a2, a3, a4, a5, a6, a7: out std_logic; -- for LED display at FPGA
insideopendoor, in1, in2, in3, in4, in5, in1up, in2up, in3up, in4up, in5up, in5down, in4down, in3down, in2down, in1down: std_logic; -- input request for each floor
opendoor: out std_logic; -- from inside elevator
closedoor: out std_logic); -- from inside elevator
end elevator;
architecture sequence of elevator is
constant timedoorclose: integer := 3;
constant timedoorclosed: integer := 2;
constant time_nx_state: integer :=4;
signal demand: std_logic_vector(0 to 4) := "00000";
signal direction_of_elevator : integer range 0 to 2 := 0;
signal updownpassenger : std_logic := '0';
signal signalstatus: std_logic := '1';
type status is (L1, L2, L3, L4, L5);
signal pr_state, nx_state: status;
begin
main: process (clk, insideopendoor, in1, in2, in3, in4, in5, in1up, in2up, in3up, in4up, in5up, in5down, in4down, in3down, in2down, in1down)
variable digit1 : std_logic_vector (6 downto 0);
variable count : integer range 0 to (time_nx_state + timedoorclose + timedoorclosed);
variable bufferopendoor : std_logic;
variable position : integer range 0 to 4;
variable tempup : integer range 1 to 2 := 1;
variable tempdown : integer range -4 to 4;
begin
if (clk'event and clk='1') then
demand(0) <= demand(0) or in1 or in1up or in1down;
demand(1) <= demand(1) or in2 or in2up or in2down;
demand(2) <= demand(2) or in3 or in3up or in3down;
demand(3) <= demand(3) or in4 or in4up or in4down;
demand(4) <= demand(4) or in5 or in5up or in5down;
case pr_state is
when L1 => position := 0;
when L2 => position := 1;
when L3 => position := 2;
when L4 => position := 3;
when L5 => position := 4;
end case;
for i in 1 to 4 loop
if demand(i) ='1' then
tempup := i - position;
else null;
end if;
end loop;
for i in 3 downto 0 loop
bufferopendoor := '1';
closedoor <= '0';
count := 0;
end loop; --
elsif (updownpassenger = '1') then
if (count < timedoorclose) then
opendoor <= '1';
bufferopendoor := '1';
elsif count < (timedoorclose + timedoorclosed) then
opendoor <= '0';
bufferopendoor := '0';
else
closedoor <= '0';
end if;
--else null; ------
--end if; ------
-----------part main-----------------
count := count +1;
if insideopendoor = '1' then
opendoor<='1';
bufferopendoor :='1';
closedoor <= '0';
count := 0;
elsif (updownpassenger ='1') then
if (count < timedoorclose) then
opendoor <= '1';
bufferopendoor := '1';
closedoor <= '0';
elsif (count < (timedoorclose + timedoorclosed)) then
opendoor <= '0';
bufferopendoor := '0';
closedoor <= '1';
else
closedoor <= '0';
pr_state <= nx_state;
if signalstatus = '1' then
signalstatus <= '0';
else
signalstatus <= '1';
end if;
count := 0;
end if;
else null; --
end if;--
case nx_state is
when L1 =>
digit1 := "1111001";
if demand(0) = '1' then
demand(0) <= '0';
else null;
end if;
when L2 =>
digit1 := "0100100";
if demand(1) = '1' then
demand(1) <= '0';
else null;
end if;
when L3 =>
digit1 := "0110000";
if demand(3) = '1' then
demand(3) <= '0';
else null;
end if;
when L4 =>
digit1 := "0011001";
if demand(3) = '1' then
demand(3) <= '0';
else null;
end if;
when L5 =>
digit1 := "0010010";
if demand(4) = '1' then
demand(4) <= '0';
else null;
end if;
when others => null;
end case;
a1 <= digit1(0);
a2 <= digit1(1);
a3 <= digit1(2);
a4 <= digit1(3);
a5 <= digit1(4);
a6 <= digit1(5);
a7 <= digit1(6);
end if;
end process main;
step: process (pr_state, signalstatus)
begin
case pr_state is
--end if;
when L1 =>
if (demand(0)='1') then
nx_state <= pr_state;
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <=L2;
elsif direction_of_elevator = 2 then
nx_state <= pr_state;
else
nx_state <= pr_state;
end if;
end if;
when L2 =>
if (demand(1)= '1') then
nx_state <= pr_state;
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <= L3;
elsif direction_of_elevator = 2 then
nx_state <= L1;
else
nx_state <= pr_state;
end if;
end if;
when L3 =>
if (demand(2)= '1') then
nx_state <= pr_state;
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <= L4;
elsif direction_of_elevator = 2 then
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <= L5;
elsif direction_of_elevator = 2 then
end if;
end if;
end if;
when L5 =>
if (demand(4)='1') then
nx_state <= pr_state;
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <= L4;
elsif direction_of_elevator = 2 then
nx_state <= L1;
else
nx_state <= pr_state;
end if;
end if;
when others => null;
end case;
end process step;
end sequence;
Your code seems very mixed up. There is a specific reason why it won't synthesise: think carefully when the code immediately following this line here
elsif (updownpassenger = '1') then
will be executed. It will be executed following a positive edge or negative edge on any input in the sensitivity list, apart from clk where it will be executed only following a negative edge. How would you design logic with such behaviour? Well, your synthesiser can't do it, either.
Basically, you need to refactor your code. You need to split it into sequential and combinational processes. (Combinational logic is logic whose output depends only on it's input and thus is logic that contains no latches or flip-flops. Sequential logic is logic that contains latches or flip-flops, but will also usually contain some gates too. Do not use latches - they are not synchronous design.) Whilst there are many ways to code such processes, it is wise to be consistent by sticking to a template. Here are three templates, which if followed, will give you everything you need and will keep your VHDL coding life simple:
Here is the template for sequential logic with an asynchronous reset, which all synthesis tools should understand:
process(clock, async_reset) -- nothing else should go in the sensitivity list
begin
-- never put anything here
if async_reset ='1' then -- or '0' for an active low reset
-- set/reset the flip-flops here
-- ie drive the signals to their initial values
elsif rising_edge(clock) then -- or falling_edge(clock) or clk'event and clk='1' or clk'event and clk='0'
-- put the synchronous stuff here
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
Here is the template for sequential logic without an asynchronous reset:
process(clock) -- nothing else should go in the sensitivity list
begin
-- never put anything here
if rising_edge(clock) then -- or falling_edge(clock) or clk'event and clk='1' or clk'event and clk='0'
-- put the synchronous stuff here
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
And here is the corresponding template for a combinational process:
process(all inputs in the sensitivity list) -- an 'input' is a signal either on the LHS of an assignment or a signal that is tested
begin
-- combinational logic (with complete assignment and no feedback)
end process;

Signal parameter in a subprogram is not supported error

My code is about a ping pang game using VHDL and maxplus2. I can't get it complied.
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
-- use ieee.std_logic_arith.all;
entity center is
port (
clk: in std_logic;
ca: in std_logic;
cb: in std_logic;
enable: in std_logic;
a: in std_logic;
b: in std_logic;
ball: out std_logic_vector(16 downto 0);
sa: out std_ulogic;
sb: out std_ulogic;
over: inout std_ulogic
);
end center;
architecture behavior of center is
signal direction : integer range 0 to 2;
signal num : integer range -1 to 17;
begin
process (enable,ca,cb,a,b,clk)
begin
if enable = '0' then
over <= '0';
sa <= '0';
sb <= '0';
elsif enable = '1' and rising_edge(clk) then
if direction = 2 then
if ca = '1' then
direction <= 0;
num <= 1;
elsif cb = '1' then
direction <= 1;
num <= 16;
else
direction <= 2;
num <= 8;
end if;
elsif direction = 0 and num > 0 then
if b = '1' then
if num < 2 then
num <= num - 1;
direction <= 1;
else
direction <= 2;
sa <= '1' after 10 ns;
sb <= '0' after 10 ns;
over <= not over after 10 ns;
end if;
end if;
elsif direction = 1 and num <= 16 then
if a = '1' then
if num >= 14 then
num <= num + 1;
direction <= 2;
else
direction <= 2;
sa <= '0' after 10 ns;
sb <= '1' after 10 ns;
over <= not over after 10 ns;
end if;
end if;
elsif direction = 0 and num = -1 then
num <= 8;
direction <= 2;
sa <= '0' after 10 ns;
sb <= '1' after 10 ns;
over <= not over after 10 ns;
elsif direction = 0 and num = -1 then
num <= 8;
direction <= 2;
sa <= '0' after 10 ns;
sb <= '1' after 10 ns;
over <= not over after 10 ns;
end if;
end if;
end process;
end architecture behavior;
But I get a error:
signal parameter in a subprogram is not supported
I am confused, I don't know why I get this error.
I think as David also said you need to provide more information.
What it looks like for me is that your are writing a test bench the above code cannot be synthesized correctly. ISE will tell you that your syntax is ok but the delays are ignored IE the after keyword. The after keyword is only used in simulation.
That said i would also clean up the code there are a lot of redundancies. FX
The last two elsif statements. only one is needed. and the sensitivity list. only clk and enable should be there.
I've tried to clean up your code:
process (enable,clk)
begin
if enable = '0' then
over <= '0';
sa <= '0';
sb <= '0';
elsif rising_edge(clk) then
case( direction ) is
when 0 =>
if num > 0 then
if b = '1' then
if num < 2 then
num <= num - 1;
direction <= 1;
else
direction <= 2;
sa <= '1' after 10 ns;
sb <= '0' after 10 ns;
over <= not over after 10 ns;
end if;
end if;
elsif num = -1 then
num <= 8;
direction <= 2;
sa <= '0' after 10 ns;
sb <= '1' after 10 ns;
over <= not over after 10 ns;
end if;
when 1 =>
if num <= 16 then
if a = '1' then
if num >= 14 then
num <= num + 1;
direction <= 2;
else
direction <= 2;
sa <= '0' after 10 ns;
sb <= '1' after 10 ns;
over <= not over after 10 ns;
end if;
end if;
end if;
when 2 =>
if ca = '1' then
direction <= 0;
num <= 1;
elsif cb = '1' then
direction <= 1;
num <= 16;
else
direction <= 2;
num <= 8;
end if;
when others => NULL;
end case ;
end if;
end process;
Try and remove your after keywords and see if it will compile then.

Vhdl rising_edge statement not synthesizable

I am writing a little program for use on my Zybo FPGA, its supposedly a variable frequency divider with 10 different steps.
However on the last line when I try to output my clock to an LED for testing purposes it gives me this error: Line 137: statement is not synthesizable since it does not hold its value under NOT(clock-edge) condition
Here is my code
entity StappenMotor is
Port ( Reset, CLK : in STD_LOGIC;
X1, X2 : in STD_LOGIC;
Z1 : out STD_LOGIC);
end StappenMotor;
architecture Behavioral of StappenMotor is
signal speed : integer := 0;
signal puls : STD_LOGIC;
begin
speed_proc: process(X1, X2) is
begin
if (rising_edge(X1) and speed < 10) then
speed <= speed + 1;
elsif (rising_edge(X2) and speed > 0) then
speed <= speed - 1;
end if;
end process speed_proc;
freq_proc: process(CLK) is
variable int : integer := 0;
begin
if rising_edge(CLK) then
int := int + 1;
end if;
case speed is
when 0 =>
if int = 250000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 1 =>
if int = 200000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 2 =>
if int = 175000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 3 =>
if int = 150000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 4 =>
if int = 125000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 5 =>
if int = 100000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 6 =>
if int = 75000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 7 =>
if int = 62500000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 8 =>
if int = 50000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 9 =>
if int = 35000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 10 =>
if int = 25000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when others =>
if int = 10000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
end case;
end process freq_proc;
test: process(puls) is
begin
if rising_edge(puls) then
Z1 <= '1';
else Z1 <= '0';
end if;
end process test;
end Behavioral;
Error occurs on the line:
if rising_edge(puls) then
Anyone got a clue?
Kind regards.
All of your processes have some issues, though the compiler may not complain about them as loudly as the one in test.
In speed_proc, you are qualifying rising_edge() with an additional comparison. I would recommend nesting if statements instead (put the comparison if inside the rising_edge() if). You're also trying to clock the same register with 2 separate clocks. You probably need to find a different way to do this.
In freq_proc, only your variable increment is inside the rising_edge() check - I don't see a reason not to put the rest in as well. It's more standard, and it should generally lead to fewer unexpected problems.
In test, as #Chiggs mentioned, what you're trying to accomplish is invalid. If you want to toggle Z1 every clock cycle, you can do:
if rising_edge(puls) then
Z1 <= not Z1;
end if;
(For simulation, you'd need to initialize Z1 to see a valid output.)
The problem is the whole test process, not just the single line you've mentioned.
test: process(puls) is
begin
if rising_edge(puls) then
Z1 <= '1';
else Z1 <= '0';
end if;
end process test;
If you think about what you've described here, you're asking to drive Z1 high whenever there's a rising edge on the clock and drive it low whenever puls changes but isn't a rising edge (which includes Z->1, 1->0, Z->0 transitions).
This generally isn't possible in an FPGA and therefore is not synthesisable, hence the tool complaining.

Resources