⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi_master_tb.vhd

📁 SPI BUS VHDL实现
💻 VHD
📖 第 1 页 / 共 3 页
字号:
        -- through all combinations of CPHA and CPOL
        for i in 0 to 3 loop
            -- setup CLKDIV
            -- variable I will loop through CLKDIV
            -- set CLKDIV according to value of I
            case i is
                when 0 =>
                    clkdiv <= "00";
                when 1 => 
                    clkdiv <= "01";
                when 2 =>
                    clkdiv <= "10";
                when 3 =>
                    clkdiv <= "11";
                when others =>
                    clkdiv <= "00";
            end case;
            
            -- enable spi interface logic and interrupts
            spien <= '1';
            inten <= '1';
            
            -- variable J will loop through CPHA and CPOL
            -- set RCV_CPOL, SLAVE_CPHA, SLAVE_CPOL based on CPHA and CPOL
            for j in 0 to 3 loop
                case j is
                    when 0 =>
                        cpha <= '0';
                        cpol <= '0';
                        rcv_cpol <= '1';    -- =1 when cpha = cpol
                        slave_cpha <= '0';  -- must match cpha
                        slave_cpol <= '0';  -- must match cpol
                    when 1 => 
                        cpha <= '0';
                        cpol <= '1';
                        rcv_cpol <= '0';    -- =0 when cpha <> cpol
                        slave_cpha <= '0';  -- must match cpha
                        slave_cpol <= '1';  -- must match cpol
                    when 2 =>
                        cpha <= '1';
                        cpol <= '0';
                        rcv_cpol <= '0';    -- =0 when cpha <> cpol
                        slave_cpha <= '1';  -- must match cpha
                        slave_cpol <= '0';  -- must match cpol
                    when 3 =>
                        cpha <= '1';
                        cpol <= '1';
                        rcv_cpol <= '1';    -- =1 when cpha = cpol
                        slave_cpha <= '1';  -- must match cpha
                        slave_cpol <= '1';  -- must match cpol
                    when others =>
                        cpha <= '0';
                        cpol <= '0';
                        rcv_cpol <= '1';    -- =1 when cpha = cpol
                        slave_cpha <= '0';  -- must match cpha
                        slave_cpol <= '0';  -- must match cpol
                end case;           
        
                -- wait for a clock signal to allow signal assignments to 
                -- take effect
                wait until clk'event and clk = '1';
                
 
                
                -- Now need to call the state machine to write registers
                -- to set up the SPI transaction, then need to generate the START signal

                -- Variable K will loop through the register writes to set up the 
                -- control registers, slave select registers, first data word, 
                -- and assertion of the START  signal
                write <= '1';
                for k in 0 to 3 loop
                    -- first setup data and address
                    case k is
                        when 0 =>
                            -- write to control register
                            uc_addr <= BASE_ADDR & SPICR_ADDR;  
                            -- first set SPIEN, INTEN, CLKDIV, CPHA, CPOL,
                            -- and RCV_CPOL without setting start
                            uc_data <= spien & inten & '0' & clkdiv &
                                cpha & cpol & rcv_cpol;
                        when 1 =>
                            -- write to slave select register
                            uc_addr <= BASE_ADDR & SPISSR_ADDR;
                            -- set slave select based on test
                            -- first set slave select to all zeros
                            -- then set the bit indexed by test loops
                            uc_data <= (others => '0');
                            uc_data(4*(i mod 2) +j) <= '1';
                        when 2 =>
                            -- now write first data to be transmitted
                            uc_addr <= BASE_ADDR & SPITR_ADDR;
                            uc_data <= TST_DATA_OUT(0);
                        when 3 =>
                            -- now set start in the control register
                            uc_addr <= BASE_ADDR & SPICR_ADDR;
                            uc_data <= spien & inten & '1' & clkdiv &
                                cpha & cpol & rcv_cpol;
                        when others =>
                            uc_addr <= (others => '0');
                            uc_data <= (others => '0');
                    end case;
                
                    -- wait a clock signal for signal assignments to take affect
                    wait until clk'event and clk = '1';
                    
                    -- now signal uC state machine to write to SPI interface
                    go <= '1';
                    wait until clk'event and clk = '1';
                    wait until clk'event and clk = '1';
                    go <= '0';
                    wait until uc_done = '1';
                end loop;

                -- wait for INT_N from the SPI interface to indicate that the XMIT register
                -- is empty.
                -- then write data to the transmit data register for transfer over SPI
                -- and read data from the receive data register (if data is there)
                for k in 0 to 3 loop
                    if int_n = '1' then
                        -- wait for interrupt
                        wait until int_n = '0'; 
                    end if; 
            
                    -- interrupt has occurred, read status register
                    uc_addr <= BASE_ADDR & SPISR_ADDR;
                    write <= '0';
                    go <= '1';
                    wait until clk'event and clk ='1';
                    wait until clk'event and clk = '1';
                    go <= '0';
                    wait until uc_done = '1';
            
                    -- Determine cause of interrupt
                    -- if SPIERR is asserted, write a '0' to the bit to clear it
                    -- wait for this bit to clear (meaning that error went away)
                    -- then reset SPI logic
                    if data_in (SPIERR_BIT) = '1' then
                        while data_in(SPIERR_BIT) = '1' loop
                            -- SPIERR - 
                            -- reset this bit and the interrupt  by writing a '0' to
                            -- this bit in SPISR
                            uc_addr <= BASE_ADDR & SPISR_ADDR;
                            uc_data <= (others => '0');
    
                            write <= '1';
                            go <= '1';
                            wait until clk'event and clk = '1';
                            wait until clk'event and clk = '1';
                            go <= '0';
                            wait until uc_done = '1';
        
                        
                            -- now read status register again to see if 
                            -- SPIERR has gone away
                            uc_addr <= BASE_ADDR & SPISR_ADDR;
                            write <= '0';
                            go <= '1';
                            wait until clk'event and clk ='1';
                            wait until clk'event and clk = '1';
                            go <= '0';
                            wait until uc_done = '1';
                        end loop;
                        
                        
                        -- now reset logic by negating SPIEN in 
                        -- control register
                        uc_addr <= BASE_ADDR & SPICR_ADDR;
                        uc_data <= '0' & inten & '1' & clkdiv &
                                cpha & cpol & rcv_cpol;
                        write <= '1';
                        go <= '1';
                        wait until clk'event and clk = '1';
                        wait until clk'event and clk = '1';
                        go <= '0';
                        wait until uc_done = '1';
                        
                        
                        -- set signal that will exit loop
                        exit_loop <= '1';
                        
                    else 
                        exit_loop <= '0';
                        if data_in(XMIT_EMPTY_BIT) = '1' then
                            -- xmit empty asserted
                            -- write new transmit data
                            -- unless last data has already been written
                            -- if last data has been written, write to control register
                            -- to negate start
            
                            if k = 3 then
                                -- all data words have been written to SPITR,
                                -- write to control register to negate start
                                uc_addr <= BASE_ADDR & SPICR_ADDR;
                                uc_data <= spien & inten & '0' & clkdiv &
                                cpha & cpol & rcv_cpol;
                            else
                                -- write next data word to be transmitted
                                -- to SPITR
                                uc_addr <= BASE_ADDR & SPITR_ADDR;
                                uc_data <= TST_DATA_OUT(k+1);
                            end if;
                        
                            write <= '1';
                            go <= '1';
                            wait until clk'event and clk = '1';
                            wait until clk'event and clk = '1';
                            go <= '0';
                            wait until uc_done = '1';
                        end if;
            
                        -- if receive full, then read receive register
                        -- Note, first time through loop, receive register will not
                        -- be full because XMIT empty starts the loop and will
                        -- occur at the beginning of the first transaction
                        if data_in(RCV_FULL_BIT) = '1' then
                            if i=0 and j=0 and k=0 then
                                -- first test
                                -- error because receive register should not
                                -- be full first time through the loop on first test
                                error <= '1';
                            else
                                -- read receive register data
                                uc_addr <= BASE_ADDR & SPIRR_ADDR;
                                write <= '0';
                                go <= '1';
                                wait until clk'event and clk = '1';
                                wait until clk'event and clk = '1';
                                go <= '0';
                                wait until uc_done = '1';
                            
                                -- if i=0, j=0, k=1 first received data is data from slave
                                if i=0 and j=0 and k=1 then
                                    if data_in = CE then
                                        error <= '0';
                                    else
                                        error <= '1';
                                    end if;
                                elsif k=0 then
                                    -- for all tests after the first, the slave
                                    -- sends out last data received
                                    -- check for data of TST_DATA_OUT(2)
                                    if data_in = TST_DATA_OUT(2) then
                                        error <= '0';
                                    else
                                        error <= '1';
                                    end if;
                                elsif k=1 then
                                    if data_in = TST_DATA_OUT(3) then
                                        error <= '0';
                                    else
                                        error <= '1';
                                    end if;
                                else
                                    if data_in = TST_DATA_OUT(k-2) then
                                        error <= '0';
                                    else
                                        error <= '1';
                                    end if;
                                end if;
                            end if;
                            
                        end if; 
                    end if;
                end loop;

                if exit_loop = '0' then
                    if int_n = '1'  then
                        -- wait for interrupt indicating that rcv register is full
                        -- for last data word
                        wait until int_n = '0'; 
                    end if; 

                    -- read the receive data register 
                    write <= '0';
                    uc_addr <= BASE_ADDR & SPIRR_ADDR;
                    go <= '1';
                    wait until clk'event and clk = '1';
                    wait until clk'event and clk = '1';
                    go <= '0';
                    wait until uc_done = '1';
                end if;
        
                -- Before exitying the test, read the status register SPISR
                -- to insure that the bus is not busy and that this test
                -- has completed
                write <= '0';
                uc_addr <= BASE_ADDR & SPISR_ADDR;
                go <= '1';
                wait until clk'event and clk ='1';
                wait until clk'event and clk ='1';

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -