Tuesday, 12 September 2017

Using Components in VHDL

Recently I was asked to provide a bit of assistance with some VHDL code - One of the blog readers was looking to implement a logic based CPU on the Mimas V2 Development board. I don't claim to be an expert in VHDL but the crux of his issue was using pre-written code in one project several times. The beauty of FPGA technology is that as long as there is space within the device and pins available it is possible to have as many logic functions as one wants!

There comes a point in FPGA programming where trying to put all of the code in one single source file becomes really awkward. The file would become very long to read and debug and it may make more sense to take a modular approach and re-use code from previous designs. Luckily for the FPGA design engineer it is possible to write and design modules in VHDL very easily and each module can be tested and used on it's own.

The way to implement this is to use the component keyword in VHDL and 'instantiate' as many of the modules or blocks of code as one wants.

In previous posts I have already used this method but I haven't really ever discussed it explicitly so here goes:
In a VHDL source module the code is organised into section statements known as:
  • Entities - The statement which defines the external input and output connections of the module.
  • Architectures - This is the code section which actually tells or defines the function of the module.
  • Components - A statement within the architecture section which allows the designer to link internal signals or external signals with pre-written VHDL code in another module.
  • Instances - A statement which actually creates the 'instance' of the external module code within another module. A designer can have multiple instances of a module within a design with one component statement as long as all of the connections are correctly port mapped.
Here is an example of an Entity statement:

entity EntitySection is
           Port ( clkinput : in STD_LOGIC;
                  input1 : in STD_LOGIC;
                  input2 : in STD_LOGIC;
                  input3 : in STD_LOGIC;
                  output1 : out STD_LOGIC;
                  output2 : out STD_LOGIC);
end EntitySection;

You can have as many inputs and outputs as you like and there can be combined inputs and outputs. The green text are keywords and cannot be used as labels. The red text are labels which are used to remind the designer what the entity's purpose is. The black text are the defined inputs and outputs. The blue text are the type of inputs and outputs.

Here is an example of an Architecture statement:

architecture Behavioral of EntitySection is 
begin 
      input1 <= not input2; 
end Behavioral;

This is the section of code that defines how the internal signals and external signals will interact to realise the function required. As before the green text are keywords, the red text are labels and the black text are the inputs and outputs.

Here is an example of a Component statement:

COMPONENT Not_gate 
          PORT( input1  : IN std_logic
                output1 : OUT std_logic); 
END COMPONENT;

As above, the different colours relate to keywords, labels, definitions and types.
Here is an example of a Instantiation statement:

Inst_Not_gate: Not_gate 
         PORT MAP(
                   input1  => input_signal1, 
                   output1 => output_signal1 
                  );

The instantiation code is the way the designer defines how the signals from the component module connect to the signals within the source module. These signals in the source module could be internal or external signals.

As an example lets write some simple two input logic gates in VHDL code and then'instantiate multiple versions of them in VHDL and then simulate their function and then finally show the results working on the Mimas V2 FPGA Development board. In theory any FPGA development board could be made to work including the Elbert V2 (I will share the Elbert V2 version also as I know some people are using those boards).

Load up Xilinx WebISE and start a new project - I called mine Lots of gates and placed it in a suitable folder on the hard disk.


Click next when ready to continue...


Input the settings shown (These are correct for the Numato Labs Mimas V2 development board).
Then click next when ready...


Click Finish to return to the main project screen within Xilinx WebISE:


Next right click on the Hierarchy window and select Add new source:


Select VHDL source module and give it a suitable name - I called mine Not_gate:


Click Next when ready to continue and enter the inputs and outputs for the Not_gate module. I chose to have an input and an output - to create a single inverter.


Click Next when ready to continue and display the summary page:


Click Finish to return to the main project window:


The WebISE software has helpfully created some code for us based on the decisions we made. I like to delete the comments (green text) as I don't find them helpful:


Now we need to write the architecture statement to make the module behave as an inverter or Not gate. It is very simple as the inverter function is already present within VHDL. Here is the code for the entire module:

library IEEE
use IEEE.STD_LOGIC_1164.ALL

entity Not_gate is 
    Port ( A : in STD_LOGIC
           B : out STD_LOGIC); 
    end Not_gate

architecture Behavioral of Not_gate is 
  begin 
     B <= not A; 
  end Behavioral;

Now save the module - just in case...and then right click on the synthesize – XST process and select run. The software checks the code written is correct. Once the process has completed there will be a green tick on that section:


Now let’s simulate the code we have just written to ensure it works properly before we use it. It's always a good idea to simulate things to make sure that it works as intended.

Click on the simulate radio button on the Hierarchy window:



Next right click on the Hierarchy window and select Add new source:


Select VHDL test bench and call the file something sensible...I called mine Not_gate_tb. Click Next when ready to continue:



Associate the test bench source file with the code you wish to simulate...click Next when ready to continue:



Click finish to continue and return to the main project window:



Helpfully Xilinx WebISE has automatically generated the test bench code for us...unhelpfully it has also introduced some errors. Don't worry about these for now...the code generated is expecting a clock source to be present. There isn't a clock source in our design as we did not need one. We will remove the errors when we modify the test bench code. Again I like remove the top comments as I don't need them. Comments are useful but only when necessary...

Here is the code with the comments removed:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
 
ENTITY Not_gate_tb IS
END Not_gate_tb;
 
ARCHITECTURE behavior OF Not_gate_tb IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT Not_gate
    PORT(
         A : IN  std_logic;
         B : OUT  std_logic
        );
    END COMPONENT;
    

   --Inputs
   signal A : std_logic := '0';

  --Outputs
   signal B : std_logic;
   -- No clocks detected in port list. Replace <clock> below with 
   -- appropriate port name 
 
   constant <clock>_period : time := 10 ns;
 
BEGIN
 
 -- Instantiate the Unit Under Test (UUT)
   uut: Not_gate PORT MAP (
          A => A,
          B => B
        );

   -- Clock process definitions
   <clock>_process :process
   begin
  <clock> <= '0';
  wait for <clock>_period/2;
  <clock> <= '1';
  wait for <clock>_period/2;
   end process;
 

   -- Stimulus process
   stim_proc: process
   begin  
      -- hold reset state for 100 ns.
      wait for 100 ns; 

      wait for <clock>_period*10;

      -- insert stimulus here 

      wait;
   end process;
 
END;

Now we need to remove the code relating to the automatically generated clock as this isn't
required:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
 
ENTITY Not_gate_tb IS
END Not_gate_tb;
 
ARCHITECTURE behavior OF Not_gate_tb IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT Not_gate
    PORT(
         A : IN  std_logic;
         B : OUT  std_logic
        );
    END COMPONENT;
    

   --Inputs
   signal A : std_logic := '0';

  --Outputs
   signal B : std_logic;
 
BEGIN
 
 -- Instantiate the Unit Under Test (UUT)
   uut: Not_gate PORT MAP (
          A => A,
          B => B
        );

   -- Stimulus process
   stim_proc: process
   begin  
      -- hold reset state for 100 ns.
      wait for 100 ns; 

      -- insert stimulus here 

      wait;
   end process;

END;

The code generated actually uses the component statement so our automatically generated code is a perfect example of how a statement should be used! In the architecture statement we can see the component declaration for the Not_gate. Below that section some internal signals are defined to connect to the component we would like to simulate. Underneath that section we have the instantiation section which creates a version of the not_gate called 'uut' and maps the internal signal connections to the component signal connections. Now we need to write some code in the stimulus process section which sets the A input signal to a known value so that the simulator can run the code in the Not_gate module and display what will happen at the output signal - B.

As the module is an inverter or not gate it should be obvious that whatever logic level is present at the output signal is the opposite or inverse of the input signal. For more complicated modules this might be more difficult to assess which is why simulation is useful. It is also possible to see if there are any timing or sequencing issues present with more complicated modules. Simulation can be a very useful diagnostic tool when developing FPGA code.

Let’s write the stimulus VHDL code to test the module code and provide the simulator some information. Let’s set the 'A' input of the inverter to logic '1' for 100 ns and then set it to logic '0' for 100 ns and then set it to an unknown logic level 'X' for 100 ns. When we run the simulator we will be able to visually see what the output signal 'B' does when presented with those input 'stimuli' or logic states.

*Stimuli - a latin word which is the plural of stimulus, to provide a specific functional reaction!

Here is the code:

-- Stimulus process
   stim_proc: process
   begin  
      -- hold reset state for 100 ns.
      wait for 100 ns; 

      A <= '1';
  wait for 100 ns; 
  
  A <= '0';
  wait for 100 ns;
  
  A <= 'X';
  wait for 100 ns;

      wait;
   end process;

Let’s save the code and run the simulator! Click on the Not_gate VHDL test bench module in the Hierarchy window:


Next right click on 'Behavioral Check Syntax' in the process window and select Run:


Once the process has completed there should be a green tick present:



Next right click on Simulate Behavioral Model and select Run:


Once the process has completed the ISIM screen will be displayed showing the results of the simulation:


At first it looks as though the simulation has failed as the result traces are red and in an X state - don't worry though that is what was expected. The last state we simulated was an 'X' state for the input signal. Click on the 'Zoom to Full View' icon on the toolbar to display the full results traces:


The green part of the traces show how the input 'A' went from a logic '0' to a logic '1' after 100 ns and the output 'B' changed accordingly. Then the input 'A' went from a logic '1' to a logic '0' for 100 ns and then the input 'A' was set to an unknown logic state 'X' and the output 'B' responded with a logic 'X' for the rest of the simulation - exactly what the test bench code was meant to do. So our simulation worked perfectly and more importantly the Not_gate module works perfectly!

This module can now be reused as many times as we like in any of our designs - Most Excellent!

Close down the ISIM application as we are finished with that program to return to the main project screen.

Let’s add some more logic functions like the AND, OR, and XOR functions. I'm not going to show all of the steps with pictures this time though, it's the same process as before.

Click on the implementation radio button and then add new VHDL source modules to the project. I called mine And_gate, Or_gate and XOR_gate. I chose to make them all two input devices with one output.


Here is the project window with all of the VHDL source file modules:


I deleted all of the comments that were not needed for each of the new modules and added the necessary code for the architecture sections. The code should be pretty self-explanatory but just in case here is the VHDL code for each logic function:

And Gate logic function VHDL code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity And_Gate is
    Port ( A : in  STD_LOGIC;
           B : in  STD_LOGIC;
           Q : out  STD_LOGIC);
end And_Gate;

architecture Behavioral of And_Gate is

begin

   Q <= A and B;

end Behavioral;

Or Gate logic function VHDL code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Or_gate is
    Port ( A : in  STD_LOGIC;
           B : in  STD_LOGIC;
           Q : out  STD_LOGIC);
end Or_gate;

architecture Behavioral of Or_gate is

begin

Q <= A or B;

end Behavioral;

Xor Gate logic function VHDL code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Xor_gate is
    Port ( A : in  STD_LOGIC;
           B : in  STD_LOGIC;
           Q : out  STD_LOGIC);
end Xor_gate;

architecture Behavioral of Xor_gate is

begin

Q <= A xor B;

end Behavioral;

Ensure each VHDL module has the correct code. If you were so inclined you could then simulate each module to make certain the code behaves as intended. I'm not going to bother this time but for more complicated modules it's very important that it's simulated. I have saved myself hours of debugging by simulating the module behaviour before continuing.

At this point I like to draw a diagram which shows what function I want all of these modules to perform when connected together. Normally I would do this before I start writing the code but as this is just an example I'm doing it now. Lets implement each logic gate into the FPGA and use the DIP switches to connect to the inputs of the logic gates and then lets connect the outputs of the logic gates to the LEDS so that we can see the results when we change the state of the DIP switches!


From the diagram we can now create a VHDL top module which will connect to the DIP switches and LED and we can then make components to call all of the other modules and connect those modules inputs and outputs to the top module's inputs and outputs. Sounds complicated but it is actually fairly simple. Lets create the top module by right clicking in the hierarchy window as before...I called mine lots_of_gates_top_module:


Click Next and lets select how many inputs and outputs we will need. We need one input and output for the Not gate, two inputs and one output for the And gate, Or gate and Xor gate. So that makes seven inputs and four outputs. Give the inputs and outputs sensible names:


Click next to display the summary screen:


Click Finish to return to the main project screen.


Again remove the comments that are not necessary. Add comments later if required...


Now we need to add the component statements in the architecture section. The first
component we want to add is the Not gate. There is a really cool and easy way to do this thanks to Xilinx WebISE all we have to do is click on the module we want to use and then click on the Design Utilities option in the process window and double click on 'View HDL Instantiation Template':


We can then select and copy the code without the comments and paste it into the architecture section of the top module. It saves typing and it's completely correct! All we then need to do is correctly complete the port map section and our first component is done:


The Not_gate component signal connections map to the Not_input signal and the Not_Output_LED signal. I also changed the component instantiation label to something more meaningful. It can get awkward when you have multiple components of the same type if you don't use a sensible naming convention:


Repeat the process for all of the other components we intend to add. Once you have done that we need to move the instantiation sections to the begin and end section of the architecture statement. Once complete the code should look like this:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity lots_of_gates_top_module is
    Port ( Not_input : in  STD_LOGIC;
           Not_Output_LED : out  STD_LOGIC;
          
     And_A_Input : in  STD_LOGIC;
           And_B_Input : in  STD_LOGIC;
           And_Q_Output_LED : out  STD_LOGIC;
          
     Or_A_Input : in  STD_LOGIC;
           Or_B_Input : in  STD_LOGIC;
           Or_Q_Output_LED : out  STD_LOGIC;
          
     Xor_A_Input : in  STD_LOGIC;
           Xor_B_Input : in  STD_LOGIC;
           Xor_Q_Output_LED : out  STD_LOGIC);
end lots_of_gates_top_module;

architecture Behavioral of lots_of_gates_top_module is

 COMPONENT Not_gate
 PORT(
  A : IN std_logic;         
  B : OUT std_logic
  );
 END COMPONENT;

 COMPONENT And_Gate
 PORT(
  A : IN std_logic;
  B : IN std_logic;         
  Q : OUT std_logic
  );
 END COMPONENT;

 COMPONENT Or_gate
 PORT(
  A : IN std_logic;
  B : IN std_logic;         
  Q : OUT std_logic
  );
 END COMPONENT;

 COMPONENT Xor_gate
 PORT(
  A : IN std_logic;
  B : IN std_logic;         
  Q : OUT std_logic
  );
 END COMPONENT;

begin

 Not_gate_1: Not_gate PORT MAP(
  A => Not_input,
  B => Not_Output_LED
 );

 And_Gate_1: And_Gate PORT MAP(
  A => And_A_Input,
  B => And_B_Input,
  Q => And_Q_Output_LED
 );

 Or_gate_1: Or_gate PORT MAP(
  A => Or_A_Input,
  B => Or_B_Input,
  Q => Or_Q_Output_LED
 );

 Xor_gate_1: Xor_gate PORT MAP(
  A => Xor_A_Input,
  B => Xor_B_Input,
  Q => Xor_Q_Output_LED
 );

end Behavioral; 

The code should be fairly self-explanatory. Save the module and now let’s simulate it to make sure it will work as intended. Using the same process as before let’s create a test bench forthe top module and make sure that everything will work.

Click on the simulate radio button in the hierarchy window and then add a new source, select VHDL test bench and give it a suitable name. I called mine lots_gates_test_bench. Then associate the module with the lots_of_gates VHDL module and click finish. Then WebISE will generate some code for us. Delete the comments as necessary. After that delete the clock sections as we don't need those sections.

Finally all that is needed is to write the stimuli section like before. Lets exercise each gate in turn with suitable logic levels and allow time for each state to be easily viewed on the simulator screen. We could exercise all the gates at once but I prefer to see each state separately.

Here is the stimulus code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity lots_of_gates_top_module is
    Port ( Not_input : in  STD_LOGIC;
           Not_Output_LED : out  STD_LOGIC;
          
     And_A_Input : in  STD_LOGIC;
           And_B_Input : in  STD_LOGIC;
           And_Q_Output_LED : out  STD_LOGIC;
          
     Or_A_Input : in  STD_LOGIC;
           Or_B_Input : in  STD_LOGIC;
           Or_Q_Output_LED : out  STD_LOGIC;
          
     Xor_A_Input : in  STD_LOGIC;
           Xor_B_Input : in  STD_LOGIC;
           Xor_Q_Output_LED : out  STD_LOGIC);
end lots_of_gates_top_module;

architecture Behavioral of lots_of_gates_top_module is

 COMPONENT Not_gate
 PORT(
  A : IN std_logic;         
  B : OUT std_logic
  );
 END COMPONENT;

 COMPONENT And_Gate
 PORT(
  A : IN std_logic;
  B : IN std_logic;         
  Q : OUT std_logic
  );
 END COMPONENT;

 COMPONENT Or_gate
 PORT(
  A : IN std_logic;
  B : IN std_logic;         
  Q : OUT std_logic
  );
 END COMPONENT;

 COMPONENT Xor_gate
 PORT(
  A : IN std_logic;
  B : IN std_logic;         
  Q : OUT std_logic
  );
 END COMPONENT;

begin

 Not_gate_1: Not_gate PORT MAP(
  A => Not_input,
  B => Not_Output_LED
 );

 And_Gate_1: And_Gate PORT MAP(
  A => And_A_Input,
  B => And_B_Input,
  Q => And_Q_Output_LED
 );

 Or_gate_1: Or_gate PORT MAP(
  A => Or_A_Input,
  B => Or_B_Input,
  Q => Or_Q_Output_LED
 );

 Xor_gate_1: Xor_gate PORT MAP(
  A => Xor_A_Input,
  B => Xor_B_Input,
  Q => Xor_Q_Output_LED
 );

end Behavioral; 

Let’s check the syntax and run the simulator!

Here is the result, I did manipulate the traces to put the outputs next to the inputs:


Close down the simulator...It’s time for the final bit of code writing - creating the implementation constraints file to tell WebISE how the external devices will connect to the FPGA signals in our design. In the hierarchy window click on add new source and choose implementation constraints file:


Click next to continue:


Click Finish to return to the main project screen. Now we need to decide how we want our DIP switches and LEDS to connect to our inputs and outputs.
  • Let’s set DIP switch 0 to be the Not gate input
  • Let’s set LED 0 to be the Not gate output
  • Let’s set DIP switch 1 to be the AND gate A input
  • Let’s set DIP switch 2 to be the AND gate B input
  • Let’s set LED 1 to be the AND gate Output
  • Let’s set DIP switch 3 to be the OR gate A input
  • Let’s set DIP switch 4 to be the OR gate B input
  • Let’s set LED 3 to be the OR gate Output
  • Let’s set DIP switch 5 to be the XOR gate A input
  • Let’s set DIP switch 6 to be the XOR gate B input
  • Let’s set LED 5 to be the XOR gate Output
It is possible to use the WebISE software to generate the constraints for us but I prefer to write my own code using the supplied constraints file from Numato Labs as a template.

Here is the code:

#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
# This file is a .ucf for Mimas V2                                 #
# To use it in your project :                                      #
# * Remove or comment the lines corresponding to unused pins in    #
# the 
project                                                      #

# * Rename the used signals according to the your project          #
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#

CONFIG VCCAUX = "3.3" ;
#NET "CLK" LOC = V10 | IOSTANDARD = LVCMOS33 | PERIOD = 100MHz;
#NET "RST_n" IOSTANDARD = LVCMOS33 | PULLUP;

#################################################################################
# DIP Switches                                                                  #
#################################################################################

NET "Not_input" LOC = C17 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | PULLUP;
NET "And_A_Input" LOC = C18 | IOSTANDARD = LVCMOS33 | DRIVE = 8SLEW = FAST | PULLUP;
NET "And_B_Input" LOC = D17 | IOSTANDARD = LVCMOS33 | DRIVE = 8SLEW = FAST | PULLUP;
NET "Or_A_Input" LOC = D18 | IOSTANDARD = LVCMOS33 | DRIVE = 8SLEW = FAST | PULLUP;
NET "Or_B_Input" LOC = E18 | IOSTANDARD = LVCMOS33 | DRIVE = 8SLEW = FAST | PULLUP;
NET "Xor_A_Input" LOC = E16 | IOSTANDARD = LVCMOS33 | DRIVE = 8SLEW = FAST | PULLUP;
NET "Xor_B_Input" LOC = F18 | IOSTANDARD = LVCMOS33 | DRIVE = 8SLEW = FAST | PULLUP;

#################################################################################
# LEDs                                                                          #
#################################################################################

NET "Not_Output_LED" LOC = P15 | IOSTANDARD = LVCMOS33 | DRIVE = 8SLEW = FAST;
NET "And_Q_Output_LED" LOC = N15 | IOSTANDARD = LVCMOS33 | DRIVE = 8SLEW = FAST;
NET "Or_Q_Output_LED" LOC = U17 | IOSTANDARD = LVCMOS33 | DRIVE = 8SLEW = FAST;
NET "Xor_Q_Output_LED" LOC = T17 | IOSTANDARD = LVCMOS33 | DRIVE = 8SLEW = FAST;

Copy and paste the above code into the constraints file and then Save the file! It's now time to check everything is correct and implement everything before creating a bit stream file and upload it to the Mimas V2....

Click on the green arrow in the process window to process all of the code. Once complete there should be green tick marks on each section:


Next right click on Generate Programming File and Process Properties and select create Binary Configuration file:


Click Ok and then Right click on Generate Programming file and select run:


Once that has completed - connect up the Mimas V2 development board to your computer and load up the Mimas V2 Config tool. Select the correct COM port and finally navigate to the recently created Bit Stream file called 'lots_of_gates_top_module.bin' and click Upload:


It may take a while...I hear that programming the Mimas V2 using a JTAG programmer is considerably faster! Once that has completed lets test it out!

Remember that the Mimas V2 Logic levels are active low. So the LEDS will be off when a logic '1' is present at the output.
  • If you manipulate DIP switch 8 - the D1 LED will change state
  • If you manipulate DIP switches 6 and 7 - the D3 LED will change state (AND function)
  • If you manipulate DIP switches 4 and 5 - the D5 LED will change state (OR function)
  • If you manipulate DIP switches 2 and 3 - the D7 LED will change state (XOR function)
The project uploaded to the Mimas V2 and working!
Well that's about it for now...Apologies for the really long post. I couldn't really find a way to make it much shorter. If you want to be adventurous change the code to have multiple NOT gates, or AND gates etc....it only requires changing the instantiation sections with a single component declaration, you will need to map the pins though.

If people need access to the project and files it's here:
https://drive.google.com/open?id=0B7fA8ZgAyKMlaHo5Qms2YjhtNW8

That's all for now people - take care, Langster!

Tuesday, 1 August 2017

Designing A USB Breakout Board!

I often need to intercept USB signals for decoding and measurement purposes.  I cut a cable apart last time I needed one but to be honest I much prefer doing things properly.  I also noticed that nobody seems to sell a similar product on Ebay, Aliexpress or Amazon!  I did find a vendor in the USA on tindie:


USB Inspector
Image Copyright - Misperry via Tindie

https://www.tindie.com/products/misperry/usb-inspector/?pt=full_prod_search

I also found this product on tindie which is similar but has a current monitoring circuit built in:

https://www.tindie.com/products/Kaktus/usbuddy-usb-development-tool/?pt=full_prod_search

A friend of mine and blog reader found this one:

https://friedcircuits.us/50?search=usb

Either of these products would work for my purposes but the first product's shipping costs from the USA seem a little extravagant and I only wanted one or two.

The second product uses pin headers to allow connection which are a bit close together for my liking. It's often the way of things.  When I cannot obtain what I want I make my own!

The circuit is very simple:


The PCB layout is a little more complicated.  I would like to keep the board as small as possible but maintain the recommended conductor impedance that a USB cable should have.  By maintaining the impedance it means that signals can be correctly measured and power is not needlessly wasted.  The USB specification document is possibly one of the hardest pieces of technical literature I have had to read.  I don't recommend it unless absolutely necessary:

http://www.usb.org/developers/docs/usb20_docs/#usb20spec

There is also a standard for USB cables which dilutes the information into a slightly more readable format (note - I am being overly sarcastic):

BS EN 62680-2-3:2015

The standard is not free to read however...but memberships to local and university libraries yields useful results.

A USB 2.0 cable must have many specifications but the two most critical that I am interested in are:

  • Cable impedance - 76.5 Î© to 103.5 Ω
  • Current carrying capability - 500 mA (standard) or 1.5 A from a dedicated charging port.

The information on the current carrying capability is confusing as there is mention of 5 amps on the wikipedia article:

https://en.wikipedia.org/wiki/USB#Power-use_topology

So based upon the above information we need to ensure the board layout has tracks capable of carrying 1.5 Amps of current at 5 Vdc and that the data pairs D+ and D- are routed as a differential pair with 90 ohms impedance.  I picked 90 ohms as a reasonable middle value and it was cited in this application note from Silicon Labs:

https://www.silabs.com/documents/public/application-notes/AN0046.pdf

Here is a useful article on layout guidelines for differential pairs:

http://www.eetimes.com/document.asp?doc_id=1144365

Basically I want to make sure my breakout board doesn't ruin the USB signals by interrupting them. USB cables are actually proper transmission lines and the cable should be screened and the internal cables twisted to maintain uniform impedance.  The D+ and D- tracks which are differential signals will need to be routed close together above a solid ground plane (Microstrip transmission line) ensuring that both tracks are exactly the same length.  Most PCB routing software like eagle have built in calculators and tools to assist with this.

Here is an excellent (and free) online trace width calculator:

http://www.4pcb.com/trace-width-calculator.html

I entered the following information into the calculator:

  • Current: 1.5 Amps (I'm going with the lower value specified)
  • Copper thickness: 35 µm (Standard 1 oz copper thickness for FR4 PCB material)
  • Temperature Rise: 10 °C (Just a guess)
  • Ambient Temperature: 25 °C (Just a guess)
  • Trace Length: 35 mm (just a guess for now)

I'm only going to have a two layer PCB so I'm only interested in external traces.  Here is what the calculator came up with:

  • Required Trace Width: 525.491 µm or 0.525491 mm
  • Resistance: 33.612 mΩ
  • Voltage Drop: 50.419 mV
  • Power Loss: 75.628 mW

So that sets the PCB track thickness to be at least 0.6 mm.  I may well go with 1 mm as space should not be a problem.

Next we need to set the track impedance above a ground plane which is otherwise known as a microstrip transmission line.  Here is another very useful (and free) calculator:

https://www.eeweb.com/toolbox/edge-coupled-microstrip-impedance

If people need to read up on what an edge coupled microstrip layout is then please check out the link below.  It is essentially a method of setting the impedance of PCB tracks based upon the thickness and width of the track, the thickness of the dielectric material (FR4 PCB) and Wheeler's Equation.

https://en.wikipedia.org/wiki/Microstrip

Transmission line theory is complicated and to be honest I have no intention of attempting to simplify it...I'm not sure that I could.  Basically this is some of the RF black magic people talk about.... I'm trying to keep things simple.  I would suggest that anyone who is serious about electronics and electrical signal propagation needs to have a basic understanding of transmission line theory and how to layout PCB tracks to properly interface connectors with circuits.

Here is what I fed into to the calculator:

Trace Thickness: 35 µm (Standard 1 oz copper thickness for FR4 PCB material)
Substrate Height: 1.6 mm (Standard FR4 PCB)
Trace Width: 1.5 mm (I chose 1 mm value above but went for 1.5 mm to get the right impedance)
Trace Spacing: 0.12 mm (I chose this value as a guess after trying a few different values)
Substrate Dielectric: 4 (This is the relative permittivity of FR4 PCB material)

The calculated result gives a differential impedance of 89.8 Ω - close enough!  So all that's needed is to set the D+ and D- tracks to be 0.12 mm apart and 1.5 mm thick and try to keep the tracks the same length...If we manage that we have the 89.8 Ω impedance needed to ensure that the USB signals remain unaffected when we use the PCB.

Now that we have all of the track properties calculated we can design the PCB layout.  There is a tool in Eagle for doing this that ensures that the differential tracks are routed together.  You have to label the net names with an 'underscore P' and an 'underscore N'.  I set the label for my D+ and D- nets to 'TEST_P' and 'TEST-_N' but any sensible names will do.  I then routed the +V and GND tracks manually and then set the autorouter to route the top layer.  I cannot seem to get the differential pair tool to work otherwise.  Here is what the board layout looks like:


Edit - I have updated the design after some valuable feedback from Aamir Ahmed Khan (Thank you!) - I did not remember to set the track separation distance in my original layout, I have rectified that and my calculations.  Here is the new and now hopefully correct layout.  (Note to self - I should not rush when designing PCB layouts and writing informative blog posts!).  I found the easiest way to do this was to set the grid to 0.2 mm spacing with the alternative at 0.1 mm and route the differential tracks by hand one after the other.  That enabled me to ensure the tracks were correctly separated and of the correct thickness.  I also set the ground plane isolation to be 0.2 mm to ensure the track on the bottom layer was correctly isolated...Lets see if this works!  I hope the PCB fabricators are able to etch the board for me with such precise track isolation...I can always run a scalpel down the gap though.

I will probably get the whole thing manufactured by Elecrow and for that I will need a bill of materials.

Qty Device Package Parts Vendor Part Number Description







1 USB 2.0 Socket USB X1 Farnell 2134385 AMP USB 2.0 connector
4 Ring_Test 1X01_LONGPAD +V, D+, D-, GND Ebay.co.uk 292175228920 Ring Test Connector
1 M02PTH3 1X02_LONGPADS JP7 Farnell 3418285 Standard 2-pin 0.1" header pins
1 USB 2.0 Connector USB-A-H JP1 Farnell 1696544 USB Connectors








Here is the PCB render:




My plan is to have ten boards made, keep two for myself and flog the rest!

That's all for now - Langster!

Monday, 24 July 2017

Having electronic breakout boards manufactured in China by Elecrow

I have an online shop where I sell some of the items I have designed and written about.  I normally have the PCBS made in china and then populate them and test them myself at my local hackspace or when I'm in a rush on the kitchen worktop - Note to young engineers: a surer method of annoying your significant other I have yet to find!

It is often quite stressful and difficult for me to hand solder surface mount components. I have to test and fault find the circuit and get everything working....after that shipping the orders in good time only compounds the issues.  It's all about being prepared and patient...I am not always good at being prepared and then my patience wears thin!

I get my PCBS made in China by a company called Elecrow:

https://www.elecrow.com/

They sell all sorts of useful bits and pieces for the electronics hobbyist and also have a PCB manufacturing service and now more recently a PCB assembly service.

I have had at least fifty PCBS made by Elecrow and the quality has always been excellent.  The price has always been acceptable and the service excellent.  I may have also quietly lost my temper with my ineptitude in assembling surface mount components on small printed circuit boards and decided to see how much it would actually cost to get the whole product made by Elecrow.

I saw the new service advertised on the site and clicked on the appropriate page:

https://www.elecrow.com/pcb-assembly-p-366.html

Next I uploaded the gerber files for the project in a zip file along with the bill of materials with at least two sources for the components and the package sizes.  Ensuring the design is correct and the bill of materials is correct is critical...I cannot stress this part enough!

The initial price I paid to have the project assessed and the printed circuit boards and solder stencil made was £32.05 or $41.76 USD. This all started on a Sunday night on the 23rd of June.

A very helpful lady named Shelley got in contact within a day to say the order had been received but production would not start as they couldn't open the bill of materials spreadsheet I had sent with the gerber files.  I made the mistake of not uploading the bill of materials in the Microsoft Excel format, very quickly resolved by resending the BOM in the correct file format.

Shelley got in contact within a few days to provide a quote for fitting the standard components or for fully populating the PCB.  The full cost was another £61.41 or $80 USD for ten fully completed PCBS which I thought was quite reasonable so I sent the money over and hoped for the best.

I also sent through some basic instructions and tips on how to populate the PCB gained from my own experience in doing it - I didn't want anyone else to struggle populating the PCBS like I had and I also wanted to be sure that when the boards arrived they worked first time!

On the 12th of July Shelley emailed to say that the boards had been manufactured and that component population was about to start.  She did say that they had issues with the Op-Amp I had chosen but this was sorted pretty quickly....luckily my circuit will work with just about any Op-Amp so I wasn't too worried.

On the 18th of July I got an email from someone named Sunshine to say that the my order was complete and shipped by DHL.  I didn't actually bother tracking it but it arrived today on the 24th of July, well packaged in a sturdy cardboard box and bubble wrap.  Each PCB was individually wrapped in a zip lock anti-static bag with some anti-static foam on the header pins.

Every single one of the boards worked perfectly.  Here are some photos of the PCB etc...I didn't take any of my smiling face!!!  The coin is a one pence sterling coin for scale.

Populated Pressure Sensors From Elecrow!
Check out the reflow soldering!

For the price (£93.46 or $121.76) I am very happy with the service that Elecrow provided and I will be getting more of these boards and other boards fully populated when I need to.  Shelley did say that If I get a higher quantity of PCBS made up the price quoted would reduce.  I just hope I manage to sell them all so that I can get more things made...maybe I should spend more time advertising over designing and blogging?!??

I doubt that I will ever sell enough of these to retire but I do enjoy keeping my hand in the manufacturing process - it is very useful to know how to get things made and if I ever do come up with a cunning plan...I mean product I can realise it fairly quickly and efficiently with Elecrow's help.

That's all for now - Langster!



Wednesday, 21 June 2017

Myoware muscle sensor circuits from Sparkfun and others....

It's been a while since I wrote anything up and to be honest with you I haven't had much time or inclination to do any electronics outside of work....it gets that way sometimes.

Here is the previous post on this project for those that are following along:

http://langster1980.blogspot.co.uk/2017/05/graphing-data-from-venturi-tube.html



MyoWare Muscle Sensor
I received in the post a Myoware EMG (Electromyography) sensor kit available from Sparkfun and other vendors.  The webpage for the product is shown below:

https://www.sparkfun.com/products/13723

The idea with this circuit is to sense muscle movement when a person breathes in and out and from that correlate lung function.  How much air a person can breathe in and out is partly to do with muscle (diaphragm) and chest movement - I'm not a medical doctor so I'm a little out of my depth here...however it was part of the functionality requested for the medical device so I'm investigating solutions and this circuit is one solution.  Lets see how well it works and get some data and compare it to what would be expected.  As a healthy male of some 30+ years (in my prime!) it should show that I'm a paragon of excellence...in reality I suspect it will show that my heart and muscle function are average but more importantly present!

Here are the instructions for use:

https://github.com/AdvancerTechnologies/MyoWare_MuscleSensor/blob/master/Documents/AT-04-001.pdf

The board itself is very simple to setup and use and the instructions are clear and concise.

This is the setup I'm going with...I'm certain there shouldn't be any issues but I don't have the buffer circuit so...it's time to man up!

I have attached the red sensor wire and blue sensor wires to electrode pads and put them on my sternum at either side of my heart.  I attached the black wire to an electrode pad and placed that on my stomach to provide a base reference.  I'm looking to measure my hearts sinus rhythm...and see how sensitive things are.  Here is the test code I've written:

(I had both the raw and sig output connected to my arduino analogue inputs A0 and A1)

//test code for Myoware EMG PCB

// variables for input pin from MyoWare PCB
int analogInputSig = A0;
int analogInputRaw =A1;

// variables to store the values
int valueSig = 0;
int valueRaw = 0;

void setup() {
  
  pinMode(analogInputSig, INPUT);
  pinMode(analogInputRaw, INPUT);

  // begin sending over serial port
  Serial.begin(9600);
}

void loop() {

  // read the values from the sensor:
  valueSig = analogRead(analogInputSig);
  valueRaw = analogRead(analogInputRaw);

  //print the reading received
  Serial.print(valueSig);
  Serial.print(",");
  Serial.print(valueRaw);
  Serial.println();

  // wait for a bit to not overload the port
  delay(10);
}

Here is the serial output graphed for your viewing pleasure:



Here is my wife's heart rate...apparently I don't have quite the effect on her I used to!



Here is what happens when the sensors are placed on the abdomen:


So...I'm alive and so is the wife!  The Myoware picks up a good strong electrical signal when sensors are placed close to the heart...but when placed on the abdomen did not really pick up anything I could see correlating to breathing or diaphragm movement.  Either I had my sensors incorrectly placed or the circuit is not sensitive enough for this purpose.  Adjusting the gain potentiometer on the Myoware PCB did change the gain response but didn't provide the response I was looking for - It was hoped that it would be possible to correlate diaphragm muscle movement with regular breathing.

I did notice that if I activated (flexed) my abdmoninal muscles electrical signals were definitely present and well detected...maybe I don't use my diaphragm much when I breathe in and out?  I will have to investigate further.

I could not find a schematic diagram for the Myoware circuit although the shields are marked as being open source. Update - See comments below from Brian Kaminsky of Advancer Technologies.

Here is the schematic for the previous version of the device:

https://cdn.sparkfun.com/datasheets/Sensors/Biometric/Muscle%20Sensor%20Platinum%20v3.3.pdf

The main integrated circuit is an AD8648 which is a quad operational amplifier.  I suspect the two smaller devices are programmable gain devices for each of the sensor inputs and the rest of the components are associated gain and filtering requirements.

Here is the datasheet for the AD8648

http://www.analog.com/media/en/technical-documentation/data-sheets/AD8646_8647_8648.pdf

Here is the datasheet for the devices marked AD A 1V (An AD 628 I think....)

http://www.analog.com/media/en/technical-documentation/data-sheets/AD628.pdf

The company (Advancer Technologies) that developed the Myoware PCBs also wrote this instructable which shows how a similar circuit could be developed:

http://www.instructables.com/id/Muscle-EMG-Sensor-for-a-Microcontroller/

I have seen similar circuits in the past and believe this is certainly one route to achieving the measurement of electrical signals either from the heart (ECG - ElectroCardioGrapy) or muscle movement (EMG - ElectroMyoGraphy).

I would certainly say that this circuit has been very well designed and implemented and would be very useful if one wanted to use muscle flexing signals to control an external device or detect when someone has used a muscle...so say for instance you wished to mirror your arm movement with a robotic arm then this is definitely the circuit for the job!

That is all for now - take care always, Langster!

Thursday, 8 June 2017

Tutorial for Xilinx DCM Clock Generator with the Mimas V2

A blog reader contacted me recently for help generating signal clock sources with the Mimas V2.  In particular they wanted a 108 MHz clock for HDMI purposes however the Spartan 6 FPGA on the Mimas V2 is capable of generating source clocks up to 1 GHz if the output is used to drive a BUFPLL.  What this means is that the clock will be generated but in order to work special internal routing is required within the FPGA.  It is a topic for another post to be honest.  For now lets only generate clocks up to 400 MHz

The datasheet for the the Spartan 6 FPGA devices is available below:

https://www.xilinx.com/support/documentation/data_sheets/ds162.pdf

Rather than write a lot of VHDL code to generate the clocks we need we are going to use a feature of Xilinx WebISE 14.7 to write the code for us - cool huh.

Lets set some parameters!  Lets generate a 200 MHz clock and send it to one of the output pins and then view this on an oscilloscope or logic probe.  If people are interested the instruction manual for the DCM clock generator is here:

DCM Clock Generator Manual

Lets fire up Xilinx WebISE and start a new project:


Choose to save the project in a suitable location on your hard disk and give the project a suitable name - I called mine DCM_Clock_Tutorial but any sensible name will do:


Click Next when ready.

Make sure all the settings are the same as in the image below - these are the settings required for the FPGA device on the Mimas V2:


Click Next when ready to display the project summary page:


And finally click Finish to return to the main project screen:

 Now right click on the design hierachy window and select add source:


Select VHDL module and give the file a suitable name, I called mine DCM_Clock_Top_Module but another name could be used.  It should be something sensible however:


Click Next to continue and add the inputs and outputs.  I have chosen to add a signal called CLK as an input and a signal called CLKOUT_200M as an output.  If we wanted to we could leave this screen blank and write our own code later.


Click Next to continue and display the summary screen:


Click finish to return to the main project window and see the automatically generated code:


I prefer to delete most of the comments as they don't add any value at this point however...they can be left or completed if required.

At this point it is always a good idea to save things.

We will return to write VHDL code here later but for now lets add another new source, this time select IP (Core Generator and Architecture Wizard) and give the file a suitable name:


Click Next when ready and then wait for WebISE to load up all of the available IP cores for the Spartan 6 family:


Type Clock into the search field:


Click Next when ready:


Click Finish and wait for WebISE to build the code and load the wizard.

Make sure the settings are as shown below:


The options selected are for the Mimas V2 which has a 100 MHz source clock.  We have also chosen to reduce jitter which should make the clock more accurate and we have decided to let WebISE select the most applicable mode for us - Click Next when ready to continue:


Ensure the same settings have been selected and click Next when ready.


Ensure the settings are the same as above and click Next when ready - for this tutorial we don't need a reset input or locked input.


These are the IO functions which will be automatically created by the wizard when the code is generated.  Click Next when ready.



These are the names that will be used for the input clock signals and output clock signals - Click Next when ready.


Click Generate when ready and wait until the code has been generated.


Now here is where we could do things in multiple ways.  We could add code to the VHDL module or we can take advantage of WebISE and have it write the code for us...I'm going to take the easy option.  Click on the newly created ClockMultiplier200M module in the Hierachy Window and then expand the CORE Generator process icon and select View HDL Instantiation Template:


Open the file and scroll down to line 67:


Select and copy the VHDL code from line 67 to line 76:



Paste this code into the VHDL top module code at line 11 in the header of the architecture function:


Now return to the HDL Instantiation Template and select the code on line 82 to line 89 and copy it. Then paste that code into the top module code on line 22 between the begin and end Behavioural lines:


Go to line 22 and change the text 'your_instance_name to something sensible, I typed clockMultiplier:


Next we need to modify the code so that the port map section connects to the inputs and outputs in the Entity section:


Next we need to generate the implementation constraints file.  Right click on the hierarchy window and select Add new source like before:


Click Next when ready.


Click Finish when ready.

We need to create the implementation constraints code specifically for the Mimas V2.  I tend to use the original supplied by Numato Labs and then modify it to suit our purposes.  Copy and paste the code below into the text editor in WebISE:


#******************************************************************#
#                          UCF for Mimas V2                        # #                                                                  #
#******************************************************************#

CONFIG VCCAUX = "3.3" ;

NET "CLK" LOC = V10  | IOSTANDARD = LVCMOS33 | PERIOD = 100MHz ;

NET "CLKOUT_200M"  LOC = T10  | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST | OUT_TERM = UNTUNED_50 ; #Pin 4

The above code tells the 'compiler' that the CLK input from the 100 MHz crystal oscillator is connected to pin V10 and that we would like to use pin T10 as the 200 MHz output pin on P8 pin 4. The pin has been set to provide a 50 Ohm output impedance.  I chose the T10 pin as according to the information in ug381.pdf (The DCM Clock Manager Manual) this pin - GCLK2 is a global clock pin location.


I chose to set the impedance to 50 ohms so that it can be properly measured with an oscilloscope.

Lets save our work and upload it to the FPGA - Click on the implement top module arrow button and then after those processes are complete create a bitfile.  Navigate the to folder where the project was stored and locate the newly created bitfile!  Then load up the MimasV2 Configuration tool and connect up your Mimas to your PC.  Select the appropriate COM port and then....

Then upload it to the Mimas V2 development board:


Once uploaded Pin 4 of the output Bank P8 should have a clock signal on it which can be viewed with an oscilloscope or logic probe.  In truth these clock signals are designed to be used internally within your FPGA design and not brought out to a pin.  The signal won't be particularly square or have a a fast rising edge.

Here is a photo I took of a signal from the FPGA measured with an oscilloscope - it looks more like a sine wave!


That's all for now - Langster




Tuesday, 9 May 2017

Graphing the Data from the Venturi Tube

In the previous post I wrote about how I 3D printed a venturi tube and updated the code with new constant values.  At the end of the post I was looking for a way to display the data graphically live.

I think I have managed it!  The previous post for those that are interested is here:

http://langster1980.blogspot.co.uk/2017/05/making-venturi-tube.html

I had been researching Python scripting and whilst this is possible I don't have the time, patience or inclination to learn another programming language - there is only so much room in my head for information!  Perhaps I will learn Python in the future and being aware of it and it's function will probably serve me well.

I was browsing through you tube and google looking for programs which graph serial data automatically from comma separated values.  I specifically made sure that the data sent out to the serial port from the arduino was comma separated...it makes it easy to import into a spreadsheet program and graph.  I would like to be able to do that real time as well.

In my searching I found this video:

https://youtu.be/yYyW16FYqE0

It describes a java applet which has been written to graph serial data directly from the arduino - just what I was looking for!  The video itself explains how to use it quite simply so I won't bother. Sufficed to say all one needs to do is select the appropriate COM port and baud rate and then complete the form with the required information and units and the graph will be displayed.

The java applet can be downloaded from here:

http://farrellf.com/TelemetryViewer/T...

If you haven't got Java installed that will be needed also:

https://java.com/en/download/

Once everything is installed I would watch the video and learn how to use the applet.  The help button is quite useful! Here are the results:


Here is another screenshot:


Which is very close to the example image given when this project was first specified:

Displaying image.png

As this part of the project is almost complete, I'm going to move on to the next section which was to measure the pressure output from the ventilator using one of my pressure sensor breakout boards - not too hard to add hopefully. After that it's develop a EMG measurement circuit.

Along the way I think it might be useful to add a microSD card to log the data received along with a real time clock and finally use bluetooth communications to provide wireless serial communications. It's also time to consider powering the system - I'm looking at using 18650 lithium cells and a suitable charging circuit with protection.  After than design an enclosure and add some LEDS to show function and this project can be marked complete!  Not too far now!!!!

Take care always - Langster!