I have used this program for 2 hours ( learning at school with a bad teacher ) and I have no idea what I am doing. I just know that somehow and 3 is working but not and 2. Also I would like to know how can I mix the 3 entitys? (inverse, and2, and3) all together.
I don't know why I have to add more detail as I don't know how this program work and I don't know what I am doing, the only thing I could understand is to set some entity that is like setting a variable but when I have to execute the idea Im completely lost
-- inversor
ENTITY bdp_portes IS
END bdp_portes;
ARCHITECTURE vectors OF bdp_portes IS
COMPONENT inversor
port(
a: IN BIT;
z: OUT BIT);
END COMPONENT;
SIGNAL a,z : BIT;
FOR DUT: inversor USE ENTITY WORK.inversor(logica);
BEGIN
DUT: inversor PORT MAP (a,z);
PROCESS
BEGIN
a <= '0';
wait for 100 ns;
a <= '1';
wait for 500 ns;
a <= '0';
wait for 1000 ns;
a <= '1';
END PROCESS;
END vectors;
--AND 2
ENTITY bdp_portes IS
END bdp_portes;
ARCHITECTURE test OF bdp_portes IS
COMPONENT and2
PORT (a, b: IN BIT; z:OUT BIT);
END COMPONENT;
SIGNAL ent1, ent2, sortida: BIT;
FOR DUT1: and2 USE ENTITY WORK.and2(logica2);
BEGIN
DUT1: and2 PORT MAP (ent1,ent2,sortida);
PROCESS (ent1,ent2)
BEGIN
ent1 <= NOT ent1 AFTER 50 ns;
ent2 <= NOT ent2 AFTER 100 ns;
sortida <= ent1 and ent2;
END PROCESS;
END test;
-- AND 3
ENTITY bdp_portes IS
END bdp_portes;
ARCHITECTURE test OF bdp_portes IS
COMPONENT and3
PORT (a, b, c: IN BIT; z:OUT BIT);
END COMPONENT;
SIGNAL ent1, ent2, ent3, sortida: BIT;
FOR DUT1: and3 USE ENTITY WORK.and3(logica3);
BEGIN
DUT1: and3 PORT MAP (ent1,ent2,sortida);
PROCESS (ent1,ent2,ent3)
BEGIN
ent1 <= NOT ent1 AFTER 50 ns;
ent2 <= NOT ent2 AFTER 100 ns;
ent3 <= NOT ent3 AFTER 150 ns;
sortida <= ent1 and ent2 and ent3;
END PROCESS;
END test;
Related
This is my first VHDL code, I have this multiplexer (two inputs, one selection bit) which has 8bit-vector inputs. How can I write a testing function that generates all possible vectors?
library IEEE;
use IEEE.std_logic_1164.all;
entity mux is
port(
in0, in1: in std_logic_vector(7 downto 0);
sel: in std_logic;
out0: out std_logic_vector(7 downto 0);
end mux;
architecture dataflow of mux is
begin
out0<=in1 when sel='1'
else in0;
end dataflow;
This is the testbench at the moment:
library IEEE;
use IEEE.std_logic_1164.all;
entity testbench is --empty
end testbench;
architecture tb of testbench is
-- DuT component
component mux is
port(
in0, in1: in std_logic_vector(7 downto 0);
sel: in std_logic;
out0: out std_logic);
end component;
signal tb_sel: std_logic;
signal tb_in0, tb_in1, tb_out0: std_logic_vector(7 downto 0);
begin
-- Connect DuT
DuT: mux port map(tb_in0, tb_in1, tb_sel, tb_out0);
process
begin
tb_sel <= 0;
tb_in0 <= "00000000";
tb_in1 <= "00000000";
-- TODO: test all possibilities
end process;
end tb;
Something like this can be used:
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
entity testbench is --empty
end testbench;
architecture tb of testbench is
signal tb_sel: std_logic;
signal tb_in0, tb_in1, tb_out0: std_logic_vector(7 downto 0);
begin
-- Connect DuT
DuT: entity work.mux port map(tb_in0, tb_in1, tb_sel, tb_out0);
process
begin
-- Done: Test all possibilities
for sel in 0 to 1 loop
for in0 in 0 to 2 ** tb_in0'length - 1 loop
for in1 in 0 to 2 ** tb_in1'length - 1 loop
-- Make stimuli
if sel = 0 then
tb_sel <= '0';
else
tb_sel <= '1';
end if;
tb_in0 <= std_logic_vector(to_unsigned(in0, tb_in0'length));
tb_in1 <= std_logic_vector(to_unsigned(in1, tb_in1'length));
-- Wait for output, also to ease viewing in waveforms
wait for 10 ns;
-- Test output
if sel = 0 then
assert tb_out0 = tb_in0 report "Wrong out0 output value for selected in0 input" severity error;
else
assert tb_out0 = tb_in1 report "Wrong out0 output value for selected in1 input" severity error;
end if;
end loop;
end loop;
end loop;
report "OK (not actual failure)" severity FAILURE;
wait;
end process;
end tb;
Note that I have used instantiation by entity for mux, to avoid the component declaration, where there actually was an error in the port list; clearly showing why it is a bad idea to write the same twice ;-)
Also not that I have included the IEEE numeric_std package.
It can surely be improved with respect to testing of X values also, but for a simple module like a mux the testing above will give the required coverage.
For more advanced testing, take a look at OSVVM.
So i have this receiver code for the RS232 communication link, I'm supposed to send 8 bits with 1 start bit "0" and one stop bit "1", no parity check bit, I have tried with those code in most kinds of ways but the simulation never worked correctly, even though some people told me my problem is the testbench not the code but it never works on the FPGA implementation, the first signal i sent is always wrong where as any signal after that is correct.
here is the code below
entity Rs232Rxd is
port( Reset, Clock16x, Rxd: in std_logic;
DataOut1: out std_logic_vector (7 downto 0));
end Rs232Rxd;
architecture Rs232Rxd_Arch of Rs232Rxd is
attribute enum_encoding: string;
-- state definitions
type stateType is (stIdle, stData, stStop, stRxdCompleted);
attribute enum_encoding of statetype: type is "00 01 11 10";
signal iReset : std_logic;
signal iRxd1, iRxd2 : std_logic := '1';
signal presState: stateType;
signal nextState: stateType;
signal iClock1xEnable, iClock1x, iEnableDataOut: std_logic :='0' ;
signal iClockDiv: std_logic_vector (3 downto 0) := (others=>'0') ;
signal iDataOut1, iShiftRegister: std_logic_vector (7 downto 0):= (others=>'0');
signal iNoBitsReceived: std_logic_vector (3 downto 0):= (others=>'0') ;
begin
process (Clock16x) begin
if rising_edge(Clock16x) then
if Reset = '1' or iReset = '1' then
iRxd1 <= '1';
iRxd2 <= '1';
iClock1xEnable <= '0';
iClockDiv <= (others=>'0');
else
iRxd1 <= Rxd;
iRxd2 <= iRxd1;
end if;
if iRxd1 = '0' and iRxd2 = '1' then
iClock1xEnable <= '1';
end if;
if iClock1xEnable = '1' then
iClockDiv <= iClockDiv + '1';
end if;
end if;
end process;
iClock1x <= iClockDiv(3);
process (iClock1xEnable, iClock1x)
begin
if iClock1xEnable = '0' then
iNoBitsReceived <= (others=>'0');
presState <= stIdle;
elsif rising_edge(iClock1x) then
iNoBitsReceived <= iNoBitsReceived + '1';
presState <= nextState;
if iEnableDataOut = '1' then
iDataOut1 <= iShiftRegister;
--iShiftRegister <= (others=>'0');
else
iShiftRegister <= Rxd & iShiftRegister(7 downto 1);
end if;
end if;
end process;
DataOut1 <= iDataOut1;
process (presState, iClock1xEnable, iNoBitsReceived)
begin
-- signal defaults
iReset <= '0';
iEnableDataOut <= '0';
case presState is
when stIdle =>
if iClock1xEnable = '1' then
nextState <= stData;
else
nextState <= stIdle;
end if;
when stData =>
if iNoBitsReceived = "1000" then
iEnableDataOut <= '1';
nextState <= stStop;
else
iEnableDataOut <= '0';
nextState <= stData;
end if;
when stStop =>
nextState <= stRxdCompleted;
when stRxdCompleted =>
iReset <= '1';
nextState <= stIdle;
end case;
end process;
end Rs232Rxd_Arch;
Your question doesn't present a Minimal Complete and Verifiable Example. The problem cannot be duplicated without writing a testbench and your problem lacks specificity ('signal' and 'wrong' used here are imprecise).
There are some observations.
A stop bit followed by a start bit of a successive character leaves no room for state stRxdCompleted. Also iNoBitsReceived is not set to all '0's when iClock1xEnable goes invalid, meaning the sampling point is not determined by the falling edge of the start bit for successive characters:
This is a capital 'A' immediately followed by a lower case 'a', the stop bit immediately followed by the start bit of the second character (which is legal).
In the first character you see that the start bit is counted as one of the character bits.
You also see that the bit counter isn't reset when the enable goes invalid, which will cause sampling point drift (and may eventually cause sampling errors depending on clock differences or transmission distortion and lack of isosynchronous sampling point reset).
You also see presState is stStop during the last data bit of the first character and yet the second character is correct. Looking a bit closer we see the start bit of the first character occurs during stData and that doesn't occur for the second character.
There's a basic issue with number of states and state transitions when iClock1x is stopped.
You don't need the state machine, you have the counter named iNoBitsReceived that can store all the state should ishiftregister be long enough to accommodate start (and possibly stop) bits should you also detect framing errors.
Tying operations to specific counts without a separate state machine, along with clearing the bit counter when idle:
Gives us something that works with a bit less complexity:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Rs232Rxd is
port (
Reset,
Clock16x,
Rxd: in std_logic;
DataOut1: out std_logic_vector (7 downto 0)
);
end entity Rs232Rxd;
architecture foo of Rs232Rxd is
signal rxd1: std_logic;
signal rxd2: std_logic;
signal baudctr: unsigned (3 downto 0);
signal ctr16x: unsigned (3 downto 0);
signal enab1xstart: std_logic;
signal enable1x: std_logic;
signal ninthbit: std_logic;
signal sampleenab: std_logic;
signal shiftregister: std_logic_vector(7 downto 0);
begin
CLOCK_DOMAIN:
process (clock16x)
begin
if rising_edge(clock16x) then
rxd1 <= rxd;
rxd2 <= rxd1;
end if;
end process;
enab1xstart <= not rxd1 and rxd2 and not enable1x;
ENABLE_1X:
process (clock16x, reset)
begin
if reset = '1' then
enable1x <= '0';
elsif rising_edge(clock16x) then
if enab1xstart = '1' then
enable1x <= '1';
elsif ninthbit = '1' then
enable1x <= '0';
end if;
end if;
end process;
SAMPLE_COUNTER:
process (clock16x, reset, ninthbit)
begin
if reset = '1' or ninthbit = '1' then
ctr16x <= (others => '0'); -- for simulation
elsif rising_edge(clock16x) then
if enab1xstart = '1' or enable1x = '1' then
ctr16x <= ctr16x + 1;
end if;
end if;
end process;
sampleenab <= not ctr16x(3) and ctr16x(2) and ctr16x(1) and ctr16x(0);
BAUD_COUNTER:
process (clock16x, reset)
begin
if reset = '1' then
baudctr <= (others => '0');
elsif rising_edge(clock16x) and sampleenab = '1' then
if baudctr = 8 then
baudctr <= (others => '0');
else
baudctr <= baudctr + 1;
end if;
end if;
end process;
NINTH_BIT: -- one clock16x period long, after baudctr changes
process (clock16x, reset)
begin
if reset = '1' then
ninthbit <= '0';
elsif rising_edge(clock16x) then
ninthbit <= sampleenab and baudctr(3) and not baudctr(2) and
not baudctr(1) and not baudctr(0);
end if;
end process;
SHIFT_REG:
process (clock16x, reset)
begin
if reset = '1' then
shiftregister <= (others => '0'); -- for pretty waveforms
elsif rising_edge(clock16x) and sampleenab = '1' then
shiftregister <= rxd2 & shiftregister(7 downto 1);
end if;
end process;
OUTREG:
process (clock16x, reset)
begin
if reset = '1' then
dataout1 <= (others => '0');
elsif rising_edge(clock16x) and ninthbit = '1' then
dataout1 <= shiftregister;
end if;
end process;
end architecture;
VHDL basic identifiers are case insensitive, and the names weren't particularly enlightening. The format of the two above waveforms indicates name changes handily.
If you extend the shift register length by one or two you can detect framing errors during the stop bit. Changing the shift register length would require slicing the shift register output for writing to your data output.
Note this architecture is written to use package numeric_std and not Synopsys package std_logic_arith. You also didn't provide the context clause preceding the entity declaration.
This architecture also produces enables and uses the 16x clock instead of producing a 1x clock.
It was written after finding the amount of changes to correct issues in the original architecture seemed overwhelming. (When in doubt, start over.)
This testbench was used:
library ieee;
use ieee.std_logic_1164.all;
entity rs232rxd_tb is
end entity;
architecture foo of rs232rxd_tb is
signal reset: std_logic := '0';
signal clock16x: std_logic := '0';
signal rxd: std_logic := '1';
signal dataout1: std_logic_vector (7 downto 0);
begin
DUT:
entity work.rs232rxd
port map (
reset => reset,
clock16x => clock16x,
rxd => rxd,
dataout1 => dataout1
);
CLOCK:
process
begin
wait for 3.255 us; -- 16X clock divided by 2, 9600 baud 104.16 us
clock16x <= not clock16x;
if now > 2.30 ms then
wait;
end if;
end process;
STIMULI:
process
begin
wait for 6.51 us;
reset <= '1';
wait for 13.02 us;
reset <= '0';
wait for 13.02 us;
wait for 40 us;
rxd <= '0';
wait for 104.16 us; -- start bit
rxd <= '1';
wait for 104.16 us; -- first data bit, bit 0 = '1'
rxd <= '0';
wait for 104.16 us; -- second data bit, bit 1 = '0'
rxd <= '0';
wait for 104.16 us; -- third data bit, bit 2 = '0';
wait for 104.16 us; -- fourth data bit, bit 3 = '0';
wait for 104.16 us; -- fifth data bit, bit 4 = '0';
wait for 104.16 us; -- sixth data bit, bit 5 = '0';
rxd <= '1';
wait for 104.16 us; -- seventh data bit, bit 6 = '1';
rxd <= '0';
wait for 104.16 us; -- eigth data bit, bit 7 = '0';
rxd <= '1';
wait for 104.16 us; -- stop bit ( = '1')
--wait for 104.16 us; -- idle
rxd <= '0';
wait for 104.16 us; -- start bit
rxd <= '1';
wait for 104.16 us; -- first data bit, bit 0 = '1'
rxd <= '0';
wait for 104.16 us; -- second data bit, bit 1 = '0'
rxd <= '0';
wait for 104.16 us; -- third data bit, bit 2 = '0';
wait for 104.16 us; -- fourth data bit, bit 3 = '0';
wait for 104.16 us; -- fifth data bit, bit 4 = '0';
rxd <= '1';
wait for 104.16 us; -- sixth data bit, bit 5 = '1';
wait for 104.16 us; -- seventh data bit, bit 6 = '1';
rxd <= '0';
wait for 104.16 us; -- eigth data bit, bit 7 = '0';
rxd <= '1';
wait for 104.16 us; -- stop bit ( = '1')
wait;
end process;
end architecture;
You can see that new architecture has all the same essential elements, although clocked process elements are in separate process statements.
There is no state machine process.
The architecture is extensible to a full feature UART receiver by playing around with separating inputs to the shift register (for parity, two stop bits, 7 data bits, etc.). Parity can be performed serially.
Here is a design for 4-bit asynchronous ripple counter (using T flip flop however I didn't define a component for Tff and just coded the behavior of circuit regarding T signals).
Following are the questions:
1.) inout ports, I first defined Q as inout (since it's obviously my output and the bits are also used as clk inputs to their following flip flops). Still, when I wanted to simulate my code, the Q output was UUUU which makes sense cause I had to initialize it with the number I wanted my count to begin with. Though I didn't know how to set an inout initial value (I tried Process ... Q <= "0000"; wait; end process but it didn't work)!
2.) In order to solve the above-mentioned problem I changed my inout port to out (Q_out) and defined Q as a signal, this worked BUT...my counter only changed the Q(0) bit and not the others...thus it counts like: 0,1,0,1,0,1,...
3.) I want to debug this code. I tried another style, instead of a 4-bit output I defined 4 1-bit output signals (Q_out1 to Q_out2) in addition to 4 internal signals Q0 to Q1 and this perfectly works
I just want to know why the first style (Q as a 4_bit vector) didn't work out.
thanks in advance for your help.
Here is my code and its test bench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity four_bit_Asynch_Counter is
Port ( T0,T1,T2,T3 : in STD_LOGIC;
clk : in STD_LOGIC;
Q_out: out STD_LOGIC_VECTOR (3 downto 0));
end four_bit_Asynch_Counter;
architecture Behavioral of four_bit_Asynch_Counter is
signal Q : STD_LOGIC_VECTOR (3 downto 0) := "0000";
begin
Process (clk,Q(0),Q(1),Q(2))
begin
if (falling_edge(clk)) then
if (T0 = '1') then
Q(0) <= not Q(0);
else
Q(0) <= Q(0);
end if;
end if;
if (falling_edge(Q(0))) then
if (T1 = '1') then
Q(1) <= not Q(1);
else
Q(1) <= Q(1);
end if;
end if;
if (falling_edge(Q(1))) then
if (T2 = '1') then
Q(2) <= not Q(2);
else
Q(2) <= Q(2);
end if;
end if;
if (falling_edge(Q(2))) then
if (T3 = '1') then
Q(3) <= not Q(3);
else
Q(3) <= Q(3);
end if;
end if;
Q_out <= Q;
end Process;
end Behavioral;
--------------- Test Bench------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY tb_counter IS
END tb_counter;
ARCHITECTURE behavior OF tb_counter IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT four_bit_Asynch_Counter
PORT(
T0 : IN std_logic;
T1 : IN std_logic;
T2 : IN std_logic;
T3 : IN std_logic;
clk : IN std_logic;
Q_out : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
--Inputs
signal T0 : std_logic := '1';
signal T1 : std_logic := '1';
signal T2 : std_logic := '1';
signal T3 : std_logic := '1';
signal clk : std_logic := '0';
--Outputs
signal Q_out : std_logic_vector(3 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: four_bit_Asynch_Counter PORT MAP (
T0 => T0,
T1 => T1,
T2 => T2,
T3 => T3,
clk => clk,
Q_out => Q_out
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
wait for clk_period*10;
-- insert stimulus here
wait;
end process;
END;
The TL;DR answer is that q(3) doesn't show up in your process sensitivity list.
architecture behavioral of four_bit_asynch_counter is
signal q: std_logic_vector (3 downto 0) := "0000";
begin
process (clk, q(0), q(1), q(2))
begin
if falling_edge(clk) then
if t0 = '1' then
q(0) <= not q(0);
-- else
-- q(0) <= q(0);
end if;
end if;
if falling_edge(q(0)) then
if t1 = '1' then
q(1) <= not q(1);
-- else
-- q(1) <= q(1);
end if;
end if;
if falling_edge(q(1)) then
if t2 = '1' then
q(2) <= not q(2);
-- else
-- q(2) <= q(2);
end if;
end if;
if falling_edge(q(2)) then
if t3 = '1' then
q(3) <= not q(3);
-- else
-- q(3) <= q(3);
end if;
end if;
q_out <= q;
end process;
end architecture behavioral;
For your process sensitivity list you've discovered a feature in how the sensitivity list is constructed from the expression consisting of primaries - clk, q(0), q(1), q(2).
From IEEE Std 1076 -1993, 8.1 Wait statement:
...
The sensitivity set is initially empty. For each primary in the condition of the condition clause, if the primary is
-- A simple name that denotes a signal, add the longest static prefix of the name to the sensitivity set
-- A selected name whose prefix denotes a signal, add the longest static prefix of the name to the sensitivity set
-- An expanded name whose prefix denotes a signal, add the longest static prefix of the name to the sensitivity set
-- An indexed name whose prefix denotes a signal, add the longest static prefix of the name to the sensitivity set and apply this rule to all expressions in the indexed name
...
...
This rule is also used to construct the sensitivity sets of the wait statements in the equivalent process statements for concurrent procedure call statements( 9.3 ), concurrent assertion statements ( 9.4 ), and concurrent signal assignment statements ( 9.5 ).
If a signal name that denotes a signal of a composite type appears in a sensitivity list, the effect is as if the name of each scalar subelement of that signal appears in the list.
...
I only included elements of the rule that are of interest here, the first covers the clock the last element shown covers the std_logic_vector elements specified by selected names.
It helps to understand what is meant by the longest static prefix. This explained in -1993 6.1 Names.
The primaries (indexed names) are static names (q(0), q(1), q(2)), every expression that's part of each indexed name is static.
This means the longest static prefix is the indexed name comprising each primary.
And this leaves q(3) dangling in the breeze for the process signal assignment statement:
q_out <= q;
Without sensitivity to q(3) the value of q_out is not updated until the next event in the sensitivity list, which happens to be on clk:
There are two ways to cure this, you could move the q_out assignment outside the process statement, where it becomes a concurrent signal assignment (with an elaborated equivalent process with a sensitivity list set to q), or you can change the sensitivity list in the present process:
process (clk, q)
So that q_out is updated for an event on q(3) (noting the last quoted paragraph in 8.1 above).
This behavior hold true for later revisions of the standard as well.
With the process sensitivity list is fixed:
Your counter behaves properly.
Also note I commented out the redundant else assignments to the q(0), q(1), q(2) and q(3) a signal will hold it's value until assigned and these are sequential (clocked) statements. Also eliminated the redundant parentheses pairs.
When implementing counters in realisable hardware (either ASIC or FPGA) you should never use a ripple counter. By using the flip-flop output as a clock to the next you will have sub-optimal timing, the tools will not be able to accurately validate the setup and hold times and you are not able to take advantage of dedicated clock routing. In general asynchronous design is a bad idea for real implementations.
A true synchronous design will be much better for synthesis and is much easier to infer in the VHDL code.
Examples of Counter implementations
See the above link for both verilog and vhdl examples of counter implementation.
I'm a VHDL newbie and I'm struggling with the following idea. I think I still misunderstand the idea of counters and timers in VHDL. I will explain it with a simple blinking LED diode. (BTW I'm learning on Spartan-3E FPGA kit.) So here is my code (I'm not using reset yet)
entity top_level is
Port( clk : in STD_LOGIC;
led1 : out STD_LOGIC);
end top_level;
architecture Behavioral of top_level is
signal timer : STD_LOGIC_VECTOR(25 downto 0) := "00000000000000000000000000";
signal reset: boolean:= false;
begin
process (clk)
begin
led1 <= '1';
if clk='1' and clk'event then
if reset <= true then
timer <= (others => '0');
end if;
timer <= timer + 1;
end if;
if timer <= "11100100111000011100000000" then
led1 <= '0';
end if;
end process;
end Behavioral;
The oscillator frequency is 50 MHz so one period is 20 ns. If I want to blink with a LED for 1.2 second (which makes 60 000 000 cycles) I need to create a 26 bit vector. So I created a process which is triggered by clk change.
WHAT I THINK IT SHOULD DO:
the first line of code is a logic 1 assignment to led1. So the led1 should light until the counter won't count 60 000 000 cycles. When counter counts 60 000 000 cycles, the led logic state should switch to 0 which means no light. As the maximum value of 26 bit number is 67 108 863, the LED should light for 60 000 000 cycles and be turned off for the remaining 7 108 863 cycles. Isn't that right ?
WHAT IT DOES:My impression is, that it's kinda reversed. The LED is off for the most of the time (67 108 063 cycles) and lights for 7 108 863 cycles. Why is this happening ? I don't really get it.
Additional question: How can I achieve to run this process only once/twice/...? E.g. I want to blink with my LED 3 times and then turn it off. Because as far as I know after reaching maximum 26 bit number, the time vector will start counting from the beginning (from 0). And so on, endlessly.
First of all, you should divide your design in several parts, which can be entities or several processes. I'll use processes or some one-liner. You can also extract the presented functions into a separate package.
part 1: generate a 0.833 Hz signal from 50 MHz system clock
part 2: control whether the led is on or off
part 3: count the on cycles and disable the led after 3
Part 1
I would suggest to use the type UNSIGNED for a counter, so the '+' operator is defined for this type.
I named it timer_us so it's easy to see that this signal is an unsigned.
Additionally, you can use (others => '0') in declarations, too.
signal reset : STD_LOGIC := '0'; -- disabled reset; TODO move this signal to port
signal timer_us : UNSIGNED(25 downto 0) := (others => '0');
signal timer_tick : STD_LOGIC;
process(clk)
begin
if rising_edge(clk) then
if (reset = '1') then
timer_us <= (others => '0');
else
timer_us <= timer_us + 1;
end if;
end if;
end process;
timer_tick <= '1' when (timer_us = to_unsigned(60 * 1000 * 1000), timer_us'length) else '0';
The last line describes a ternary operator (like z = a ? x : y in C). So the tick signal is '1' if the timer reaches 60,000,000. But there is a fault: Your counter starts at 0 so 60,000,000 cycles are already reached at max - 1.
Some improvements for a more generic counter template:
in most cases it's necessary to reset the counter independently from the main reset -> timer_rst
define a constant for the maximal counter value -> TIMER_MAX
automatically calculate the counter value depending on the maximal counter value -> log2ceil
implement a function to convert boolean expressions to STD_LOGIC -> to_sl
because timer is of type unsigned, you can use a direct comparison with an integer value
Here the extended counter code:
signal reset : STD_LOGIC := '0'; -- disabled reset; TODO move this signal to port
function log2ceil(arg : positive) return natural is
variable tmp : positive := 1;
variable log : natural := 0;
begin
if arg = 1 then return 0; end if;
while arg > tmp loop
tmp := tmp * 2;
log := log + 1;
end loop;
return log;
end function;
function to_sl(condition : BOOLEAN) return STD_LOGIC is
begin
if condition then
return '1';
else
return '0';
end if;
end function;
constant TIMER_MAX : POSITIVE := 60 * 1000 * 1000 - 1;
constant TIMER_BITS : POSITIVE := log2ceil(TIMER_MAX);
signal timer_rst : STD_LOGIC;
signal timer_us : UNSIGNED(TIMER_BITS - 1 downto 0) := (others => '0');
signal timer_tick : STD_LOGIC;
timer_rst <= reset or timer_tick;
process(clk)
begin
if rising_edge(clk) then
if (timer_rst = '1') then
timer <= (others => '0');
else
timer <= timer + 1;
end if;
end if;
end process;
timer_tick <= to_sl(timer = TIMER_MAX - 1));
If you have fun in coding function, you can also invent a function which converts a time (the period for the 0.833 Hz signal) into a cycle count at a given frequency of 50 MHz ;)
Part 2
A blinking LED is a simple T-FF:
signal blink : STD_LOGIC := '0'; -- blink will be mapped to a FF, so initialize it
process(clk)
begin
if rising_edge(clk) then
if (timer_tick = '1') then
blink <= not blink;
end if;
end if;
end process;
LED <= blink;
Or as an one-liner (no need for a process block):
blink <= blink xor timer_tick when rising_edge(clk);
LED <= blink;
Part 3
So now you have all the tools to build counters. You can implement a second counter to count from 0 to 2. if 2 is reached you can set a control signal counter2_ctrl which is then feed back to the blink process to stop this process from toggling.
Here the extended one-liner:
blink_enable <= not counter2_ctrl;
blink <= blink xor (timer_tick and blink_enable) when rising_edge(clk);
To your question
The inverse LED output can be caused by low-active circuits on your test board.
I'm trying to write RS232 transmitter module in vhdl for Spartan. According to simulation in Xilinx, it seems to be working fine, but when i try to deploy it on device, it simply doesn't work. I have found out that it might be problem with latches, but somehow I'm not able to pinpoint them. I'm using 50 Mhz clock and the bit rate of transmission is 115200 bs.
This is my vhdl code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.std_logic_arith.all; -- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity nadajnikRS is
Port ( start : in STD_LOGIC;
reset : in STD_LOGIC;
clk : in STD_LOGIC;
DI : in STD_LOGIC_VECTOR(7 downto 0);
RS_TX : out STD_LOGIC;
busy : out STD_LOGIC);
end nadajnikRS;
architecture Behavioral of transRS is
signal register : STD_LOGIC_VECTOR(8 downto 0) := (others => '1' );
signal counter : INTEGER range 0 to 9 := 0;
signal baud_clk : STD_LOGIC := '0';
signal ready : STD_LOGIC := '0';
type states is (working, free);
signal state: states := free;
signal baud_counter : INTEGER range 0 to 220 := 215;
begin
baud_clock: process (clk)
begin
if rising_edge(clk) then
if (ready = '1') then
if (baud_counter < 218) then
if (baud_counter = 217) then
baud_clk <= '1';
end if;
baud_counter <= baud_counter+1;
else
baud_counter <= 0;
baud_clk <= '0';
end if;
else
baud_counter <= 0;
end if;
end if;
end process baud_clock;
shiftregister : process (baud_clk)
begin
if rising_edge(baud_clk) then
if (state = free) then
RS_TX <= '0';
register (7 downto 0) <= DI;
else
RS_TX <= register(0);
register <= '1' & register(8 downto 1);
end if;
end if;
end process shiftregister;
bitcounter : process (baud_clk)
begin
if rising_edge(baud_clk) then
counter <= counter + 1;
if (counter = 10) then
counter <= 1;
end if;
end if;
end process bitcounter;
shiftstate: process (reset, counter, start)
begin
if (reset = '1') then
ready <= '0';
end if;
if (start = '1') then
ready <= '1';
state <= free;
end if;
if (counter = 1 ) then
state <= working;
elsif (counter = 10) then
state <= free;
end if;
end process;
statemachine : process (state)
begin
case state is
when working => busy <= '1';
when free => busy <= '0' ;
end case;
end process statemachine;
end Behavioral;
During synthesis I get two latch warnings:
Xst:737 - Found 1-bit latch for signal <ready>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
Xst:737 - Found 1-bit latch for signal <state_0>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
I tried to eliminate them by adding additional if statements, but nothing seems to work.
I will be grateful for any help,
Ghaad
A process describing a register should have exactly one signal in the sensitivity list, clk (possibly a reset signal as well if you use asynchronous resets), since a register is only sensitive to a single event, namely a clock edge.
Thus your process sensitivity list baud_clock: process (clk,ready) and shiftregister : process (baud_clk, state) already indicate that you have a problem.
When describing a register, always make sure that your if(rising_edge(clk)) surrounds ALL of the described logic. A simple registered process should look like this:
process(clk) begin
-- NO LOGIC HERE
if(rising_edge(clk)) then
if(reset='1') then
-- Synchronous reset logic here.
else
-- All other logic here.
end if;
end if;
-- NO LOGIC HERE
end process;
Look at your 'shiftstate' process, which is responsible for driving 'ready'. How does it drive 'ready' when 'reset' is not 1, and 'start' is not 1? You haven't told it, so it keeps 'ready' unchanged in those cases. That's what 'latch' means: the process needs to remember what 'ready' was before, and keep it the same; your code therefore infers a memory. Make sure that 'ready' is driven in all branches; you can do this easily with a default assignment at the top.
Having said that, your code has multiple other issues. Did someone suggest in another thread that you shouldn't have your rising edge detection inside an if statement? Or was that someone else? Go back and read it again.
Try to fill all the posibilities of if statements so that for every run the program will know which value correspond to a variable. If statement has almost always go with else or elsif options to not produce latches..
A latch can occur when a process is allowed to go from start to finish without the driven outputs being assigned a value. That is if you have any conditional statements in your process and your outputs are driven inside these conditional statements then there a high chance that the outputs may never be driven. To avoid this it is good practice to place a concurrent statement at the beginning of your process to ensure your outputs are being set at least once. This will tell your synthesiser not to create a latch.