From 544e5951f9a860e625c3ef9bf312c9bc3ec9bd70 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Tue, 7 Feb 2017 20:30:29 +0100 Subject: [PATCH] microzed_apo: Add SPI FSM for LEDs and encoder communication. Signed-off-by: Pavel Pisa --- system/ip/spi_leds_and_enc_1.0/component.xml | 8 + .../hdl/spi_leds_and_enc_v1_0.vhd | 156 ++++++++++++++++++ .../hdl/spi_leds_and_enc_v1_0_S00_AXI.vhd | 66 +++++--- .../hdl/spi_leds_and_enc_v1_0_spi_fsm.vhd | 92 +++++++++++ 4 files changed, 302 insertions(+), 20 deletions(-) create mode 100644 system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0_spi_fsm.vhd diff --git a/system/ip/spi_leds_and_enc_1.0/component.xml b/system/ip/spi_leds_and_enc_1.0/component.xml index 47b7fcb..f967bc9 100644 --- a/system/ip/spi_leds_and_enc_1.0/component.xml +++ b/system/ip/spi_leds_and_enc_1.0/component.xml @@ -704,6 +704,10 @@ xilinx_vhdlsynthesis_view_fileset + + hdl/spi_leds_and_enc_v1_0_spi_fsm.vhd + vhdlSource + hdl/spi_leds_and_enc_v1_0_S00_AXI.vhd vhdlSource @@ -716,6 +720,10 @@ xilinx_vhdlbehavioralsimulation_view_fileset + + hdl/spi_leds_and_enc_v1_0_spi_fsm.vhd + vhdlSource + hdl/spi_leds_and_enc_v1_0_S00_AXI.vhd vhdlSource diff --git a/system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0.vhd b/system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0.vhd index 0cdc32f..dfe415d 100644 --- a/system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0.vhd +++ b/system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0.vhd @@ -59,6 +59,17 @@ architecture arch_imp of spi_leds_and_enc_v1_0 is C_S_AXI_ADDR_WIDTH : integer := 6 ); port ( + output_led_line : out std_logic_vector(31 downto 0); + output_led_rgb1 : out std_logic_vector(23 downto 0); + output_led_rgb2 : out std_logic_vector(23 downto 0); + output_led_direct : out std_logic_vector(7 downto 0); + output_kbd_direct : out std_logic_vector(3 downto 0); + + in_enc_direct : in std_logic_vector(8 downto 0); + in_kbd_direct : in std_logic_vector(3 downto 0); + in_enc_8bit : in std_logic_vector(23 downto 0); + in_enc_buttons : in std_logic_vector(2 downto 0); + S_AXI_ACLK : in std_logic; S_AXI_ARESETN : in std_logic; S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); @@ -83,6 +94,61 @@ architecture arch_imp of spi_leds_and_enc_v1_0 is ); end component spi_leds_and_enc_v1_0_S00_AXI; + component spi_leds_and_enc_v1_0_spi_fsm is + generic ( + data_width : integer := 32; + spi_clkdiv : integer := 10 + ); + port ( + reset_in : in std_logic; + + clk_in : in std_logic; + clk_en : in std_logic; + + spi_clk : out std_logic; + spi_cs : out std_logic; + spi_mosi : out std_logic; + spi_miso : in std_logic; + + tx_data : in std_logic_vector(data_width-1 downto 0); + rx_data : out std_logic_vector(data_width-1 downto 0); + + trasfer_rq : in std_logic; + transfer_ready : out std_logic + ); + end component; + + constant spi_data_width : integer := 48; + constant spi_clk_div : integer := 10; + constant enc_number : integer := 3; + + signal fsm_clk : std_logic; + signal fsm_rst : std_logic; + signal spi_rx_data : std_logic_vector(spi_data_width-1 downto 0); + signal spi_tx_data : std_logic_vector(spi_data_width-1 downto 0); + signal spi_transfer_ready : std_logic; + + signal spi_out_rgb1 : std_logic_vector(2 downto 0); + signal spi_out_rgb2 : std_logic_vector(2 downto 0); + + signal spi_out_led3 : std_logic; + signal spi_out_led4 : std_logic; + + signal output_led_line : std_logic_vector(31 downto 0); + signal output_led_rgb1 : std_logic_vector(23 downto 0); + signal output_led_rgb2 : std_logic_vector(23 downto 0); + signal output_led_direct : std_logic_vector(7 downto 0); + signal output_kbd_direct : std_logic_vector(3 downto 0); + + signal in_enc_direct : std_logic_vector(8 downto 0); + signal in_kbd_direct : std_logic_vector(3 downto 0); + signal in_enc_8bit : std_logic_vector(23 downto 0); + signal in_enc_buttons : std_logic_vector(2 downto 0); + + signal enc_cha : std_logic_vector(enc_number downto 1); + signal enc_chb : std_logic_vector(enc_number downto 1); + signal enc_sw : std_logic_vector(enc_number downto 1); + begin -- Instantiation of Axi Bus Interface S00_AXI @@ -92,6 +158,17 @@ spi_leds_and_enc_v1_0_S00_AXI_inst : spi_leds_and_enc_v1_0_S00_AXI C_S_AXI_ADDR_WIDTH => C_S00_AXI_ADDR_WIDTH ) port map ( + output_led_line => output_led_line, + output_led_rgb1 => output_led_rgb1, + output_led_rgb2 => output_led_rgb2, + output_led_direct => output_led_direct, + output_kbd_direct => output_kbd_direct, + + in_enc_direct => in_enc_direct, + in_kbd_direct => in_kbd_direct, + in_enc_8bit => in_enc_8bit, + in_enc_buttons => in_enc_buttons, + S_AXI_ACLK => s00_axi_aclk, S_AXI_ARESETN => s00_axi_aresetn, S_AXI_AWADDR => s00_axi_awaddr, @@ -117,6 +194,85 @@ spi_leds_and_enc_v1_0_S00_AXI_inst : spi_leds_and_enc_v1_0_S00_AXI -- Add user logic here +spi_leds_and_enc_v1_0_spi_fsm_inst: spi_leds_and_enc_v1_0_spi_fsm + generic map ( + data_width => spi_data_width, + spi_clkdiv => spi_clk_div + ) + port map ( + reset_in => fsm_rst, + clk_in => fsm_clk, + clk_en => '1', + + spi_clk => spi_led_clk, + spi_cs => spi_led_cs, + spi_mosi => spi_led_data, + spi_miso => spi_led_encin, + + tx_data => spi_tx_data, + rx_data => spi_rx_data, + + trasfer_rq => '1', + transfer_ready => spi_transfer_ready + ); + + + fsm_clk <= s00_axi_aclk; + fsm_rst <= not s00_axi_aresetn; + +data_logic_process :process + begin + wait until rising_edge (fsm_clk); + if fsm_rst = '1' then + spi_led_reset <= '1'; + elsif spi_transfer_ready = '1' then + spi_led_reset <= '0'; + end if; + end process; + + spi_tx_data(47) <= '0'; + spi_tx_data(46 downto 44) <= spi_out_rgb1; + spi_tx_data(43 downto 42) <= (others => '0'); + spi_tx_data(41) <= spi_out_led4; + spi_tx_data(40) <= spi_out_led3; + spi_tx_data(39 downto 8) <= output_led_line; + spi_tx_data(7) <= '0'; + spi_tx_data(6 downto 3) <= not output_kbd_direct; + spi_tx_data(2 downto 0) <= spi_out_rgb2; + + enc_cha(1) <= not spi_rx_data(4); + enc_sw(1) <= not spi_rx_data(5); + enc_chb(1) <= not spi_rx_data(6); + + enc_cha(2) <= not spi_rx_data(11); + enc_sw(2) <= not spi_rx_data(12); + enc_chb(2) <= not spi_rx_data(13); + + enc_cha(3) <= not spi_rx_data(8); + enc_sw(3) <= not spi_rx_data(9); + enc_chb(3) <= not spi_rx_data(10); + + in_kbd_direct <= not spi_rx_data(3 downto 0); + + in_enc_buttons(2) <= enc_sw(1); + in_enc_buttons(1) <= enc_sw(2); + in_enc_buttons(0) <= enc_sw(3); + + in_enc_8bit <= (others => '0'); + + in_enc_direct <= (8 => enc_sw(1), 7 => enc_chb(1), 6 => enc_cha(1), + 5 => enc_sw(2), 4 => enc_chb(2), 3 => enc_cha(2), + 2 => enc_sw(3), 1 => enc_chb(3), 0 => enc_cha(3)); + + -- output_led_rgb1 : out std_logic_vector(23 downto 0); + -- output_led_rgb2 : out std_logic_vector(23 downto 0); + -- output_led_direct : out std_logic_vector(7 downto 0); + + spi_out_rgb1 <= output_led_direct(2 downto 0); + spi_out_rgb2 <= output_led_direct(5 downto 3); + spi_out_led3 <= output_led_direct(6); + spi_out_led4 <= output_led_direct(7); + -- User logic ends end arch_imp; diff --git a/system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0_S00_AXI.vhd b/system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0_S00_AXI.vhd index 6a55a35..b78af27 100644 --- a/system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0_S00_AXI.vhd +++ b/system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0_S00_AXI.vhd @@ -17,6 +17,17 @@ entity spi_leds_and_enc_v1_0_S00_AXI is port ( -- Users to add ports here + output_led_line : out std_logic_vector(31 downto 0); + output_led_rgb1 : out std_logic_vector(23 downto 0); + output_led_rgb2 : out std_logic_vector(23 downto 0); + output_led_direct : out std_logic_vector(7 downto 0); + output_kbd_direct : out std_logic_vector(3 downto 0); + + in_enc_direct : in std_logic_vector(8 downto 0); + in_kbd_direct : in std_logic_vector(3 downto 0); + in_enc_8bit : in std_logic_vector(23 downto 0); + in_enc_buttons : in std_logic_vector(2 downto 0); + -- User ports ends -- Do not modify the ports beyond this line @@ -228,8 +239,8 @@ begin slv_reg5 <= (others => '0'); slv_reg6 <= (others => '0'); slv_reg7 <= (others => '0'); - slv_reg8 <= (others => '0'); - slv_reg9 <= (others => '0'); + -- slv_reg8 <= (others => '0'); + -- slv_reg9 <= (others => '0'); slv_reg10 <= (others => '0'); slv_reg11 <= (others => '0'); slv_reg12 <= (others => '0'); @@ -304,22 +315,22 @@ begin slv_reg7(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); end if; end loop; - when b"1000" => - for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop - if ( S_AXI_WSTRB(byte_index) = '1' ) then - -- Respective byte enables are asserted as per write strobes - -- slave registor 8 - slv_reg8(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); - end if; - end loop; - when b"1001" => - for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop - if ( S_AXI_WSTRB(byte_index) = '1' ) then - -- Respective byte enables are asserted as per write strobes - -- slave registor 9 - slv_reg9(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); - end if; - end loop; + -- when b"1000" => + -- for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + -- if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- -- Respective byte enables are asserted as per write strobes + -- -- slave registor 8 + -- slv_reg8(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + -- end if; + -- end loop; + -- when b"1001" => + -- for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + -- if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- -- Respective byte enables are asserted as per write strobes + -- -- slave registor 9 + -- slv_reg9(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + -- end if; + -- end loop; when b"1010" => for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop if ( S_AXI_WSTRB(byte_index) = '1' ) then @@ -377,8 +388,8 @@ begin slv_reg5 <= slv_reg5; slv_reg6 <= slv_reg6; slv_reg7 <= slv_reg7; - slv_reg8 <= slv_reg8; - slv_reg9 <= slv_reg9; + -- slv_reg8 <= slv_reg8; + -- slv_reg9 <= slv_reg9; slv_reg10 <= slv_reg10; slv_reg11 <= slv_reg11; slv_reg12 <= slv_reg12; @@ -536,6 +547,21 @@ begin -- Add user logic here + output_led_line <= slv_reg1(31 downto 0); + output_led_rgb1 <= slv_reg4(23 downto 0); + output_led_rgb2 <= slv_reg5(23 downto 0); + output_led_direct <= slv_reg6(7 downto 0); + output_kbd_direct <= slv_reg6(11 downto 8); + + slv_reg8(3 downto 0) <= in_kbd_direct; + slv_reg8(15 downto 4) <= (others => '0'); + slv_reg8(24 downto 16) <= in_enc_direct; + slv_reg8(31 downto 25) <= (others => '0'); + + slv_reg9(23 downto 0) <= in_enc_8bit; + slv_reg9(26 downto 24) <= in_enc_buttons; + slv_reg9(31 downto 27) <= (others => '0'); + -- User logic ends end arch_imp; diff --git a/system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0_spi_fsm.vhd b/system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0_spi_fsm.vhd new file mode 100644 index 0000000..fa8b684 --- /dev/null +++ b/system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0_spi_fsm.vhd @@ -0,0 +1,92 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity spi_leds_and_enc_v1_0_spi_fsm is + generic ( + data_width : integer := 32; + spi_clkdiv : integer := 10 + ); + port ( + reset_in : in std_logic; + + clk_in : in std_logic; + clk_en : in std_logic; + + spi_clk : out std_logic; + spi_cs : out std_logic; + spi_mosi : out std_logic; + spi_miso : in std_logic; + + tx_data : in std_logic_vector(data_width-1 downto 0); + rx_data : out std_logic_vector(data_width-1 downto 0); + + trasfer_rq : in std_logic; + transfer_ready : out std_logic + ); +end spi_leds_and_enc_v1_0_spi_fsm; + +architecture arch_imp of spi_leds_and_enc_v1_0_spi_fsm is + + signal shift_reg : std_logic_vector(data_width-1 downto 0); + signal data_cnt : natural range 0 to data_width; + signal div_cnt : natural range 0 to spi_clkdiv-1; + signal clk_phase : std_logic; + signal in_progress : std_logic; + +begin + + process is + begin + wait until rising_edge (clk_in); + if ( reset_in = '1' ) then + shift_reg <= (others => '0'); + rx_data <= (others => '0'); + div_cnt <= spi_clkdiv-1; + transfer_ready <= '0'; + data_cnt <= 0; + spi_clk <= '1'; + spi_cs <= '1'; + spi_mosi <= '0'; + clk_phase <= '0'; + in_progress <= '0'; + elsif (clk_en = '1') then + transfer_ready <= '0'; + if (div_cnt /= 0) then + div_cnt <= div_cnt - 1; + elsif clk_phase = '1' then + div_cnt <= spi_clkdiv-1; + clk_phase <= '0'; + spi_clk <= '1'; + if in_progress = '1' then + shift_reg(data_width-1) <= spi_miso; + end if; + else + clk_phase <= '1'; + div_cnt <= spi_clkdiv-1; + spi_clk <= '0'; + if (data_cnt = 0) then + spi_cs <= '1'; + if in_progress = '1' then + spi_cs <= '1'; + rx_data <= shift_reg; + end if; + transfer_ready <= in_progress; + in_progress <= '0'; + if (trasfer_rq = '1') then + shift_reg <= tx_data; + data_cnt <= data_width; + spi_mosi <= '0'; + end if; + else + in_progress <= '1'; + spi_cs <= '0'; + spi_mosi <= shift_reg(0); + shift_reg <= '0' & shift_reg(data_width-1 downto 1); + data_cnt <= data_cnt - 1; + end if; + end if; + end if; + end process; + +end arch_imp; -- 2.39.2