How to use the internal oscillator in an FPGA (Lattice MachXO3)? - vhdl

I'm trying to make a Blink-LED program for a Lattice MachXO3L breakout board. I believe I have the internal-oscillator set up, I just don't know how to connect to its output and make use of it, I get errors when I try. This is on a breakout board which has an LED and a switch. It should oscillate at 1Hz when the switch is flipped one way, and be off when the switch is flipped the other way.
I'e read the PLL usage guide and searched for answers on the internet. I believe I'm close, and just hung up on some syntax issue due to being new to VHDL & FPGAs. Basically, my main code is the 'process and all code below it. Anything above that is basically stuff from the PLL usage guide.
library ieee;
use ieee.std_logic_1164.all;
library machxo3l;
use machxo3l.all;
entity led_blink is
port (
i_switch_1 : in std_logic;
o_led_1 : out std_logic;
i_clock : in std_logic;
osc_int : out std_logic
);
end led_blink;
architecture rtl of led_blink is
COMPONENT OSCH
-- synthesis translate_off
GENERIC (NOM_FREQ: string := "12.09");
-- synthesis translate on
PORT ( STDBY:IN std_logic;
OSC:OUT std_logic);
END COMPONENT;
attribute NOM_FREQ : string;
attribute NOM_FREQ of OSCHinst0 : label is "12.09";
constant C_CNT_1HZ : natural := 6000000;
signal R_CNT_1HZ : natural range 0 to C_CNT_1HZ;
signal R_1HZ : std_logic := '0';
begin
OSCHInst0: OSCH
-- synthesis translate_off
GENERIC MAP(NOM_FREQ => "12.09")
-- synthesis translate on
PORT MAP (STDBY => '0',
OSC => osc_int
);
p_1HZ : process (i_clock) is
begin
if rising_edge(i_clock) then
if R_CNT_1HZ = C_CNT_100HZ-1 then
R_1HZ <= not R_1Hz;
R_CNT_1HZ <= 0;
else
R_CNT_1HZ <= R_CNT_1HZ + 1;
end if;
end if;
end process;
osc_int <= i_clock;
o_led_1 <= R_1HZ when (i_switch_1 = '0') else not R_1HZ;
end rtl;
If I try and assign osc_int to the sensitivity list of the p_1Hz process, I get an error stating that I can not read from an output.
Just a side-note in case other viewers get confused like me, driving i_clock from osc_int appears illogical, because it uses an assignment that seems to suggest the reverse occurs osc_int <= i_clock. Correct me if I'm wrong, but it's assigning an input, to an output, which appears confusing to non-hdl programmers because the direction is decided by the input/output types, rather than the assignment operator itself.
When I do this (link i_clk to osc_int), it saves without giving me errors, it isn't until I try to synthesize the code that it says there are multiple non-tristate drivers for i_clock. The only way I can imagine this being true is if the 'port' from the 'component' section named OSC, being mapped to osc_int, creates two driving signals both linked to i_clock in that single osc_int <= i_clock; statement. But if that's true, how would you access the clock's output at all?
If I just remove the osc_int <= i_clock statement, it works, just with the LED constantly-on/constantly-off, not oscillating/constantly-off.

The clock generated came from inside the OSCH component. Then you don't need any i_clock to achieve what you want. The output of the internal oscillator is the OUT port of the OSCH component.
you can try this :
entity led_blink is
port (
i_switch_1 : in std_logic; -- from the input switch : OK
o_led_1 : out std_logic -- to the blinking led : OK
);
end led_blink;
architecture rtl of led_blink is
COMPONENT OSCH
-- synthesis translate_off
GENERIC (NOM_FREQ: string := "12.09");
-- synthesis translate on
PORT ( STDBY:IN std_logic;
OSC:OUT std_logic);
END COMPONENT;
attribute NOM_FREQ : string;
attribute NOM_FREQ of OSCHinst0 : label is "12.09";
constant C_CNT_1HZ : natural := 6000000;
signal R_CNT_1HZ : natural range 0 to C_CNT_1HZ := 0;
signal R_1HZ : std_logic := '0';
begin
OSCHInst0: OSCH
-- synthesis translate_off
GENERIC MAP(NOM_FREQ => "12.09")
-- synthesis translate on
PORT MAP (STDBY => '0',
OSC => osc_int -- <= this is the 12.09MHz internal clock from the internal oscillator
);
p_1HZ : process (osc_int) is
begin
if rising_edge(osc_int) then
if R_CNT_1HZ = C_CNT_100HZ-1 then
R_1HZ <= not R_1Hz;
R_CNT_1HZ <= 0;
else
R_CNT_1HZ <= R_CNT_1HZ + 1;
end if;
end if;
end process;
o_led_1 <= R_1HZ when (i_switch_1 = '0') else '0';
end rtl;

Related

Type of identifier does not agree with its usage as "boolean" type - VHDL in Quartus

I'm developing a simple buffering system in VHDL. I get the error I mentioned in the title for "empty" whenever I try to compile. I don't know why it won't let me invert a std_logic type. I've also been getting errors about the comparisons. For some reason, it doesn't recognize the ">" and "<" operators on status_as_int and the thresholds.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
ENTITY Buffer_Controller is
port (
empty : in std_logic;
full : in std_logic;
filling_status : in std_logic_vector(14 downto 0);
read_thresh : in integer;
write_thresh : in integer;
read_now : out std_logic;
write_now : out std_logic
);
END ENTITY;
ARCHITECTURE ctrl of Buffer_Controller is
signal status_as_int : integer;
BEGIN
status_as_int <= to_integer(unsigned(filling_status));
read_now <= '1' when (NOT(empty) AND status_as_int > read_thresh) else
'0';
write_now <= '1' when (NOT(full) AND status_as_int < write_thresh) else
'0';
END ARCHITECTURE;
empty and full are not booleans. They're std_logic, which is a user defined type (defined in the ieee.std_logic_1164 library). That's not a boolean.
Yes, you can invert them, but the result will still be std_logic. (The overloaded implementation of NOT for std_logic is also defined in the ieee.std_logic_1164 library).
To convert to boolean, You need to compare them to something that can be interpreted as std_logic, e.g.
read_now <= '1' when
empty = '0' AND
status_as_int > read_thresh
else '0';

Trigger On Very Short Pulse - VHDL

I'm using a CMOD A7 (Artix 7) and I need to trigger a process based on a pulse of around 10ns duration (blue line):
Normally I'd do triggering like this by having a process constantly compare the current value of the input line with the last value using a temporary register to hold the last value. However, I believe the oscillator on this board has a period of around 83ns which is far too slow for this approach.
If I was using pure digital electronics, this would be easy, connect a flipflop to the trigger, poll the output of that flipflop (which would change and latch with the input) and then reset it once I've read it and started my actions. So I would imagine there's a way to do this in VHDL but I'm led to believe using if rising_edge() on non-clock signals is a no-go.
Where do I start with this?
So the solution here is twofold:
Firstly, I can derive a 100MHz clock using the onboard MCCM and Vivado's ClockWiz IP.
I can also use the FDCE component provided by Vivado to utilise one of the onboard flipflops to extend the pulses and reset it after passing it through a few flipflops for synchronisation.
I've not tested this yet but I believe it should work:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library unisim;
use unisim.vcomponents.all;
entity input_syncroniser is
generic
(
in_pipe_len: in positive := 5
);
port
(
clk : in STD_LOGIC;
rst : in STD_LOGIC;
din : in STD_LOGIC;
dfo : out STD_LOGIC
);
end input_syncroniser;
architecture behavioural of input_syncroniser is
signal delayed_pulse: std_logic := '0';
signal in_pipe: std_logic_vector(in_pipe_len - 1 downto 0) := (others => '0');
signal pipe_head: std_logic := '0';
begin
FDCE_inst : FDCE
generic map
(
INIT => '0'
)
port map
(
Q => delayed_pulse,
C => din,
CE => '1',
CLR => pipe_head,
D => '1'
);
input_synchroniser: process(clk)
begin
if (rising_edge(clk)) then
in_pipe <= in_pipe(in_pipe'high downto in_pipe'low) & delayed_pulse;
end if;
end process;
pipe_head <= in_pipe(in_pipe'high);
dfo <= pipe_head;
end behavioural;

'Opt_Design Error' in Vivado when trying Run Implementation

Trying to make a UART Transmitter to send a data from FPGA to PC; 9600 baudrate, 8-bits, no parity, 1 start & stop bit; I wrote a code with VHDL, run synthesis and simulate it in a way I like it to be. I wanted to see it with BASYS 3 FPGA, After created constraints, Run Implementation issued an error in which its called "Opt_Design Error".
library ieee;
use ieee.std_logic_1164.all;
entity rs232_omo is
generic(clk_max:integer:=10400); --for baudrate
port(
clk : in std_logic;
rst : in std_logic;
start : in std_logic;
input : in std_logic_vector(7 downto 0);
done : out std_logic;
output : out std_logic;
showstates: out std_logic_vector(3 downto 0)
);
end entity;
architecture dataflow of rs232_omo is
type states is (idle_state,start_state,send_state,stop_state);
signal present_state,next_state : states;
signal data,data_next : std_logic;
begin
process(clk,rst)
variable count : integer range 0 to clk_max;
variable index : integer range 0 to 10;
begin
if rst='1' then
present_state<=idle_state;
count:=0;
data<='1';
done<='0';
elsif rising_edge(clk) then
present_state<=next_state;
count:=count+1;
index:=index+1;
data<=data_next;
end if;
end process;
process(present_state,data,clk,rst,start)
variable count : integer range 0 to clk_max;
variable index : integer range 0 to 10;
begin
done<='0';
data_next<='1';
case present_state is
when idle_state =>
showstates<="1000";
data_next<='1';
if start='1' and rst='0' then
count:=count+1;
if count=clk_max then
next_state<=start_state;
count:=0;
end if;
end if;
when start_state =>
showstates<="0100";
data_next<='0';
count:=count+1;
if count=clk_max then
next_state<=send_state;
count:=0;
end if;
when send_state =>
showstates<="0010";
count:=count+1;
data_next<=input(index);
if count=clk_max then
if index=7 then
index:=0;
next_state<=stop_state;
else
index:=index+1;
end if;
count:=0;
end if;
when stop_state =>
showstates<="0001";
count:=count+1;
if count=clk_max then
next_state<=idle_state;
done<='1';
count:=0;
end if;
end case;
end process;
output<=data;
end architecture;
This's the error message in detail
"[DRC MDRV-1]Multiple Driver Nets:Net done_OBUF has multiple drivers:
done_OBUF_inst_i_1/O,and done_reg/Q"
"[Vivado_Tcl 4-78] Error(s) found during DRC. Opt_Design not run."
What would be the reason for this error?
You are assigning done both in the first and the second process, which is exactly what the implementation is complaining about, you cannot have multiple drivers.
Remove done<='0'; from the first process and it should complete the implementation.
(I didn't check if the rest of the code is doing exactly what you want.)

VHDL FSM not compiling

I've created the following fsm to control a fir filter but I'm getting two errors while compiling.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL;
entity fsm is
generic (n: integer:=4);
port( clk: in STD_LOGIC;
rst: in STD_LOGIC;
a: out STD_LOGIC_VECTOR(2*n-1 downto 0));
end fsm;
architecture fsm_struct of fsm is
type state_type is (state0, state1, state2);
signal state: state_type;
signal rstff, rom_enable, ram_read_enable, ram_write_enable: STD_LOGIC;
component filter_rom is
generic (n: integer);
port ( clk: in STD_LOGIC;
rstff: in STD_LOGIC;
rom_enable : in STD_LOGIC;
ram_read_enable : in STD_LOGIC;
ram_write_enable : in STD_LOGIC;
a: out STD_LOGIC_VECTOR(2*n-1 downto 0));
end component;
begin
process(clk,rst)
variable delay1:integer:=0;
variable delay2:integer:=0;
variable delay3:integer:=0;
begin
if rst='1' then
state<=state0;
else if rising_edge(clk) then
case state is
when state0 => --initialize & input data
rom_enable<='1';
rstff<='1';
if delay1=1 then
rstff<='0';
state<=state1;
delay2:=0;
else
delay1:=delay1+1;
state<=state0;
end if;
when state1 => --write data to ram
if delay2=2 then
ram_write_enable<='1';
state<=state2;
delay3:=0;
else
delay2:=delay2+1;
state<=state1;
end if;
when state2 => --read data from ram
if delay3=1 then
ram_read_enable<='1';
state<=state0;
delay1:=0;
else
delay3:=delay3+1;
state<=state2;
end if;
end case;
end if;
end process;
filter0: filter_memory generic map(n=>n) port map(clk,rstff,rom_enable,ram_read_enable,ram_write_enable,a);
end fsm_struct;
The errors I'm getting are: Line 83: Syntax error near "process",
Line 85: Syntax error near "generic". at the end of the program. I know that my code won't even compile to any of your machines as my filter is not defined, but I need some help from a fresh set of eyes.
I used 'else if' instead of 'elsif' and it didn't compile.
filter0: filter_memory generic map(n=>n) but your component name is filter_rom
try
filter0: filter_rom generic map(n=>n)
If you changed else if to elsif change it here also.
It compiles in Vivado 2017.4

Is it possible to programmatically define a Hierarchical Name in VHDL 2008?

I have a rather large project, comprised of many modules integrated into one top-level component. I've created test-benches for these modules which make use of API packages (which I've created alongside them). I also have a top-level test-bench that tests the integrated system as a whole.
For one of the components, I'm interested in using VHDL-2008 Hierarchical Names within its MyModuleAPIPackage in order to access the internal signals from the top level testbench. Since I'm trying to write modular and re-usable code, I'd like to be able to instantiate the package so that it references the signals of the module within the component-level test (where the module is at the top level)
<<signal .MyComponent.MySignal : std_logic>>
and also within the top-level test (where there is an underlying structure)
<<signal .MySystem.MySubSystem.MyComponent.MySignal : std_logic>>
Perhaps this could be attainable through a combination of Hierarchical Names and generics?
Here is some (pseudo) code exemplifying what I'm trying to achieve.
MyModule.vhd
-- MyModule.vhd
entity MyModule is
port(
CLK : in std_logic;
RST : in std_logic;
DATA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(7 downto 0)
);
end entity MyModule;
architecture behavioral of MyModule is
-- Signal and constant definitions here.
begin
-- Describes how MyModule behaves.
end architecture behavioral;
----------------------
-- MyModule Test-Bench
----------------------
entity MyModule_tb is
end entity MyModule_tb;
architecture test of MyModule_tb is
-- Signal and constant definitions here
signal CLK, RST : std_logic := '0';
signal DATA_IN, DATA_OUT : std_logic_vector(7 downto 0) := (others = '0');
procedure DoComplexStuff(
InstructionCode : natural
)
is
begin
case InstructionCode is
when 0 =>
DATA_IN <= "01010101";
wait until CLK = '1';
DATA_IN <= "00110011";
wait until CLK = '1';
-- Lots of pretty complex stimuli
assert DATA_OUT = "00110011"
report "Output mismatch!"
severity failure;
when 1 =>
-- Lots of pretty complex stimuli
-- when ... =>
-- Plenty more instruction codes
others =>
null;
end procedure DoComplexStuff;
begin
CLK <= not CLK after 1 ms;
MainTestProc:
process
begin
for i in 0 to 99 loop
DoComplexStuff(i);
end loop;
end;
DUT: entity work.MyModule(behavioral)
port map(
CLK => CLK,
RST => RST,
DATA_IN => DATA_IN,
DATA_OUT => DATA_OUT
);
end architecture test;
I wish for procedure DoComplexStuff to be available at the top-level.
MyModuleApi.vhd
package MyModuleAPI is
generic(
-- Programatically defined aliases
PATH : path;
)
alias CLK is <<signal PATH.CLK : std_logic);
alias RST is <<signal PATH.RST : std_logic);
alias DATA_IN is <<signal PATH.DATA_IN : std_logic_vector(7 downto 0));
alias DATA_OUTis <<signal PATH.DATA_OUT : std_logic_vector(7 downto 0));
procedure DoComplexStuff(
InstructionCode : in natural
);
end package;
package body MyModuleAPI is
-- I can now include this package within MyModule_tb and
-- MyTopLevelComponent_tb and call DoComplexStuff to interact with the signals
-- from MyModule
procedure DoComplexStuff(
InstructionCode : natural
)
is
begin
case InstructionCode is
when 0 =>
DATA_IN <= "01010101";
wait until CLK = '1';
DATA_IN <= "00110011";
wait until CLK = '1';
-- Lots of pretty complex stimuli
assert DATA_OUT = "00110011"
report "Output mismatch!"
severity failure;
when 1 =>
-- Lots of pretty complex stimuli
-- when ... =>
-- Plenty more instruction codes
others =>
null;
end procedure DoComplexStuff;
end package body MyModuleAPI;
Therefore, MyModule_tb would include the package MyModuleAPI with a parameter specifying itself as the top level component and MyTopLevel_tb would include the same package with a parameter properly specifying the path to MyModule. (?)
NOTE: yes, my intention is to modify (bit-bang) internal signals during a top-level test. This would be similar to using ModelSim's "signal_force" and "signal_release" commands.
Thanks in advance for your guidance!

Resources