📄 spi_test.vhd
字号:
library ieee;use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity spi is generic(N:integer:=100); port( allclk :in std_logic; rst : in std_ulogic; --addr : in std_ulogic_vector(1 downto 0); --for signaltap,change it --to signal --datain : in std_ulogic_vector(7 downto 0); dataout : out std_ulogic_vector(7 downto 0):="00000000"; --write : in std_ulogic; irq : out std_ulogic:='0'; misoi : in std_ulogic; mosio : out std_ulogic:='0'; scko : out std_ulogic:='0'; spics : in std_ulogic; cs : out std_ulogic );end spi;architecture behav of spi is-- type statemachine is(cs_en,spi_init,clk_sel,ad_init_1,ad_init_2,test);-- signal st,nxst : statemachine; signal st,nxst : std_ulogic_vector(2 downto 0); signal clk : std_ulogic; -- spi main clk signal bit_ctr : std_ulogic_vector(2 downto 0); signal ctl_reg : std_ulogic_vector(7 downto 0); -- control register signal dvd_ctr : std_ulogic_vector(4 downto 0); -- clock divider signal dvd2 : std_ulogic; signal dvd_zero : std_ulogic; -- enable clock divider signal irq_flag : std_ulogic; signal misoe_lcl : std_ulogic; signal mosie_lcl : std_ulogic; signal oflow : std_ulogic; signal sel_clk : std_ulogic_vector(1 downto 0); signal shift_reg : std_ulogic_vector(7 downto 0); signal shift_clk : std_ulogic; signal shift_clk_negedge : std_ulogic; -- negative edge of SCK signal shift_negative_edge_nxt : std_ulogic; signal shift_negative_edge : std_ulogic; signal shift_datain : std_ulogic; signal shift_dataout : std_ulogic; signal spi_go : std_ulogic; -- begin a transfer signal status : std_ulogic_vector(7 downto 0); signal tx_end : std_ulogic; -- 0 when transfer is end signal tx_run : std_ulogic; -- 1 when a transfer is going signal tx_start : std_ulogic; signal tx_start_r1 : std_ulogic; signal addr : std_ulogic_vector(1 downto 0); signal datain : std_ulogic_vector(7 downto 0); signal write : std_ulogic; signal temp : integer; begin mosio <= shift_dataout; spi_go <= '1' when write='1' and addr="00" and tx_run='0' else '0'; process(allclk,rst) begin if allclk='1' and allclk'event then if temp<N-1 then temp<=temp+1; else temp<=0; end if; if temp<N/2 then clk<='1'; else clk<='0'; end if; end if; end process;-- shift reg sr_proc : process(clk) begin if (clk'event and clk='1') then if (rst='1') then shift_reg <= "00000000"; else if (spi_go='1') then -- can't write when transfering shift_reg <= datain; elsif (shift_clk='1') then shift_reg <= shift_reg(6 downto 0) & shift_datain; end if; end if; end if; end process; neg_proc : process(clk) begin if (clk'event and clk='1') then if (rst='1') then shift_negative_edge <= '0'; elsif (shift_clk_negedge='1') then shift_negative_edge <= shift_negative_edge_nxt; elsif (spi_go='1') then shift_negative_edge <= datain(7); end if; end if; end process; shift_negative_edge_nxt <= misoi; shift_dataout <= shift_reg(7); shift_datain <= shift_negative_edge; tr_proc : process(clk) begin if (clk'event and clk='1') then if (rst='1') then tx_run <= '0'; else if (tx_start='1') then tx_run <= '1'; elsif (tx_end='1') then tx_run <= '0'; end if; end if; end if; end process; bc_proc : process (clk) begin if (clk'event and clk='1') then if (rst='1') then bit_ctr <= "000"; else if (tx_start='1') then bit_ctr <= "000"; elsif (shift_clk='1') then bit_ctr <= std_ulogic_vector(unsigned(bit_ctr)-1); end if; end if; end if; end process; tx_end <= '1' when bit_ctr="001" and shift_clk='1' and tx_run='1' else '0'; tx_start <= '1' when spi_go='1' else '0'; -- control reg gjr_proc : process (clk) begin if (clk'event and clk='1') then if (rst='1') then ctl_reg <= "00000000"; else if ( write='1' and addr="01") then ctl_reg <= datain; end if; end if; end if; end process; sel_clk <= ctl_reg(6 downto 5); -- select clk divider o_proc : process (clk) begin if (clk'event and clk='1') then if (rst='1') then oflow <= '0'; else if ( write='1' and addr="00" and tx_run='1') then oflow <= '1'; elsif ( write='1' and addr="10" and datain(6)='1') then oflow <= '0'; end if; end if; end if; end process; --irq elr_proc : process (clk) begin if (clk'event and clk='1') then if (rst='1') then irq_flag <= '0'; else if (tx_end='1') then irq_flag <= '1'; elsif (addr="10") then irq_flag <= '0'; end if; end if; end if; end process; irq <= irq_flag; flops_proc : process (clk) begin if (clk'event and clk='1') then tx_start_r1 <= tx_start; end if; end process; dvd_proc : process (clk) begin if (clk'event and clk='1') then if (not (tx_run='1') or tx_end='1') then -- generate clk when transfering dvd_ctr <= "00000"; -- 00=8, 01=16, 10=32, 11=64 dvd2 <= '0'; else if (dvd_ctr="00000") then if (sel_clk="00") then dvd_ctr <= "00011"; elsif (sel_clk="01") then dvd_ctr <= "00111"; elsif (sel_clk="10") then dvd_ctr <= "01111"; else dvd_ctr <= "11111"; end if; if (tx_start_r1='0') then dvd2 <= not dvd2; end if; else dvd_ctr <= std_ulogic_vector(unsigned(dvd_ctr)-1); end if; end if; end if; end process; dvd_zero <= '1' when dvd_ctr="00000" else '0'; shift_clk <= dvd_zero and dvd2 and tx_run and not tx_start_r1; shift_clk_negedge <= dvd_zero and not dvd2 and tx_run; with addr select dataout <= shift_reg when "00", ctl_reg when "01", status when "10", "XXXXXXXX" when others; status <= irq_flag & oflow & "000" & tx_run & "00"; scko <= dvd2; -- main state machine process(allclk,rst) -- use allclk variable mdly : integer; begin if rst='0' then if allclk'event and allclk='1' then case st is when "000" => -- delay if mdly<=5 then mdly:=mdly+1; else mdly:=0; end if; if mdly=5 then -- init write<='1'; datain<="10000000"; addr<="01"; mdly:=0; st<="001"; end if; when "001"=> -- transfer "10010111" datain<="10010111"; if irq_flag='0' then addr<="00"; -- wait for irq else addr<="10"; -- addr="00",transfer; addr="10",rese irq_flag st<="010"; end if; when "010"=> datain<="00100101"; if irq_flag='0'then addr<="00"; else addr<="10"; st<="011"; end if; when "011"=> if mdly<=20 then mdly:=mdly+1; else mdly:=0; end if; if mdly=20 then mdly:=0; st<="001"; end if; when others => null; end case; end if; else st<="000"; addr<="00"; datain<="00000000"; end if; end process; end behav;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -