]> rtime.felk.cvut.cz Git - fpga/zynq/canbench-sw.git/commitdiff
microzed_apo: Add SPI FSM for LEDs and encoder communication.
authorPavel Pisa <pisa@cmp.felk.cvut.cz>
Tue, 7 Feb 2017 19:30:29 +0000 (20:30 +0100)
committerPavel Pisa <pisa@cmp.felk.cvut.cz>
Tue, 7 Feb 2017 19:30:29 +0000 (20:30 +0100)
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
system/ip/spi_leds_and_enc_1.0/component.xml
system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0.vhd
system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0_S00_AXI.vhd
system/ip/spi_leds_and_enc_1.0/hdl/spi_leds_and_enc_v1_0_spi_fsm.vhd [new file with mode: 0644]

index 47b7fcb4e6ff5f20a9ac2a3831c2017ad5a3de98..f967bc9f9b15aec602064b22b12ee72d6e2034b2 100644 (file)
   <spirit:fileSets>
     <spirit:fileSet>
       <spirit:name>xilinx_vhdlsynthesis_view_fileset</spirit:name>
+      <spirit:file>
+        <spirit:name>hdl/spi_leds_and_enc_v1_0_spi_fsm.vhd</spirit:name>
+        <spirit:fileType>vhdlSource</spirit:fileType>
+      </spirit:file>
       <spirit:file>
         <spirit:name>hdl/spi_leds_and_enc_v1_0_S00_AXI.vhd</spirit:name>
         <spirit:fileType>vhdlSource</spirit:fileType>
     </spirit:fileSet>
     <spirit:fileSet>
       <spirit:name>xilinx_vhdlbehavioralsimulation_view_fileset</spirit:name>
+      <spirit:file>
+        <spirit:name>hdl/spi_leds_and_enc_v1_0_spi_fsm.vhd</spirit:name>
+        <spirit:fileType>vhdlSource</spirit:fileType>
+      </spirit:file>
       <spirit:file>
         <spirit:name>hdl/spi_leds_and_enc_v1_0_S00_AXI.vhd</spirit:name>
         <spirit:fileType>vhdlSource</spirit:fileType>
index 0cdc32f51892cb7ee1e347d76f4c43f0281ea6c2..dfe415d7f619aa9ed3d304169a7635b210822c2b 100644 (file)
@@ -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;
index 6a55a3593501adc014d5519987fe77ac91c35efd..b78af27dad1c8f03a2f3fac692ea60be5eaef4c9 100644 (file)
@@ -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 (file)
index 0000000..fa8b684
--- /dev/null
@@ -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;