Disabled external gits
This commit is contained in:
36
cs473-es/lab2/ch/hw/hdl/WS28XX/ClkGen.vhd
Normal file
36
cs473-es/lab2/ch/hw/hdl/WS28XX/ClkGen.vhd
Normal file
@@ -0,0 +1,36 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.math_real.all;
|
||||
|
||||
entity ClkGen is
|
||||
generic (
|
||||
F_OUT : natural; -- Hz
|
||||
F_CLK : natural -- Hz
|
||||
);
|
||||
port (
|
||||
clk : in std_logic;
|
||||
rst_n : in std_logic;
|
||||
clk_o : out std_logic;
|
||||
en : in std_logic
|
||||
);
|
||||
end ClkGen;
|
||||
|
||||
architecture Behavioral of ClkGen is
|
||||
constant CNT_MAX : integer := integer(floor(real(F_CLK) / real(F_OUT))) - 1;
|
||||
signal counter_reg, counter_next: integer range CNT_MAX downto 0;
|
||||
begin
|
||||
counter_next <= CNT_MAX when counter_reg = 0 else counter_reg - 1;
|
||||
process(clk, rst_n) begin
|
||||
if rising_edge(clk) then
|
||||
if rst_n = '0' then
|
||||
counter_reg <= CNT_MAX;
|
||||
else
|
||||
if en = '1' then
|
||||
counter_reg <= counter_next;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
clk_o <= '1' when counter_reg = 0 and en = '1' else '0';
|
||||
end Behavioral; -- Behavioral
|
89
cs473-es/lab2/ch/hw/hdl/WS28XX/WS28XX.vhd
Normal file
89
cs473-es/lab2/ch/hw/hdl/WS28XX/WS28XX.vhd
Normal file
@@ -0,0 +1,89 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity WS28XX is
|
||||
port(
|
||||
clk:in std_logic;
|
||||
nReset:in std_logic;
|
||||
|
||||
--Internalinterface(i.e.Avalonslave).
|
||||
address:in std_logic;
|
||||
write:in std_logic;
|
||||
writedata:in std_logic_vector(31 downto 0);
|
||||
|
||||
--Externalinterface(i.e.conduit).
|
||||
lout:out std_logic
|
||||
);
|
||||
|
||||
end WS28XX;
|
||||
|
||||
|
||||
architecture comp of WS28XX is
|
||||
|
||||
signal led_i : std_logic_vector(7 downto 0);
|
||||
signal led_v : std_logic_vector(23 downto 0);
|
||||
signal led_wr : std_logic;
|
||||
|
||||
signal led_n : std_logic_vector(7 downto 0);
|
||||
signal led_n_wr : std_logic;
|
||||
|
||||
signal ready : std_logic;
|
||||
begin
|
||||
|
||||
--WSDriver.
|
||||
l0 : entity work.WSDriver
|
||||
generic map (
|
||||
F_CLK => 50000000,
|
||||
N_LED_MAX => 255
|
||||
)
|
||||
port map (
|
||||
clk => clk,
|
||||
rst_n => nReset,
|
||||
|
||||
-- LED address and LED value
|
||||
led_wr_in => led_wr,
|
||||
led_in => led_v,
|
||||
addr_in => led_i,
|
||||
|
||||
-- Write-enable & value of N bits to keep active
|
||||
n_wr_in => led_n_wr,
|
||||
n_in => led_n,
|
||||
|
||||
-- Output 1-bit line for WS2812 strip
|
||||
ws_out => lout,
|
||||
|
||||
-- Low while shifting LED values
|
||||
ready_out => ready
|
||||
);
|
||||
|
||||
|
||||
led_i <= writedata(31 downto 24);
|
||||
led_v <= writedata(23 downto 0);
|
||||
led_n <= writedata(7 downto 0);
|
||||
|
||||
--Avalon slave - write to registers.
|
||||
process(write,address,nReset)
|
||||
begin
|
||||
if nReset = '0' then
|
||||
led_wr <= '0';
|
||||
led_n_wr <= '0';
|
||||
else
|
||||
led_wr <= '0';
|
||||
led_n_wr <= '0';
|
||||
|
||||
if write = '1' then
|
||||
case address is
|
||||
when '0' =>
|
||||
led_wr <= '1';
|
||||
when '1' =>
|
||||
led_n_wr <= '1';
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
end comp;
|
134
cs473-es/lab2/ch/hw/hdl/WS28XX/WS28XX_hw.tcl
Normal file
134
cs473-es/lab2/ch/hw/hdl/WS28XX/WS28XX_hw.tcl
Normal file
@@ -0,0 +1,134 @@
|
||||
# TCL File Generated by Component Editor 18.1
|
||||
# Fri Oct 30 13:47:37 CET 2020
|
||||
# DO NOT MODIFY
|
||||
|
||||
|
||||
#
|
||||
# WS28XX "WS28XX" v1.0
|
||||
# 2020.10.30.13:47:37
|
||||
#
|
||||
#
|
||||
|
||||
#
|
||||
# request TCL package from ACDS 16.1
|
||||
#
|
||||
package require -exact qsys 16.1
|
||||
|
||||
|
||||
#
|
||||
# module WS28XX
|
||||
#
|
||||
set_module_property DESCRIPTION ""
|
||||
set_module_property NAME WS28XX
|
||||
set_module_property VERSION 1.0
|
||||
set_module_property INTERNAL false
|
||||
set_module_property OPAQUE_ADDRESS_MAP true
|
||||
set_module_property AUTHOR ""
|
||||
set_module_property DISPLAY_NAME WS28XX
|
||||
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true
|
||||
set_module_property EDITABLE true
|
||||
set_module_property REPORT_TO_TALKBACK false
|
||||
set_module_property ALLOW_GREYBOX_GENERATION false
|
||||
set_module_property REPORT_HIERARCHY false
|
||||
|
||||
|
||||
#
|
||||
# file sets
|
||||
#
|
||||
add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" ""
|
||||
set_fileset_property QUARTUS_SYNTH TOP_LEVEL WS28XX
|
||||
set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false
|
||||
set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE false
|
||||
add_fileset_file WS28XX.vhd VHDL PATH WS28XX.vhd TOP_LEVEL_FILE
|
||||
|
||||
|
||||
#
|
||||
# parameters
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# display items
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# connection point avalon_slave
|
||||
#
|
||||
add_interface avalon_slave avalon end
|
||||
set_interface_property avalon_slave addressUnits WORDS
|
||||
set_interface_property avalon_slave associatedClock clock_sink
|
||||
set_interface_property avalon_slave associatedReset reset_sink
|
||||
set_interface_property avalon_slave bitsPerSymbol 8
|
||||
set_interface_property avalon_slave burstOnBurstBoundariesOnly false
|
||||
set_interface_property avalon_slave burstcountUnits WORDS
|
||||
set_interface_property avalon_slave explicitAddressSpan 0
|
||||
set_interface_property avalon_slave holdTime 0
|
||||
set_interface_property avalon_slave linewrapBursts false
|
||||
set_interface_property avalon_slave maximumPendingReadTransactions 0
|
||||
set_interface_property avalon_slave maximumPendingWriteTransactions 0
|
||||
set_interface_property avalon_slave readLatency 0
|
||||
set_interface_property avalon_slave readWaitTime 1
|
||||
set_interface_property avalon_slave setupTime 0
|
||||
set_interface_property avalon_slave timingUnits Cycles
|
||||
set_interface_property avalon_slave writeWaitTime 0
|
||||
set_interface_property avalon_slave ENABLED true
|
||||
set_interface_property avalon_slave EXPORT_OF ""
|
||||
set_interface_property avalon_slave PORT_NAME_MAP ""
|
||||
set_interface_property avalon_slave CMSIS_SVD_VARIABLES ""
|
||||
set_interface_property avalon_slave SVD_ADDRESS_GROUP ""
|
||||
|
||||
add_interface_port avalon_slave address address Input 2
|
||||
add_interface_port avalon_slave write write Input 1
|
||||
add_interface_port avalon_slave writedata writedata Input 32
|
||||
add_interface_port avalon_slave read read Input 1
|
||||
add_interface_port avalon_slave readdata readdata Output 32
|
||||
set_interface_assignment avalon_slave embeddedsw.configuration.isFlash 0
|
||||
set_interface_assignment avalon_slave embeddedsw.configuration.isMemoryDevice 0
|
||||
set_interface_assignment avalon_slave embeddedsw.configuration.isNonVolatileStorage 0
|
||||
set_interface_assignment avalon_slave embeddedsw.configuration.isPrintableDevice 0
|
||||
|
||||
|
||||
#
|
||||
# connection point clock_sink
|
||||
#
|
||||
add_interface clock_sink clock end
|
||||
set_interface_property clock_sink clockRate 0
|
||||
set_interface_property clock_sink ENABLED true
|
||||
set_interface_property clock_sink EXPORT_OF ""
|
||||
set_interface_property clock_sink PORT_NAME_MAP ""
|
||||
set_interface_property clock_sink CMSIS_SVD_VARIABLES ""
|
||||
set_interface_property clock_sink SVD_ADDRESS_GROUP ""
|
||||
|
||||
add_interface_port clock_sink clk clk Input 1
|
||||
|
||||
|
||||
#
|
||||
# connection point reset_sink
|
||||
#
|
||||
add_interface reset_sink reset end
|
||||
set_interface_property reset_sink associatedClock clock_sink
|
||||
set_interface_property reset_sink synchronousEdges DEASSERT
|
||||
set_interface_property reset_sink ENABLED true
|
||||
set_interface_property reset_sink EXPORT_OF ""
|
||||
set_interface_property reset_sink PORT_NAME_MAP ""
|
||||
set_interface_property reset_sink CMSIS_SVD_VARIABLES ""
|
||||
set_interface_property reset_sink SVD_ADDRESS_GROUP ""
|
||||
|
||||
add_interface_port reset_sink nReset reset_n Input 1
|
||||
|
||||
|
||||
#
|
||||
# connection point ws_out_source
|
||||
#
|
||||
add_interface ws_out_source conduit end
|
||||
set_interface_property ws_out_source associatedClock clock_sink
|
||||
set_interface_property ws_out_source associatedReset ""
|
||||
set_interface_property ws_out_source ENABLED true
|
||||
set_interface_property ws_out_source EXPORT_OF ""
|
||||
set_interface_property ws_out_source PORT_NAME_MAP ""
|
||||
set_interface_property ws_out_source CMSIS_SVD_VARIABLES ""
|
||||
set_interface_property ws_out_source SVD_ADDRESS_GROUP ""
|
||||
|
||||
add_interface_port ws_out_source lout new_signal Output 1
|
||||
|
213
cs473-es/lab2/ch/hw/hdl/WS28XX/WSDriver.vhd
Normal file
213
cs473-es/lab2/ch/hw/hdl/WS28XX/WSDriver.vhd
Normal file
@@ -0,0 +1,213 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.math_real.all;
|
||||
|
||||
entity WSDriver is
|
||||
generic (
|
||||
F_CLK : natural; -- Board frequency in Hz
|
||||
N_LED_MAX : natural -- Maximum number of LEDs to instantiate
|
||||
);
|
||||
port (
|
||||
clk : in std_logic;
|
||||
rst_n : in std_logic;
|
||||
|
||||
-- LED address and LED value
|
||||
led_wr_in : in std_logic;
|
||||
led_in : in std_logic_vector(23 downto 0);
|
||||
addr_in : in std_logic_vector(integer(ceil(log2(real(N_LED_MAX)))) - 1 downto 0);
|
||||
|
||||
-- Write-enable and value of N LEDs to keep active/addressable
|
||||
n_wr_in : in std_logic;
|
||||
n_in : in std_logic_vector(integer(ceil(log2(real(N_LED_MAX)))) - 1 downto 0);
|
||||
|
||||
-- Output 1-bit line for WS2812 strip
|
||||
ws_out : out std_logic;
|
||||
|
||||
-- Output Ready
|
||||
ready_out : out std_logic
|
||||
);
|
||||
end WSDriver;
|
||||
|
||||
architecture Behavioral of WSDriver is
|
||||
constant F_WS : real := 1.0/((0.3)*10**(-6.0));
|
||||
constant T_RES_US : real := 50.0*10**(-6.0);
|
||||
constant RES_TICKS : integer := integer(ceil(T_RES_US*F_WS));
|
||||
|
||||
constant BITS_PER_LED : integer := 24;
|
||||
|
||||
subtype LED is std_logic_vector(BITS_PER_LED - 1 downto 0);
|
||||
type LED_array is array (natural range 0 to N_LED_MAX - 1) of LED;
|
||||
|
||||
type State is (ready, tx, reset);
|
||||
|
||||
signal ws_clk : std_logic;
|
||||
signal led_idx_reg, led_idx_next : natural range 0 to N_LED_MAX - 1;
|
||||
signal bit_idx_reg, bit_idx_next : natural range 0 to N_LED_MAX - 1;
|
||||
signal state_reg, state_next : State;
|
||||
|
||||
constant WS_CLKS_PER_BIT : integer := 4;
|
||||
signal ws_cntr_reg, ws_cntr_next : integer range WS_CLKS_PER_BIT - 1 downto 0;
|
||||
signal ws_en : std_logic;
|
||||
|
||||
signal leds_reg, leds_next : LED_array;
|
||||
|
||||
-- Register for maintaining the set of driven LEDs
|
||||
signal n_leds_reg, n_leds_next : unsigned(integer(ceil(log2(real(N_LED_MAX)))) - 1 downto 0) := (others => '0');
|
||||
|
||||
-- Currently accessed LED
|
||||
signal current_led : LED;
|
||||
|
||||
-- Trailing reset counter
|
||||
signal reset_cntr_reg, reset_cntr_next : integer range RES_TICKS - 1 downto 0;
|
||||
|
||||
-- Detecting wr_in assertions
|
||||
signal wr_in_detec_reg, wr_in_detec_next : std_logic := '0';
|
||||
|
||||
|
||||
begin
|
||||
|
||||
-- Next-state LED and Bit index process
|
||||
process (all) begin
|
||||
bit_idx_next <= bit_idx_reg;
|
||||
led_idx_next <= led_idx_reg;
|
||||
reset_cntr_next <= reset_cntr_reg;
|
||||
state_next <= state_reg;
|
||||
wr_in_detec_next <= wr_in_detec_reg;
|
||||
|
||||
-- Latch wr_in value, to ensure re-transition to tx state if wr_in occured
|
||||
-- during a non-ready state.
|
||||
if led_wr_in = '1' then
|
||||
wr_in_detec_next <= '1';
|
||||
end if;
|
||||
|
||||
case state_reg is
|
||||
-- STATE READY
|
||||
when ready =>
|
||||
bit_idx_next <= BITS_PER_LED - 1;
|
||||
led_idx_next <= 0;
|
||||
|
||||
if n_leds_reg /= 0 and wr_in_detec_reg = '1' then
|
||||
wr_in_detec_next <= '0';
|
||||
state_next <= tx;
|
||||
end if;
|
||||
|
||||
-- STATE TX
|
||||
when tx =>
|
||||
if ws_cntr_reg = (WS_CLKS_PER_BIT - 1) and ws_clk ='1' then
|
||||
if bit_idx_reg = 0 then
|
||||
-- Transition to next LED
|
||||
bit_idx_next <= BITS_PER_LED - 1;
|
||||
led_idx_next <= led_idx_reg + 1;
|
||||
else
|
||||
-- Bit was fully shifted, transition to next bit
|
||||
bit_idx_next <= bit_idx_reg - 1;
|
||||
end if;
|
||||
|
||||
-- All LEDs fully shifted out (+last bit of last led)? transition to ready
|
||||
if bit_idx_reg = 0 and led_idx_reg + 1 = n_leds_reg then
|
||||
state_next <= reset;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- STATE TRAILING RESET
|
||||
when reset =>
|
||||
if ws_clk ='1' then
|
||||
if reset_cntr_reg = RES_TICKS - 1 then
|
||||
reset_cntr_next <= 0;
|
||||
state_next <= ready;
|
||||
else
|
||||
reset_cntr_next <= reset_cntr_reg + 1;
|
||||
end if;
|
||||
end if;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- Currently accessed LED multiplexer
|
||||
current_led <= leds_reg(led_idx_reg) when state_reg = tx else (others => '0');
|
||||
|
||||
-- Next state WS counter
|
||||
process (state_reg, ws_cntr_reg, ws_clk) begin
|
||||
ws_cntr_next <= ws_cntr_reg;
|
||||
if state_reg = ready or state_reg = reset then
|
||||
ws_cntr_next <= 0;
|
||||
elsif ws_clk = '1' then
|
||||
if ws_cntr_reg /= (WS_CLKS_PER_BIT - 1) then
|
||||
ws_cntr_next <= ws_cntr_reg + 1;
|
||||
else
|
||||
ws_cntr_next <= 0;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Next-state LED values
|
||||
process(led_wr_in, led_in, leds_reg, addr_in, n_wr_in, n_in) begin
|
||||
leds_next <= leds_reg;
|
||||
n_leds_next <= n_leds_reg;
|
||||
|
||||
if led_wr_in = '1' then
|
||||
leds_next(to_integer(unsigned(addr_in))) <= led_in;
|
||||
end if;
|
||||
-- Set N LEDs precedes LED write operation
|
||||
if n_wr_in = '1' then
|
||||
n_leds_next <= unsigned(n_in);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- WS output clock
|
||||
clkgen_ent : entity work.ClkGen
|
||||
generic map (
|
||||
F_CLK => F_CLK,
|
||||
F_OUT => integer(F_WS)
|
||||
)
|
||||
port map (
|
||||
clk => clk,
|
||||
rst_n => rst_n,
|
||||
clk_o => ws_clk,
|
||||
en => ws_en
|
||||
);
|
||||
|
||||
-- Only enable ws clock gen when required
|
||||
ws_en <= '1' when state_reg /= ready else '0';
|
||||
|
||||
-- Clocking logic
|
||||
process(clk) begin
|
||||
if rising_edge(clk) then
|
||||
if rst_n = '0' then
|
||||
ws_cntr_reg <= 0;
|
||||
leds_reg <= (others => (others => '0'));
|
||||
n_leds_reg <= (others => '0');
|
||||
wr_in_detec_reg <= '0';
|
||||
bit_idx_reg <= BITS_PER_LED - 1;
|
||||
state_reg <= ready;
|
||||
led_idx_reg <= 0;
|
||||
reset_cntr_reg <= 0;
|
||||
else
|
||||
ws_cntr_reg <= ws_cntr_next;
|
||||
leds_reg <= leds_next;
|
||||
n_leds_reg <= n_leds_next;
|
||||
wr_in_detec_reg <= wr_in_detec_next;
|
||||
bit_idx_reg <= bit_idx_next;
|
||||
state_reg <= state_next;
|
||||
led_idx_reg <= led_idx_next;
|
||||
reset_cntr_reg <= reset_cntr_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- WS2811 output bit sequence
|
||||
process(state_reg, ws_cntr_reg) begin
|
||||
ws_out <= '0';
|
||||
if state_reg = tx then
|
||||
case ws_cntr_reg is
|
||||
when 0 => ws_out <= '1';
|
||||
when 1 => ws_out <= current_led(bit_idx_reg);
|
||||
when 2 => ws_out <= '0';
|
||||
when 3 => ws_out <= '0';
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
ready_out <= '1' when state_reg = ready else '0';
|
||||
|
||||
end Behavioral;
|
96
cs473-es/lab2/ch/hw/hdl/WS28XX/WSDriver_tb.vhd
Normal file
96
cs473-es/lab2/ch/hw/hdl/WS28XX/WSDriver_tb.vhd
Normal file
@@ -0,0 +1,96 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use ieee.math_real.all;
|
||||
|
||||
|
||||
entity WSDriver_tb is
|
||||
end WSDriver_tb;
|
||||
|
||||
architecture test of WSDriver_tb is
|
||||
constant CLK_PERIOD : time := 20 ns;
|
||||
constant N_LED_MAX : integer := 255;
|
||||
|
||||
signal clk : std_logic := '0';
|
||||
signal rst_n : std_logic;
|
||||
|
||||
signal led_wr_in : std_logic := '0';
|
||||
signal addr_in : std_logic_vector(integer(ceil(log2(real(N_LED_MAX)))) - 1 downto 0) := (others => '0');
|
||||
signal led_in : std_logic_vector(23 downto 0) := (others => '0');
|
||||
|
||||
signal n_wr_in : std_logic := '0';
|
||||
signal n_in : std_logic_vector(integer(ceil(log2(real(N_LED_MAX)))) - 1 downto 0) := (others => '0');
|
||||
|
||||
signal ws_out : std_logic;
|
||||
signal ready_out : std_logic;
|
||||
|
||||
begin
|
||||
-- Instantiate DUT
|
||||
dut : entity work.WSDriver
|
||||
generic map (
|
||||
F_CLK => 50000000,
|
||||
N_LED_MAX => 255
|
||||
)
|
||||
port map(
|
||||
clk => clk,
|
||||
rst_n => rst_n,
|
||||
led_wr_in => led_wr_in,
|
||||
addr_in => addr_in,
|
||||
led_in => led_in,
|
||||
n_wr_in => n_wr_in,
|
||||
n_in => n_in,
|
||||
ws_out => ws_out,
|
||||
ready_out => ready_out
|
||||
);
|
||||
|
||||
-- Clocking process
|
||||
clk_generation : process
|
||||
begin
|
||||
clk <= not clk;
|
||||
wait for CLK_PERIOD / 2;
|
||||
end process;
|
||||
|
||||
tb : process
|
||||
procedure wait_ready is
|
||||
begin
|
||||
if ready_out /= '1' then
|
||||
wait until ready_out = '1';
|
||||
end if;
|
||||
end procedure wait_ready;
|
||||
|
||||
procedure finish is
|
||||
begin
|
||||
wait until falling_edge(clk);
|
||||
wait_ready;
|
||||
wait;
|
||||
end procedure finish ;
|
||||
|
||||
begin
|
||||
-- Reset
|
||||
rst_n <= '0';
|
||||
wait for CLK_PERIOD * 2.5;
|
||||
rst_n <= '1';
|
||||
wait for CLK_PERIOD * 2;
|
||||
|
||||
-- Test set N
|
||||
n_in <= std_logic_vector(to_unsigned(3, n_in'length));
|
||||
n_wr_in <= '1';
|
||||
wait for CLK_PERIOD;
|
||||
n_wr_in <= '0';
|
||||
wait_ready;
|
||||
|
||||
|
||||
-- Test write LED value
|
||||
addr_in <= std_logic_vector(to_unsigned(0, n_in'length));
|
||||
led_in <= "110011001100110011001100";
|
||||
led_wr_in <= '1';
|
||||
wait for CLK_PERIOD;
|
||||
led_wr_in <= '0';
|
||||
|
||||
-- Test finished
|
||||
wait_ready;
|
||||
finish;
|
||||
|
||||
end process;
|
||||
|
||||
end;
|
Reference in New Issue
Block a user