I've wanted to get into FPGAs for over 2 years now, had a MachXO3 development board the whole time, but it's never been a high enough priority. Til now.
I am writing code to completely abstract the protocol vending machines use (MDB protocol). I've been writing it in C (I'm a programming noob btw), but suddenly I've come to the realization that it makes a lot of sense to have an FPGA act as a "bridge chip", so now I finally have a FPGA project.
The simplest file which I will tackle first, is basically a stopwatch/timer, which when reset gets all values set back to zero (inactive/false/zero). When the time reaches a threshold value, a "flag" is set to indicate that condition. This timer is set at each falling edge (active) and set at each rising edge (inactive). I've never written a VHDL program before, so would like help either making sure it's good, or helping me accelerate towards that point. Also, I've been trying to stick to the Linux Kernel Coding style for my C code, which I'm sure I haven't done fully but I'm trying to do it naturally and make it habit. Is there a VHDL equivalent? I'd like to start out with good habits if I can. Also I'm using Lattice Diamond, but is there some sort of open source IDE or whatever Diamond is, for FPGAs? Much like EagleCad and Fusion360, I expect that I'll have wished I started out with the free/open-sourece software.
A few side questions:
I've sorta taken some example code for a shift register, and modified it (so that I can follow VHDL syntax) to be my code. A few things confuse me, the ':=' operator, which appears to assign/declare values, but why not '<=' instead? When I try to google it, I get more confused, reading that '<=' is a boolean less than or equal to operator for VHDL. Every tutorial and example code I've found, uses '<=' to assign a value, so maybe it's just where it's placed that matters?
I believe I understand what processes are and the whole sensitivity list thing, but one question I have is about architectures. Can you have more than one defined for the same module? If so that'd be handy for the code later on that analyzes the data, as data is handled differently if you're a master or slave, but still would use the same "ports". Is there a quick/simple explanation on how to use two different architectures if you can have more than one? If not I'm sure I can look it up when the time comes.
Is there a '#define' equivalent I can use in VHDL to put some human readable names on different values?
Finally, I've followed a youtube tutorial for a development board similar to mine using Lattice Diamond, and when the spreadsheet came up where you assign pin values, there's also options to toggle fast or slow slew rate, why would you want slow? I'm aware there's timing stuff you gotta deal with (aware it exists, not aware of how to deal with it). There's also a hysteresis value I don't know anything about, and an 'outload' value (with picoFarads as the unit) which I also know nothing about. Are these "advanced" features I need not worry about yet, or are they essential functions for all designs?
Oh I just remembered, I have one port as "inout", because it gets written to, then read from. But so does anything else? If I remember right, inout was for multiple sources that set it, so the 'time_elapsed' value could just be an IN type/direction right?
VHDL Code
library ieee ;
use ieee.std_logic_1164.all;
--------------------------------------------------------------------------------
entity chronoLogic is
Port (t_setup, t_break, t_response, t_inter_byte : out std_logic);
Port (time_elapsed : inout std_logic)
Port (reset : in std_logic);
end chronoLogic;
--------------------------------------------------------------------------------
architecture check of chronoLogic is
signal t_setup : bit := "0";
signal t_break : bit := "0";
signal t_response : bit := "0";
signal t_inter_byte : bit := "0";
signal microseconds : bit := "0";
process(time_elapsed)
begin
if time_elapsed'event and time_elapsed = '200000' then
t_setup <= '1';
end if;
if time_elapsed'event and time_elapsed = '100000' then
t_break <= '1';
end if;
if time_elapsed'event and time_elapsed = '5000' then
t_response <= '1';
end if;
if time_elapsed'event and time_elapsed = '1000' then
t_interByte <= '1';
end process;
--------------------------------------------------------------------------------
C Code
--uint8_t chronoLogic(uint8_t command)
--{
-- if (command == TIMER_RESET) {
-- microseconds = micros(); /*Each device has a local static copy of microseconds*/
-- return OKKK;
-- }
-- else if (command == TIMER_UPDATE) {
-- time_elapsed = micros() - microseconds;
-- /* #HardwareAdjust Verify timing with a logic analyzer and adjust values if necessary*/
-- if (time_elapsed > 200000) return T_SETUP; /*Bus Reset is over*/
-- if (time_elapsed > 100000) return T_BREAK; /*Bus Reset Timer */
-- if (time_elapsed > 5000) return T_RESPONSE;
-- if (time_elapsed > 1000) return T_INTER_BYTE;
-- }
--}