Up until this point you have made different hardware designs to achieve a number of features. These features will be used in the board as it functions as Christmas light.
Before going to a processor or communication, things needs to be fixed. The most important thing, from a hardware point of view, is the interface. The following features will need to be present:
The configuration which will be applied to your PYNQ Z2, eventually, will come through communication. For now, you will prepare it for communication with a processor. As we all have to agree on the interface and the commands the following is proposed:
The 8 rightmost bits (bits 7 downto 0) have an effect on the LEDs. The most-significant nibble (7 downto 4) selects the affected LED(s), while the least-significant nibble selectes the affected pattern. The LED selection is one-hot coded, the pattern is binary coded.
bit | description | argument |
---|---|---|
3-0 | blank the selected LED(s) | “0000” |
drive the selected LED(s) | “0001” | |
blink the selected LED(s) | Frequency = 2(nibble % 4) Hz | |
4 | LED 0 | see 3-0 |
5 | LED 1 | see 3-0 |
6 | LED 2 | see 3-0 |
7 | LED 3 | see 3-0 |
The next-to-last 10 bits (bits 17 downto 8) have an effect on the RGB LEDs. The 6 most significant bits select the affected RGB LED(s), while the least-significant nibble selectes the affected pattern. The selection is one-hot coded, the pattern is binary coded.
bit | description | argument |
---|---|---|
11-8 | duty cycle | “0000” = 0%, “1111” = 100% |
12 | red on RGB LED 0 | see 11-8 |
13 | green on RGB LED 0 | see 11-8 |
14 | blue on RGB LED 0 | see 11-8 |
15 | red on RGB LED 1 | see 11-8 |
16 | green on RGB LED 1 | see 11-8 |
17 | blue on RGB LED 1 | see 11-8 |
The commands are explained above. A few example are given here.
As you can see from the examples above, the commands can have one single effect, or can have multiple effects. This allows us configure the lights more finely grained. If you would want to recreate exercise 4, you would have to send four commands: 0x1C, 0x2D, 0x4E, 0x8F.
It is useful to keep a copy of the configuration for each target. Otherwise every command would overwrite the previous command. Off course it is not required to keep the complete configuration for each target. Only the relevant information needs to be memorised.
To indicate that a command is ready-for-interpretation, a single input is used: command_valid. As long as this input is high, the command should stay constant. There are no other limitations. The image below gives an example how the commands can be received to recreate exercise 4.
The entity/module on the hierarchical top-level should look as shown below. Keep the port names as they are shown in the VHDL/Verilog code below.
entity xmas_light is
port (
reset : in STD_LOGIC;
clock : in STD_LOGIC;
command : in STD_LOGIC_VECTOR(31 downto 0);
command_valid : in STD_LOGIC;
RGB0 : out STD_LOGIC_VECTOR(2 downto 0);
RGB1 : out STD_LOGIC_VECTOR(2 downto 0);
LEDs : out STD_LOGIC_VECTOR(3 downto 0)
);
end xmas_light;
module xmas_light (
input reset,
input clock,
input [31:0] command,
input command_valid,
output [2:0] rgb0,
output [2:0] rgb1,
output [3:0] leds
);
With the toplevel-design ready, it needs to be tested. Remember the rule-of-thumb which states that for each hour of designing you should spend two hours on testing !!
The VHDL-code below shows an example of the testbench. Verilog users can also use a VHDL testbench (and the other way around) !! An example waveform as shown below, should be obtained.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity xmas_light_tb is
end xmas_light_tb;
architecture Behavioural of xmas_light_tb is
component xmas_light is
port (
reset : in STD_LOGIC;
clock : in STD_LOGIC;
command : in STD_LOGIC_VECTOR(31 downto 0);
command_valid : in STD_LOGIC;
RGB0 : out STD_LOGIC_VECTOR(2 downto 0);
RGB1 : out STD_LOGIC_VECTOR(2 downto 0);
LEDs : out STD_LOGIC_VECTOR(3 downto 0)
);
end component;
signal reset, clock : STD_LOGIC;
signal command : STD_LOGIC_VECTOR(31 downto 0);
signal command_valid : STD_LOGIC;
signal RGB0 : STD_LOGIC_VECTOR(2 downto 0);
signal RGB1 : STD_LOGIC_VECTOR(2 downto 0);
signal LEDs : STD_LOGIC_VECTOR(3 downto 0);
constant clock_period : time := 10 ns;
begin
-------------------------------------------------------------------------------
-- STIMULI
-------------------------------------------------------------------------------
PSTIM: process
begin
reset <= '1';
command <= x"00000000";
command_valid <= '0';
wait for clock_period*10;
reset <= '0';
wait for clock_period*1000;
--*************************************************************************
-- turn on all LEDs
command <= x"000000_F1"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- turn off all LEDs
command <= x"000000_F0"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate all LEDs at 1 Hz
command <= x"000000_FC"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate all LEDs at 2 Hz
command <= x"000000_FD"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate all LEDs at 4 Hz
command <= x"000000_FE"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate all LEDs at 8 Hz
command <= x"000000_FF"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- turn off all LEDs
command <= x"000000_F0"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
--*************************************************************************
-- turn on LED(0)
command <= x"000000_11"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- turn off LED(0)
command <= x"000000_10"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(0) at 1 Hz
command <= x"000000_1C"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(0) at 2 Hz
command <= x"000000_1D"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(0) at 4 Hz
command <= x"000000_1E"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(0) at 8 Hz
command <= x"000000_1F"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- turn off all LEDs
command <= x"000000_F0"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
--*************************************************************************
-- turn on LED(1)
command <= x"000000_21"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- turn off LED(1)
command <= x"000000_20"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(1) at 1 Hz
command <= x"000000_2C"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(1) at 2 Hz
command <= x"000000_2D"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(1) at 4 Hz
command <= x"000000_2E"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(1) at 8 Hz
command <= x"000000_2F"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- turn off all LEDs
command <= x"000000_F0"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
--*************************************************************************
-- turn on LED(2)
command <= x"000000_41"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- turn off LED(2)
command <= x"000000_40"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(2) at 1 Hz
command <= x"000000_4C"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(2) at 2 Hz
command <= x"000000_4D"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(2) at 4 Hz
command <= x"000000_4E"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(0) at 8 Hz
command <= x"000000_4F"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- turn off all LEDs
command <= x"000000_F0"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
--*************************************************************************
-- turn on LED(3)
command <= x"000000_81"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- turn off LED(3)
command <= x"000000_80"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(3) at 1 Hz
command <= x"000000_8C"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(3) at 2 Hz
command <= x"000000_8D"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(3) at 4 Hz
command <= x"000000_8E"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- oscillate LED(1) at 8 Hz
command <= x"000000_8F"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- turn off all LEDs
command <= x"000000_F0"; command_valid <= '1'; wait for clock_period*4;
command <= x"000000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*1000;
-- turn off all RGB LEDs
command <= x"000_3F0_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on RED_0 - PWM1
command <= x"000_011_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on GREEN_0 - PWM2
command <= x"000_022_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on BLUE_0 - PWM3
command <= x"000_043_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on RED_1 - PWM4
command <= x"000_084_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on GREEN_1 - PWM5
command <= x"000_105_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on BLUE_1 - PWM6
command <= x"000_206_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on RED_0 - PWM7
command <= x"000_017_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on GREEN_0 - PWM8
command <= x"000_028_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on BLUE_0 - PWM9
command <= x"000_049_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on RED_1 - PWMA
command <= x"000_08A_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on GREEN_1 - PWMB
command <= x"000_10B_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on BLUE_1 - PWMC
command <= x"000_20C_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on RED_0 - PWMD
command <= x"000_01D_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on GREEN_0 - PWME
command <= x"000_02E_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on BLUE_0 - PWMF
command <= x"000_04F_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on RED_1 - PWMF
command <= x"000_08F_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on GREEN_1 - PWMF
command <= x"000_10F_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on BLUE_1 - PWMF
command <= x"000_20F_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on RED_0 - PWMF
command <= x"000_01F_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
-- turn on GREEN_0 - PWME
command <= x"000_02F_00"; command_valid <= '1'; wait for clock_period*4;
command <= x"000_000_00"; command_valid <= '0'; wait for clock_period*4;
wait for clock_period*10000;
wait;
end process;
-------------------------------------------------------------------------------
-- DEVICE UNDER TEST
-------------------------------------------------------------------------------
DUT: component xmas_light port map(
reset => reset,
clock => clock,
command => command,
command_valid => command_valid,
RGB0 => RGB0,
RGB1 => RGB1,
LEDs => LEDs
);
-------------------------------------------------------------------------------
-- CLOCK
-------------------------------------------------------------------------------
PCLK: process
begin
clock <= '1';
wait for clock_period/2;
clock <= '0';
wait for clock_period/2;
end process PCLK;
end Behavioural;