Wednesday, February 24, 2021

A hardware design for variable output frequency using an n-bit counter

The
Novel Fibonacci and non-Fibonacci structure in
the sunflower: results of a citizen science
DE1-SoC
from Terasic is a great board for hardware design and prototyping. The following code snippet is from a hardware design that I created and wrote in VHDL for the DE1-SoC.  The 10 switches and four buttons on the board are used as an n-bit counter with an adjustable multiplier to increase the output frequency of one or more output pins at a 50% duty cycle.  

As the switches are moved or the buttons are pressed, the seven-segment display is updated to reflect the numeric output frequency, and the output pin(s) are driven at the desired frequency.  The on-board clock runs at 50MHz and the signal on the output pin(s) is triggered on the rising edge of the clock input signal (positive edge triggered) so the output pin(s) can be toggled at a maximum rate of 50 million cycles per second or 25 million rising edges of the clock per second. In other words, an LED attached to one of the output pins would blink 25 million times per second, which is not recognizable to the human eye.


          
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

- - --Copyright (C) 2021. Bryan Hinton
- - --All rights reserved.
- - --
- - --Redistribution and use in source and binary forms, with or without
- - --modification, are permitted provided that the following conditions
- - --are met:
- - --1. Redistributions of source code must retain the above copyright
- - --   notice, this list of conditions and the following disclaimer.
- - --2. Redistributions in binary form must reproduce the above copyright
- - --   notice, this list of conditions and the following disclaimer in the
- - --   documentation  and/or other materials provided with the distribution.
- - --3. Neither the names of the copyright holders nor the names of any
- - --   contributors may be used to endorse or promote products derived from this
- - --   software without specific prior written permission.
- - --
- - --THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- - --AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- - --IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- - --ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- - --LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- - --CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- - --SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- - --INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- - --CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- - --ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- - --POSSIBILITY OF SUCH DAMAGE.
when 9 =>
            segment_vector := "0011000"; ---9
            when others =>
            segment_vector := "1111111"; --
            end case;
        return segment_vector;
end function get_7_segment_vector;

- -- BEGIN ARCHITECTURE
begin

scaler <= compute_prescaler((to_integer(unsigned( SW )))*scaler_mlt);

- --led off -> 25m pulses -> led on -> 25m pulses / 50% duty cycle
gpiopulse_process : process(CLOCK_50, KEY(0))
begin
    if (KEY(0) = '0') then  -- asynchronous reset
            count <= 0;
    elsif rising_edge(CLOCK_50) then
        if (count = scaler - 1) then
            state <= not state;
            count <= 0;
        elsif (count = clk50divider) then -- automatic reset
            count <= 0;
        else
            count <= count + 1;
        end if;
    end if;
end process gpiopulse_process;
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEEhwq5gb3EVpTtl/3gjYtliwzjQIcFAmA24TQACgkQjYtliwzj
QIe+mRAApc9EepxD3aphtSFn74uPocXkz7ol4l0fHfRwSoWtMuittnTo43smXjeI
zWLYhtqeijm4lzNfTQnv5eIpXMtiBNOOHgW7upqCg8v8H4e16SFpVtbwzM7Kmii0
gx3kDXwfTDjqvPgcpOwAAFV9aVwbOCdbrYlBNa9gbcY61rdclt7z/dnoiVWo1+oU
Yvl4MpVpjO2Zi7uqpZH1Qk2wThbAIOpAFbwXgvDs0c5LK3AVB7v/5uWtObbtCLsZ
a0EPyD5Jfq4hmkhUH8tAj0ba+uc/3IrT1ye8rllvUyPrmDKAW68VwCl4Iy5kCR2g
h4c+s3J87cZabkhFJVyYeQyOitK2xO1Bx3hAst5SFx9WmUP5yxtdt4PVTohnWsTu
wgVkqD0FxrqnXgP3sVm0sSoFVDzV2Ll0Md9cH9sdrev8xXLK9nFi+hgy34DlRZOd
0kZQWhg29j1dAru2OZ5OFNkjCl2a66l8dmFJkWJ9NS0JPJv84QX+nP7JCduYxS1b
hUawypHPHICsLeRw+bQJj2tOJfZW6aKQ7kOcXxFNVg3vyZD4sP0z5xe3shaZUXr6
aD//W0LPxxODhdJaINfhzMBRoS2ot6M2Dpux8tHcO2/ChSvFWqPvfW88RUfJPTZy
sqnNZUsPOLygFyLtiohcfHPCW0FNC0CnTYVAGi/AFtnx+T8NA24=
=wL8W
-----END PGP SIGNATURE-----

Wednesday, February 17, 2021

Vim for programming and systems administration

Computer pioneer, Bill Joy, created the Vi text editor.  Vi has made its way onto nearly every UNIX and Linux computer and is used by kernel developers, system administrators, programmers, and users.  The learning curve is steep; however, its efficiency pays off over time.  One hour per day for five to six years digging through kernel source code with ctags will allow you to become proficient with the editor. If you are already a C programmer and can work from the terminal quickly, then picking up Vi should be easy for you.  My notes below describe how to setup VIM, a fork of Vi that includes features such as color syntax highlighting.




For the non-programmer, having Vi handy on a terminal means easily modifying any readable file on a UNIX system from the terminal - including log files and tcpdump log file snippets.  Quickly setting up snort config files, copying public and private keys between files on servers, configuring build systems, and modifying /etc/hosts and resolv.conf can easily be done with Vim. 

Running make tags from the top level Linux kernel source tree will build the ctags file over the Linux kernel source. Alternatively; man ctags will show you how to recursively run ctags over your source code.
Nerd Tree and Taglist are two useful plugins that can be downloaded from vim.org.  
Once NERD tree and Taglist are placed in ~/.vim/plugin/, the following lines in your .vimrc will allow you to use 

<ctrl-n> and <ctrl-m> to toggle the file explorer and visual tag list.
nmap <silent> <c-n> :NERDTreeToggle<CR>
nnoremap <silent> <c-m> :TlistToggle<CR>

Vim should be good to go at this point. cd back into your source code directory and begin work.  Finally, man vim will tell you more about how to use the editor.

Enter g?g? in command mode on the current line of text.and Vim will perform a rot13 encryption of the text.

In conjunction with Vi, od and/or hexdump (if installed) can be used for examining binaries on different flavors of UNIX.

Thursday, February 1, 2018

a Hardware Design for XOR gates using sequential logic in VHDL

Hybrid boards with ARM processors integrate FPGAs with multicore ARM processors over high speed buses.  The ARM processor is termed the hard processor system or HPS.  Writing to the FPGA from the ARM processor is typically performed via C from an embedded Linux build (yocto or buildroot) running on the ARM core.  A simple bitstream can also be loaded into the FPGA fabric without using any ARM design blocks or functionality in the ARM core.

ModelSim Wave Output for the xor design
ModelSim Wave Output for the xor design
The following is a simple hardware design that I wrote in VHDL and subsequently simulated in ModelSim.  The HPS is not used. The bitstream is loaded into the FPGA fabric on boot.  The sequential design is comprised of several XOR gates, XNOR'd together with a 50Mhz input clock. XOR gates are common in cryptography.  VHDL components are utilized and a testbench is defined for testing the design.  The testbench for the design was loaded into ModelSim and the below image is the wave form simulation of the input signals, clock, and output signal.  The source code is available on github.

ModelSim Full Window view with wave form output of xor simulation. ModelSim-Intel FPGA Starter Edition © Intel
ModelSim Full Window view with wave form output of xor simulation. ModelSim-Intel FPGA Starter Edition © Intel


Monday, August 15, 2016

Debugging Multithreaded / Multiprocess Applications on the DE0-Nano-SoC with ARM DS-5

ARM DS-5 is an ideal platform for debugging multithreaded, multiprocess applications on ARM Powered® development boards that run the GNU/Linux operating system.  The DE0-Nano-SoC is an ideal reference platform for developing multithreaded, multiprocess applications in Linux user space.  Yocto provides an easy to use platform for building a bootable image and ARM® DS-5 easily integrates with the board for efficient debugging.  Altera packages a version of ARM DS-5 for the DE0-Nano-SoC.



The following requirements were in place for this project.

  • Use course-grained locking strategy. Only lock data.
  • Minimize critical sections.
  • Fork five processes, all of which are attached to the controlling terminal.
  • Create three threads in one of the five processes.
  • Two of the threads will simulate packet processing.
  • One of the threads will generate packets in a buffer.
  • Properly utilize synchronization primitives and mutex locks.
  • Maximize concurrency.
  • Minimize latency.
  • Ensure order of context switching is always random upon execution - i.e. don't control the scheduler.
  • Utilize ARM DS-5 for building and debugging the application on the attached de0-Nano-SoC FPGA.
  • Use autotools for building a shared library and link against the library with a driver program in DS-5.
  • Compile the shared library and driver program using the Linaro GCC ARM-Linux-GNUEABI Hard Float toolchain version 4.8 that is included in the Altera DS-5 download.
  • Compile the shared library and test program using the Linaro GCC ARM-Linux-GNUEABI Hard Float toolchain version 5.3 (latest stable from Linaro as of 08/15/16).
  • Debug the multiprocess, multithreaded application using both toolchains from DS-5.
  • Ensure that all possible errors from calls to pthread functions and other libc functions are properly handled.


DS-5 disassembly / memory analysis - debugging multithreaded, multiprocess applications on ARM Powered boards

DS-5 Debug Configurations - Files


DS-5 Autotools Configure Settings

DS-5 Toolchain Editor
DS-5 Toolchain Editor


Saturday, July 30, 2016

Concurrency, Parallelism, and Barrier Synchronization - Multiprocess and Multithreaded Programming

Concurrency, parallelism, threads, and processes are often misunderstood concepts.

On a preemptive, timed sliced UNIX or Linux operating system (Solaris, AIX, Linux, BSD, OS X), sequences of program code from different software applications are executed over time on a single processor.  A UNIX process is a schedulable entity.   On a UNIX system, program code from one process executes on the processor for a time quantum, after which, program code from another process executes for a time quantum.  The first process relinquishes the processor either voluntarily or involuntarily so that another process can execute its program code. This is known as context switching.  When a process context switch occurs, the state of a process is saved to its process control block and another process resumes execution on the processor.  Finally, A UNIX process is heavyweight because it has its own virtual memory space, file descriptors, register state, scheduling information, memory management information, etc.  When a process context switch occurs, this information has to be saved, and this is a computationally expensive operation.

Concurrency refers to the interleaved execution of schedulable entities on a single processor.  Context switching facilitates interleaved execution.  The execution time quantum is so small that the interleaved execution of independent, schedulable entities, often performing unrelated tasks, gives the appearance that multiple software applications are running in parallel.

Concurrency applies to both threads and processes.  A thread is also a schedulable entitity and is defined as an independent sequence of execution within a UNIX process. UNIX processes often have multiple threads of execution that share the memory space of the process.  When multiple threads of execution are running inside of a process, they are typically performing related tasks.

While threads are typically lighter weight than processes, there have been different implementations of both across UNIX and Linux operating systems over the years.  The three models that typically define the implementations across preemptive, time sliced, multi user UNIX and Linux operating systems are defined as follows: 1:1, 1:N, and M:N where 1:1 refers to the mapping of one user space thread to one kernel thread, 1:N refers to the mapping of multiple user space threads to a single kernel thread, and M:N refers to the mapping of N user space threads to M kernel threads.

In summary, both threads and processes are scheduled for execution on a single processor.  Thread context switching is lighter in weight than process context switching.  Both threads and processes are schedulable entities and concurrency is defined as the interleaved execution over time of schedulable entities on a single processor.

The Linux user space APIs for process and thread management are abstracted from alot of the details but you can set the level of concurrency and directly influence the time quantum so that system throughput is affected by shorter and longer durations of schedulable entity execution time.

Conversely, parallelism refers to the simultaneous execution of multiple schedulable entities over a time quanta.  Both processes and threads can execute in parallel across multiple cores or multiple processors.  On a multiuser system with preemptive time slicing and multiple processor cores, both concurrency and parallelism are often at play.  Affinity scheduling refers to the scheduling of both processes and threads across multiple cores so that their concurrent and often parallel execution is close to optimal.

Software applications are often designed to solve computationally complex problems.  If the algorithm to solve a computationally complex problem can be parallelized, then multiple threads or processes can all run at the same time across multiple cores.  Each process or thread executes by itself and does not contend for resources with other threads or processes that are working on the other parts of the problem to be solved. When each thread or process reaches the point where it can no longer contribute any more work to the solution of the problem, it waits at the barrier.  When all threads or processes reach the barrier, the output of their work is synchronized, and often aggregated by the master process.  Complex test frameworks often implement the barrier synchronization problem when certain types of tests can be run in parallel.

Most individual software applications running on preemptive, time sliced, multiuser Linux and UNIX operating systems are not designed with heavy, parallel thread or parallel, multi-process execution in mind.  Expensive, parallel algorithms often require multiple, dedicated processor cores with hard real time scheduling constrains.  The following paper describes the solution to a popular, parallel algorithm; flight scheduling.

Last, when designing multithreaded and multiprocess software programs, minimizing lock granularity greatly increases concurrency, throughput, and execution efficiency.  Multithreaded and multiprocess programs that do not utilize course-grained synchronization strategies do not run efficiently and often require countless hours of debugging.  The use of semaphores, mutex locks, and other synchronization primitives should be minimized to the maximum extent possible in computer programs that share resources between multiple threads or processes.  Proper program design allows for schedulable entities to run in parallel or concurrently with high throughput and minimum resource contention, and this is optimal for solving computationally complex problems on preemptive, time scliced, multi user operating systems without requiring hard real time scheduling.

After a fairly considerable amount of research in the above areas, I utilized the above design techniques for several successful, multi threaded and multi process software programs.

Thursday, June 30, 2016

VHDL Processes for Pulsing Multiple GPIO Pins at Different Frequencies on Altera FPGA

DE1-SoC GPIO Pins connected to lower power test diodes and Oscilloscope

The following VHDL processes pulse the GPIO pins at different frequencies on the Altera DE1-SoC using multiple Phase-Locked Loops.   Several diodes are connected to the GPIO banks and pulsed at a 50% duty cycle with 16mA across 3.3V.  Each GPIO bank on the DE1-SoC has 36 pins. Pin 1 is pulsed at 20hz from GPIO bank 0, and pins 0 and 1 are pulsed at 30hz from GPIO bank 1.  A direct mode PLL with locked output was configured using the Altera Quartus Prime MegaWizard.  The PLL reference clock frequency is set to 50mhz, the output clock frequency is set to 50mhz, and the duty cycle is set to 50%.  The pin mappings for GPIO banks 0 and 1 are documented on the DE1-SoC datasheet.

Pulsed GPIO pins with low-power diodes attached via breadboard on DE1-SoC FPGA


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

- --Copyright (C) 2016. Bryan R. Hinton
- --All rights reserved.
- --
- --Redistribution and use in source and binary forms, with or without
- --modification, are permitted provided that the following conditions
- --are met:
- --1. Redistributions of source code must retain the above copyright
- --   notice, this list of conditions and the following disclaimer.
- --2. Redistributions in binary form must reproduce the above copyright
- --   notice, this list of conditions and the following disclaimer in the
- --   documentation  and/or other materials provided with the distribution.
- --3. Neither the names of the copyright holders nor the names of any
- --   contributors may be used to endorse or promote products derived from this
- --   software without specific prior written permission.
- --
- --THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- --AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- --IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- --ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- --LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- --CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- --SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- --INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- --CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- --ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- --POSSIBILITY OF SUCH DAMAGE.

- ---------------------
- -- CLOCK A PROCESS --
- ---------------------
- -- INPUT: direct mode pll with locked output 
- -- and reference clock frequency set to 50mhz, 
- -- output clock frequency set to 50mhz with 50% duty 
- -- cycle and output frequency scaled by freq divider constant
- -------------------------------------------------------------
clk_a_process : process (lkd_pll_clk_a)
begin
 if rising_edge(lkd_pll_clk_a) then
  if (cycle_ctr_a < FREQ_A_DIVIDER) then
   cycle_ctr_a <= cycle_ctr_a + 1;
  else
   cycle_ctr_a <= 0;
  end if;
 end if;
end process clk_a_process;
 
- ---------------------
- -- CLOCK B PROCESS --
- ---------------------
- -- INPUT: direct mode pll with locked output 
- -- and reference clock frequency set to 50mhz, 
- -- output clock frequency set to 50mhz with 50% duty 
- -- cycle and output frequency scaled by freq divider constant
- -------------------------------------------------------------
clk_b_process : process (lkd_pll_clk_b)
begin
      if rising_edge(lkd_pll_clk_b) then
  if (cycle_ctr_b < FREQ_B_DIVIDER) then
   cycle_ctr_b <= cycle_ctr_b + 1;
  else
   cycle_ctr_b <= 0;
          end if;
     end if;
end process clk_b_process;
 
- ---------------------
- -- GPIO A PROCESS --
- ---------------------
- -- INPUT: direct mode pll with locked output
- --------------------------------------------------------- 
gpio_a_process : process (lkd_pll_clk_a)
begin
 if rising_edge(lkd_pll_clk_a) then
         if (cycle_ctr_a = 0) then
   -- toggle gpio pin1 from gpio_0
   gpio_sig_0(1) <= NOT gpio_sig_0(1);
          end if;
       end if;
end process gpio_a_process;

- ---------------------
- -- GPIO B PROCESS --
- ---------------------
- -- INPUT: direct mode pll with locked output
- ---------------------------------------------------------
gpio_b_process : process (lkd_pll_clk_b)
begin
 if rising_edge(lkd_pll_clk_b) then
         if (cycle_ctr_b = 0) then
   -- toggle gpio pins 0 and 1 from gpio_1
   gpio_sig_1 <= NOT gpio_sig_1(1 downto 0);
          end if;
       end if;
end process gpio_b_process;
 
GPIO_0 <= gpio_sig_0;
GPIO_1 <= gpio_sig_1;

end gpioarch;
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBAgAGBQJXX2UDAAoJEPbndIT4b5KAnYYP/RgR8RGP7JPgC6CIO+gCQxe7
QXrRV7ea9vZCSuF5stCVY1UbEOfSv2jcufUc5Bg12Ddi+d9NLLPJa4/jL+ZRtwet
G+sIGcmxmviBReQCU6zVWOyPBzwoD3EJJdkHf1KtZUmq3pJKNsYefKzqIyzfhJ3t
mOtShH1mCMqxA4RD8wqfGmA1V1U3kOGd3APWnby1MKvbWaDLbNptZLovtweaw3F5
zgNDOMdCwFZpMScVHCW2tiZyoFHnMyhPes7uaBgj3CAQLRgIVKr7jUnU6HIWh4Ag
6be78TT22Zmf32+udQHzKjKcoYpMVatuBX6zY+sJ8jY92PypDi7u0wtHt+G3Hrht
XUW69s3tjR4JWw4qFX+JSYl8b2sEzDEeGAMJeB9r0+mCUH5C3f1cNWp5k1Rsne3z
3djluxQJzzZ+icvYrVz50sQyzqx1TCNJIW7tY3Va5kjF/jmH7ubbGP9YkPy5uoKt
ZNyI971A4KC5haov4PiRA8J7aUG+hNkhadY1YI8AIoP5zlk1im7vahE44SVA777r
ATLj64gzHoVdOSsEqY9ju68XBNvLDWeyN4u4AQD/yiW+9dnD324q3jan9Vx+6jWX
Y6LYmR/6HOPb7yPGw/4W11oDZ3RwfnBCrmuUYzYWC2Y0NuDebrskzTM2tXXU3gyq
qUWJiP6qmL/nsf72nBa1
=nJWe
-----END PGP SIGNATURE-----


DE1-SoC GPIO Bank 0 Pin 1


Thursday, June 2, 2016

FPGA Audio Processing with the Cyclone V Dual-Core ARM Cortex-A9

The DE1-SoC FPGA Development board from Terasic is powered by an integrated Altera Cyclone V FPGA and ARM MPCore Cortex-A9 processor.  The FPGA and ARM core are connected by a high-speed interconnect fabric so you can boot Linux on the ARM core and then talk to the FPGA.

The below configuration was built from the Terasic Design Reference sources.

The DE1-SoC board below has been programmed via Quartus Prime running on Fedora 23, 64-bit Linux.  The FPGA bitstream was compiled from the Terasic Audio codec design reference.  After the bitstream was loaded on to the FPGA over the USB blaster II interface, the NIOS II command shell was used to load the NIOS II software image onto the chip.  A menu-driven, debug interface is running from a terminal on the host via the NIOS II shell with the target connected over the USB Blaster II interface.


A low-level hardware abstraction layer was programmed in C to configure the on-board audio codec chip.  The NIOS II chip is stored in on-chip memory and a PLL driven, clock signal is fed into the audio chip. The Verilog code for the hardware design was generated from Qsys.  The design supports configurable sample rates, mic in, and line in/out.


Additional components are connected to the DE1-SoC board in this photo.  The Linear DC934A (LTC2607) DAC is connected to the DE1-SoC and an oscilloscope is connected to the ground and vref pins on the DAC.

The DC934A features an LTC2607 16-Bit Dual DAC with i2c interface and an LTC2422 2-Channel 20-Bit uPower No Latency Delta Sigma ADC.

3.5mm audio cables are connected to the mic in and line out ports, respectively.  The DE1-SoC is connected to an external display over VGA so that a local console can be managed via a connected keyboard and mouse when Linux is booted from uSD.

With GPIO pins accessible via the GPIO 0 and 1 breakouts, external LEDs can be pulsed directly from the Hard Processor System (HPS), FPGA, or the FPGA via the HPS.