BCD Timer in VHDL - timer

Just started out in VHDL not long ago,out of curiosity.
So I was trying to write BCD timer on spartan 3 board and
Somehow I couldn't find out why it keeps showing 'unexpected with' error.
So if I want to have such function as shown in the link of picture,
how can I modify the code?any help would be grateful.
(clickable)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity w3 is
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
stp : in STD_LOGIC;
an : out STD_LOGIC_VECTOR (3 downto 0);
c : out STD_LOGIC_VECTOR (6 downto 0));
end w3;
architecture timer of w3 is
signal div1 : integer range 0 to 499999 :=0; -- 100Hz
signal ck100hz : std_logic; -- 100Hz output
signal div2 : integer range 0 to 249999 :=0; -- 200Hz
signal ck200hz : std_logic; -- 200Hz output
signal div3 : integer range 0 to 124999 :=0; -- 400Hz
signal ck400hz : std_logic; -- 400Hz output
signal index : integer range 0 to 9 :=0;
signal scan : std_logic_vector (3 downto 0);
signal S : std_logic;
signal disp : std_logic_vector (3 downto 0);
begin
process begin
wait until rising_edge(clk);
if div1 < 499999 then
ck100hz <= '0';
div1 <= div1+1;
else
ck100hz <= '1';
div1 <= 0;
end if;
if div2 < 249999 then
ck200hz <= '0';
div2 <= div2+1;
else
ck200hz <= '1';
div2 <= 0;
end if;
if div3 < 124999 then
ck400hz <= '0';
div3 <= div3+1;
else
ck400hz <= '1';
div3 <= 0;
end if;
end process;
process begin
wait until rising_edge(clk);
if rst = '1' then
index <= 0;
end if;
if stp = '1' then
index <= index;
end if;
if ck100hz = '1' then
if index < 3 then index <= index+1;
else index <= 0;
if index < 4 and index > 7 then index <= index+1;
else index <= 0;
if index < 8 and index > 11 then index <= index+1;
else index <= 0;
if index < 12 and index > 15 then index <= index+1;
else index <= 0;
end if;
end if;
end if;
end if;
end if;
end process;
process begin
wait until rising_edge(clk);
if ck400hz = '1' then
With scan select -- error unexpected With
an <= an(0) when "00",
an(1) when "01",
an(2) when "10",
an(3) when others;
end if;
end process;
process begin
wait until rising_edge(clk);
if ck200hz = '1' then
With S select -- error unexpected With
disp <= index integer range 0 to 3 when "00",
index integer range 4 to 7 when "01",
index integer range 8 to 11 when "10",
index integer range 12 to 15 when others;
end if;
end process;
with index select
C <= "1000000" when 0,
"1111001" when 1,
"0100100" when 2,
"0110000" when 3,
"0011001" when 4,
"0010010" when 5,
"0000010" when 6,
"1111000" when 7,
"0000000" when 8,
"0011000" when 9;
end timer;

For low-active:
You should assign 0111111 to C in case of index = 0. You have to enable almost all segments. Now your internal calculation would be high-active. The display itself is low-active, because of the PCB layout, thus you should invert the whole C vector before assigning it to a Cathode_n port: Cathode_n <= not C; Note, I used _n to designate the low-active behavior of this port.
Old code:
with index select
C <= "1000000" when 0,
"1111001" when 1,
-- ...
"0011000" when 9;
This should be the goal when writing purely high-active code:
with index select
C <= "0111111" when 0,
"0000110" when 1,
-- ...
"1100111" when 9;
Cathode_n <= not C;
High-active means: If a bit is high (1) then a thing is active. In your case an LED of a 7-segment display is activated. Based on the PCB design, you have to drive low (0) to activate a light. This is low-active, because a low value activates something.
The select statement needs to assign the position to 1 that should be enlightened, not the positions to turn off. More over low-active signals should be marked in to code to denote there different behavior. Only a top-level component should translate high-active signals to low-active signals and vice versa. This ensures, the inner parts of your design are purely high-active.
For no driver:
There is no assignment to S and scan. Both signals are 'U' or "UUUU", respectively.
Edit:
Each signal assignment creates a driver on a signal. Currently, your code never assigns any value to S nor scan. Thus the initial values of S and scan become the driving value of the signals. You should run a simulation und see a lot of Us in your waveform.
Synthesis tools might report: Signal S is read, but never assigned.
For using elsif:
I reformatted you horrible if-then-else construct:
if ck100hz = '1' then
if index < 3 then
index <= index+1;
else
index <= 0;
if index < 4 and index > 7 then
index <= index+1;
else
index <= 0;
if index < 8 and index > 11 then
index <= index+1;
else
index <= 0;
if index < 12 and index > 15 then
index <= index+1;
else
index <= 0;
end if;
end if;
end if;
end if;
end if;
Now we see, you code can not use elsif, because you have assignments in the else branch before the next if statement. On the otherhand, the index <= 0; assignment is redundant and can be removed:
if ck100hz = '1' then
if index < 3 then
index <= index+1;
else
if index < 4 and index > 7 then
index <= index+1;
else
if index < 8 and index > 11 then
index <= index+1;
else
if index < 12 and index > 15 then
index <= index+1;
else
index <= 0;
end if;
end if;
end if;
end if;
end if;
Now we can transform it to use elsif branches:
if ck100hz = '1' then
if index < 3 then
index <= index + 1;
elsif index < 4 and index > 7 then
index <= index + 1;
elsif index < 8 and index > 11 then
index <= index + 1;
elsif index < 12 and index > 15 then
index <= index+1;
else
index <= 0;
end if;
end if;
Much more readable, right?
Next, lets check your expressions in that statement:
elsif index < 4 and index > 7 then
index cannot be less than 4 and greater than 7 at the same time. So lets play synthesis and optimized away unreachable branches:
if ck100hz = '1' then
if index < 3 then
index <= index + 1;
else
index <= 0;
end if;
end if;
Ok, other problems in the code:
if rst = '1' then
index <= 0;
end if;
if stp = '1' then
index <= index;
end if;
if ck100hz = '1' then
-- ...
end if;
Reset should always have highest priority. In your case, e.g. stp has higher priority. In a good case you're only wasting FPGA resources, in a bad case synthesis can not translate your code to primitives in the FPGA. E.g. flip-flops with matching reset behavior.
Correct implementation:
if rst = '1' then
index <= 0;
elsif stp = '1' then
index <= index;
elsif ck100hz = '1' then
-- ...
end if;
I think for now, you have enough input to fix your code.

Related

generalized aggregate in vhdl

I have an array / vector and I want to generate a new array by processing the first. A simple example of what I need is that every i-th element from the new array is the sum of the i-1, i, and i+1 elements from the first one.
I know this can be done very easily in a sequential manner by iterating through the array. I was wandering if there any kind of assigning expression that would generalize this and make this a parallel operation.(like in math: new[i] := old[i - 1] + old[i] + old[i + 1], where i ∈ (1, n) ).
As your question is about parallelism, I assume that you are interested in the hardware that will be synthesized from your VHDL description, not by the simulation.
Parallelism is a matter of when all these additions take place? If your design is synchronous - let's say of the rising edge of a clock named clk - then:
subtype word: unsigned(7 downto 0);
type word_array is array(natural range <>) of word;
signal a: word_array(0 to 15);
signal b: word_array(1 to 14);
...
process(clk)
begin
if rising_edge(clk) then
for i in 1 to 14 loop
b(i) <= a(i - 1) + a(i) + a(i + 1);
end loop;
end if;
end process;
will compute in parallel the 14 values in array b at each rising edge of the clock. And it will instantiate as many 8-bits adders as needed to do this. The question is not whether you are using a for loop or something else, it is really when do these operations take place? The answer is in the description: during the very same clock period.
You could overload the "+" operator to work on vectors:
function "+"(a, b: word_array) return word_array is
constant n: positive := a'length;
variable va: word_array(0 to n - 1) := a;
variable vb: word_array(0 to n - 1) := b;
variable sum: word_array(0 to n - 1);
begin
if n = 1 then
sum(0) := va(0) + vb(0);
else
sum := (va(0 to n / 2 - 1) + vb(0 to n / 2 - 1)) &
(va(n / 2 to n - 1) + vb(n / 2 to n - 1));
end if;
return sum;
end function "+";
and use it to apparently write a more parallel description:
process(clk)
begin
if rising_edge(clk) then
b <= a(0 to 13) + a(1 to 14) + a(2 to 15);
end if;
end process;
but it would make no difference and the resulting hardware would be the same.
You could also use a generate statement to do the same:
g: for i in 1 to 14 generate
process(clk)
begin
if rising_edge(clk) then
b(i) <= a(i - 1) + a(i) + a(i + 1);
end if;
end process;
end generate g;
but, again, it would make no difference for the synthesizer.

VHDL weird bit errors seemingly makes no sense

I have a Micro-Nova FPGA dev board with a Xilinx Spartan-3A. I am trying to make it communicate bits over GPIO on a raspberry pi using 3 pins: REQ, ACK, DATA. The code works fine if I uncomment the bit_data assignments and comment out "bit_data := data_out(data_ofs);" and on the Pi i get a continous 10101010... etc. But if I leave the code as pasted below I get the wrong bits at random times eg. 1010110100... etc.
Any idea what could be the problem?:
VHDL on FPGA:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity xclock is
Port(CLK : in STD_LOGIC;
REQ : in STD_LOGIC;
ACK : out STD_LOGIC;
DATA : out STD_LOGIC);
end xclock;
architecture Behavioral of xclock is
begin
process(CLK)
variable data_ofs : integer range 0 to 2 := 0;
variable data_out : std_logic_vector(1 downto 0) := "01";
variable bit_data : std_logic := '0';
variable ack_data : std_logic := '0';
variable LASTREQ : std_logic := '0';
variable seconds : integer range 0 to 50000000 := 0;
variable tick : integer range 0 to 50000000 := 0;
begin
if CLK'event and CLK = '1' then
tick := tick + 1;
if tick = 49999999 then
tick := 0;
seconds := seconds + 1;
if seconds = 49999999 then
seconds := 0;
end if;
end if;
if seconds > 1 then
if REQ /= LASTREQ and REQ /= ack_data then
LASTREQ := REQ;
if REQ = '1' then
--bit_data := '1';
ack_data := '1';
else
--bit_data := '0';
ack_data := '0';
end if;
bit_data := data_out(data_ofs);
data_ofs := data_ofs + 1;
if data_ofs = 2 then
data_ofs := 0;
end if;
end if;
end if;
DATA <= bit_data;
ACK <= ack_data;
end if;
end process;
end Behavioral;
Bash script on Pi:
REQ=27
ACK=17
DATA=22
gpio -g mode $REQ out
gpio -g mode $ACK in
gpio -g mode $DATA in
gpio -g write $REQ 1
e=1
while [ 1 ]; do
while [ 1 ]; do
if [ `gpio -g read $ACK` -eq 1 ]; then
while [ 1 ]; do
d=`gpio -g read $DATA`
echo $d
if [ $d -ne $e ]; then
echo error DATA should be $e
sleep 1
else
if [ $e -eq 0 ]; then
e=1
else
e=0
fi
break
fi
done
gpio -g write $REQ 0
break;
fi
done
while [ 1 ]; do
if [ `gpio -g read $REQ` -eq 0 ]; then
while [ 1 ]; do
d=`gpio -g read $DATA`
echo $d
if [ $d -ne $e ]; then
echo error DATA should be $e
sleep 1
else
if [ $e -eq 0 ]; then
e=1
else
e=0
fi
break
fi
done
gpio -g write $REQ 1
break;
fi
sleep 1
done
done
Any help will be greatly appreciated. Pulling my hair out on this one!
I spent some time trying to figure out how your code is supposed to work (what the protocol is), but I gave up. Building off what other have suggested, you might try to make the following modifications and see if it makes any difference.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity xclock is
port(CLK : in STD_LOGIC;
REQ : in STD_LOGIC;
ACK : out STD_LOGIC;
DATA : out STD_LOGIC);
end xclock;
architecture Behavioral of xclock is
signal req_reg1, req_reg2, req_int, last_req : std_logic := '0';
signal bit_data_reg, ack_reg : std_logic;
begin
process(CLK)
variable data_ofs : integer range 0 to 2 := 0;
variable data_out : std_logic_vector(1 downto 0) := "01";
variable bit_data : std_logic := '0';
variable ack_data : std_logic := '0';
variable seconds : integer range 0 to 50000000 := 0;
variable tick : integer range 0 to 50000000 := 0;
begin
if CLK'event and CLK = '1' then
-- Input registers help prevent metastability on REQ line
-- Note that if there is significant bounce or glitching, then
-- you will also need a deglitcher.
req_reg1 <= REQ;
req_reg2 <= req_reg1;
req_int <= req_reg2;
tick := tick + 1;
if tick = 49999999 then
tick := 0;
seconds := seconds + 1;
if seconds = 49999999 then
seconds := 0;
end if;
end if;
if seconds > 1 then
-- Using the registered inputs instead of the direct REQ input.
if req_int /= last_req and req_int /= ack_data then
last_req <= req_int;
if req_int = '1' then
ack_data := '1';
else
ack_data := '0';
end if;
bit_data := data_out(data_ofs);
data_ofs := data_ofs + 1;
if data_ofs = 2 then
data_ofs := 0;
end if;
end if;
end if;
-- Register outputs to ensure consistent OREG packing, if enabled
bit_data_reg <= bit_data;
ack_reg <= ack_data;
DATA <= bit_data_reg;
ACK <= ack_reg;
end if;
end process;
end Behavioral;
The modifications to the code do two things:
Register the input REQ a couple times to reduce the probability of metastability, and then only use the registered values instead of the pin itself. (Read more)
Register the outputs (twice) to ensure that the output register can be placed in an OREG (in IOB), which ensures consistent clock-to-out timing at the output pad. At the boundaries of your device, when possible, it is nice to place a plain FF register stage which guarantees that packing into OREG is possible. Otherwise there may be a feedback path from last register stage back into your design which prevents packing.

Swap elements in an array - VHDL

I have a piece of code in VHDL:
I want to swap the signalIn(0) and signalIn(1) values.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity SwapFP is
port(clockIn:in std_logic);
end SwapFP;
architecture Behavioral of SwapFP is
signal tempOne,tempTwo,a1,a2 : STD_LOGIC_VECTOR(31 DOWNTO 0);
signal state : integer range 0 to 7 := 0;
begin
process(clockIn) is
type floatingPointArray is array(1 downto 0) of std_logic_vector(31 downto 0);
variable signalIn : floatingPointArray;
begin
signalIn(0) := X"3D52CEF8";
signalIn(1) := X"3FBC9F1A";
if rising_edge(clockIn) then
case state is
when 0 =>
tempOne <= signalIn(0);
tempTwo <= signalIn(1);
state <= 1;
when 1 =>
signalIn(1) := tempOne;
signalIn(0) := tempTwo;
state <= 2;
when 2 =>
a1 <= signalIn(0);
a2 <= signalIn(1);
state <= 3;
when others =>
end case;
end if;
end process;
end Behavioral;
In a1 and a2 signals, I am getting the original values X"3D52CEF8" and X"3FBC9F1A" respectively. Means that swapping is not happening. Why is it so?
Your variable assignments to signalIn at the top of the process happen every time the process runs. When state is 2, the values you assigned to signalIn when state equaled 1 are overwritten by this initial assignment.
You can much more easily swap two items like this:
process (clk)
begin
if (rising_edge(clk)) then
signalIn(0) <= signalIn(1);
signalIn(1) <= signalIn(0);
end if;
end process;
This works because the signal assignments using <= do not take place immediately, rather they are scheduled to take place after the process has run.

How to use for loop statement in case statement in Verilog

I'm trying to compile a code similar to this:
`define CORES_NUM 4
reg [1:0] core = 'h0;
reg [`CORES_NUM-1:0] result = 'h0;
integer i;
always # (posedge clk) begin
case (core)
for (i = 0; i < `CORES_NUM; i = i + 1) begin
i: begin
result[i] <= 1;
end
end
endcase
end
Only one core is active at the moment. I expect that my code is equal to that:
case (core)
0: begin
result[0] <= 1;
end
1: begin
result[1] <= 1;
end
2: begin
result[2] <= 1;
end
3: begin
result[3] <= 1;
end
endcase
In other words, I need 'for loop' only for auto setting - if I change CORES_NUM, case states are automatically changed.
But my code builds with errors. How can I use for loop in case statement?
Why not:
always #(posedge clk) if (core < `CORES_NUM) result[core] = 1;

Sum of Array elements VHDL

I am new to VHDL and I searched all of the internet and i didnt find anything that would help me !
I am trying to add the elements of an array (32 Elements !), so i cant just write
for example s <= s(0) + s(1) + s(3) ... s(5) + ....s(32)
how can i generalise such a calculation ??
or what am i doing wrong ?
My Code (that didnt work in the simulation) is ..
(just for 5 elemets ....)
library IEEE;
library work;
library std;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use ieee.std_logic_arith.all;
entity main is Port (
EIN : in std_logic;
AUS_1 : out std_logic_vector(3 downto 0));
end main;
architecture Behaviour of main is
type Cosinus is array (0 to 4) of std_logic_vector(3 downto 0);
type Sinus is array (0 to 4) of std_logic_vector(3 downto 0);
Signal SumSin :std_logic_vector(3 downto 0);
begin
main : process(Ein)
variable Cos : Cosinus;
variable Sin : Sinus;
begin
if( Ein='1' ) then
sin(0) := "0011";
sin(1) := "0001";
sin(2) := "1010";
sin(3) := "1111";
sin(4) := "1110";
for n in 0 to 4 loop
SumSin <= SumSin + Sin(n);
end loop;
else
sin(0) := "1011";
sin(1) := "0101";
sin(2) := "1000";
sin(3) := "1001";
sin(4) := "1100";
for n in 0 to 4 loop
SumSin <= SumSin + Sin(n);
end loop;
end if;
end process;
Aus_1 <= SumSin;
end Behaviour;
I would be thanksfull
First... Don't use std_logic_arith.
Then, Use a variable for the running sum and assign is to a signal afterwards:
...
main : process(Ein)
variable Cos : Cosinus;
variable Sin : Sinus;
variable SumSin : signed(3 downto 0);
begin
sumsin := (others => '0');
....
for n in Sin'range loop
SumSin := SumSin + Sin(n);
end loop;
end if;
Aus_1 <= SumSin;
end process;

Resources