Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Test bench question

Status
Not open for further replies.

Kgonz

Newbie level 5
Joined
Mar 9, 2023
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
221
Hello I am trying to create a testbench for this VHDL code of an SPI slave that I found online for verification and so that i can implement it into a project that I'm working on. I've gotten my testbench to compile and run and to drive signals but the data transfer and all the MOSI and MISO lines aren't working the way the author verified it in the website. any help is appreciated. the author verified through the website so I know the reason it doesn't work has to do with the testbench i wrote

this is a link to the website where I got the SPI slave

https://forum.digikey.com/t/spi-slave-vhdl/12721

SPI SLAVE

  1. --------------------------------------------------------------------------------

  2. --

  3. -- FileName: spi_slave.vhd

  4. -- Dependencies: none

  5. -- Design Software: Quartus Prime Version 17.0.0 Build 595 SJ Lite Edition

  6. --

  7. -- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY

  8. -- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT

  9. -- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A

  10. -- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY

  11. -- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL

  12. -- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF

  13. -- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS

  14. -- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),

  15. -- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.

  16. --

  17. -- Version History

  18. -- Version 1.0 7/5/2012 Scott Larson

  19. -- Initial Public Release

  20. -- Version 1.1 11/27/2012 Scott Larson

  21. -- Added an asynchronous active low reset

  22. -- Version 1.2 5/7/2019 Scott Larson

  23. -- Modified architecture slightly to make it synthesizable with more tools

  24. --

  25. --------------------------------------------------------------------------------



  26. LIBRARY ieee;

  27. USE ieee.std_logic_1164.all;

  28. USE ieee.std_logic_arith.all;



  29. ENTITY spi_slave IS

  30. GENERIC(

  31. cpol : STD_LOGIC := '0'; --spi clock polarity mode

  32. cpha : STD_LOGIC := '0'; --spi clock phase mode

  33. d_width : INTEGER := 8); --data width in bits

  34. PORT(

  35. sclk : IN STD_LOGIC; --spi clk from master

  36. reset_n : IN STD_LOGIC; --active low reset

  37. ss_n : IN STD_LOGIC; --active low slave select

  38. mosi : IN STD_LOGIC; --master out, slave in

  39. rx_req : IN STD_LOGIC; --'1' while busy = '0' moves data to the rx_data output

  40. st_load_en : IN STD_LOGIC; --asynchronous load enable

  41. st_load_trdy : IN STD_LOGIC; --asynchronous trdy load input

  42. st_load_rrdy : IN STD_LOGIC; --asynchronous rrdy load input

  43. st_load_roe : IN STD_LOGIC; --asynchronous roe load input

  44. tx_load_en : IN STD_LOGIC; --asynchronous transmit buffer load enable

  45. tx_load_data : IN STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --asynchronous tx data to load

  46. trdy : BUFFER STD_LOGIC := '0'; --transmit ready bit

  47. rrdy : BUFFER STD_LOGIC := '0'; --receive ready bit

  48. roe : BUFFER STD_LOGIC := '0'; --receive overrun error bit

  49. rx_data : OUT STD_LOGIC_VECTOR(d_width-1 DOWNTO 0) := (OTHERS => '0'); --receive register output to logic

  50. busy : OUT STD_LOGIC := '0'; --busy signal to logic ('1' during transaction)

  51. miso : OUT STD_LOGIC := 'Z'); --master in, slave out

  52. END spi_slave;



  53. ARCHITECTURE logic OF spi_slave IS

  54. SIGNAL mode : STD_LOGIC; --groups modes by clock polarity relation to data

  55. SIGNAL clk : STD_LOGIC; --clock

  56. SIGNAL bit_cnt : STD_LOGIC_VECTOR(d_width+8 DOWNTO 0); --'1' for active transaction bit

  57. SIGNAL wr_add : STD_LOGIC; --address of register to write ('0' = receive, '1' = status)

  58. SIGNAL rd_add : STD_LOGIC; --address of register to read ('0' = transmit, '1' = status)

  59. SIGNAL rx_buf : STD_LOGIC_VECTOR(d_width-1 DOWNTO 0) := (OTHERS => '0'); --receiver buffer

  60. SIGNAL tx_buf : STD_LOGIC_VECTOR(d_width-1 DOWNTO 0) := (OTHERS => '0'); --transmit buffer

  61. BEGIN

  62. busy <= NOT ss_n; --high during transactions

  63. --adjust clock so writes are on rising edge and reads on falling edge

  64. mode <= cpol XOR cpha; --'1' for modes that write on rising edge

  65. WITH mode SELECT

  66. clk <= sclk WHEN '1',

  67. NOT sclk WHEN OTHERS;



  68. --keep track of miso/mosi bit counts for data alignmnet

  69. PROCESS(ss_n, clk)

  70. BEGIN

  71. IF(ss_n = '1' OR reset_n = '0') THEN --this slave is not selected or being reset

  72. bit_cnt <= (conv_integer(NOT cpha) => '1', OTHERS => '0'); --reset miso/mosi bit count

  73. ELSE --this slave is selected

  74. IF(rising_edge(clk)) THEN --new bit on miso/mosi

  75. bit_cnt <= bit_cnt(d_width+8-1 DOWNTO 0) & '0'; --shift active bit indicator

  76. END IF;

  77. END IF;

  78. END PROCESS;



  79. PROCESS(ss_n, clk, st_load_en, tx_load_en, rx_req)

  80. BEGIN

  81. --write address register ('0' for receive, '1' for status)

  82. IF(bit_cnt(1) = '1' AND falling_edge(clk)) THEN

  83. wr_add <= mosi;

  84. END IF;



  85. --read address register ('0' for transmit, '1' for status)

  86. IF(bit_cnt(2) = '1' AND falling_edge(clk)) THEN

  87. rd_add <= mosi;

  88. END IF;

  89. --trdy register

  90. IF((ss_n = '1' AND st_load_en = '1' AND st_load_trdy = '0') OR reset_n = '0') THEN

  91. trdy <= '0'; --cleared by user logic or reset

  92. ELSIF(ss_n = '1' AND ((st_load_en = '1' AND st_load_trdy = '1') OR tx_load_en = '1')) THEN

  93. trdy <= '1'; --set when tx buffer written or set by user logic

  94. ELSIF(falling_edge(clk)) THEN

  95. IF(wr_add = '1' AND bit_cnt(9) = '1') THEN

  96. trdy <= mosi; --new value written over spi bus

  97. ELSIF(rd_add = '0' AND bit_cnt(d_width+8) = '1') THEN

  98. trdy <= '0'; --clear when transmit buffer read

  99. END IF;

  100. END IF;

  101. --rrdy register

  102. IF((ss_n = '1' AND ((st_load_en = '1' AND st_load_rrdy = '0') OR rx_req = '1')) OR reset_n = '0') THEN

  103. rrdy <= '0'; --cleared by user logic or rx_data has been requested or reset

  104. ELSIF(ss_n = '1' AND st_load_en = '1' AND st_load_rrdy = '1') THEN

  105. rrdy <= '1'; --set when set by user logic

  106. ELSIF(falling_edge(clk)) THEN

  107. IF(wr_add = '1' AND bit_cnt(10) = '1') THEN

  108. rrdy <= mosi; --new value written over spi bus

  109. ELSIF(wr_add = '0' AND bit_cnt(d_width+8) = '1') THEN

  110. rrdy <= '1'; --set when new data received

  111. END IF;

  112. END IF;

  113. --roe register

  114. IF((ss_n = '1' AND st_load_en = '1' AND st_load_roe = '0') OR reset_n = '0') THEN

  115. roe <= '0'; --cleared by user logic or reset

  116. ELSIF(ss_n = '1' AND st_load_en = '1' AND st_load_roe = '1') THEN

  117. roe <= '1'; --set by user logic

  118. ELSIF(falling_edge(clk)) THEN

  119. IF(rrdy = '1' AND wr_add = '0' AND bit_cnt(d_width+8) = '1') THEN

  120. roe <= '1'; --set by actual overrun

  121. ELSIF(wr_add = '1' AND bit_cnt(11) = '1') THEN

  122. roe <= mosi; --new value written by spi bus

  123. END IF;

  124. END IF;

  125. --receive registers

  126. --write to the receive register from master

  127. IF(reset_n = '0') THEN

  128. rx_buf <= (OTHERS => '0');

  129. ELSE

  130. FOR i IN 0 TO d_width-1 LOOP

  131. IF(wr_add = '0' AND bit_cnt(i+9) = '1' AND falling_edge(clk)) THEN

  132. rx_buf(d_width-1-i) <= mosi;

  133. END IF;

  134. END LOOP;

  135. END IF;

  136. --fulfill user logic request for receive data

  137. IF(reset_n = '0') THEN

  138. rx_data <= (OTHERS => '0');

  139. ELSIF(ss_n = '1' AND rx_req = '1') THEN

  140. rx_data <= rx_buf;

  141. END IF;



  142. --transmit registers

  143. IF(reset_n = '0') THEN

  144. tx_buf <= (OTHERS => '0');

  145. ELSIF(ss_n = '1' AND tx_load_en = '1') THEN --load transmit register from user logic

  146. tx_buf <= tx_load_data;

  147. ELSIF(rd_add = '0' AND bit_cnt(7 DOWNTO 0) = "00000000" AND bit_cnt(d_width+8) = '0' AND rising_edge(clk)) THEN

  148. tx_buf(d_width-1 DOWNTO 0) <= tx_buf(d_width-2 DOWNTO 0) & tx_buf(d_width-1); --shift through tx data

  149. END IF;



  150. --miso output register

  151. IF(ss_n = '1' OR reset_n = '0') THEN --no transaction occuring or reset

  152. miso <= 'Z';

  153. ELSIF(rising_edge(clk)) THEN

  154. IF(rd_add = '1') THEN --write status register to master

  155. CASE bit_cnt(10 DOWNTO 8) IS

  156. WHEN "001" => miso <= trdy;

  157. WHEN "010" => miso <= rrdy;

  158. WHEN "100" => miso <= roe;

  159. WHEN OTHERS => NULL;

  160. END CASE;

  161. ELSIF(rd_add = '0' AND bit_cnt(7 DOWNTO 0) = "00000000" AND bit_cnt(d_width+8) = '0') THEN

  162. miso <= tx_buf(d_width-1); --send transmit register data to master

  163. END IF;

  164. END IF;

  165. END PROCESS;

  166. END logic;



SPI Slave TestBench



  1. library IEEE;

  2. use IEEE.Std_logic_1164.all;



  3. entity spi_slavetestbench is

  4. end spi_slavetestbench;



  5. architecture bench of spi_slavetestbench is



  6. component spi_slave

  7. port

  8. (sclk, reset_n,ss_n,mosi,rx_req,st_load_en,st_load_trdy,st_load_rrdy,st_load_roe,tx_load_en: in std_logic;

  9. tx_load_data : IN STD_LOGIC_VECTOR;

  10. rx_data : OUT STD_LOGIC_VECTOR;

  11. busy, miso : out std_logic;

  12. trdy,rrdy,roe : BUFFER std_logic

  13. );

  14. end component;



  15. constant d_width : INTEGER := 8;

  16. signal sclk, reset_n,ss_n,mosi,rx_req,st_load_en,st_load_trdy,st_load_rrdy,st_load_roe,tx_load_en: std_logic;

  17. signal busy, miso: std_logic;

  18. signal tx_load_data: STD_LOGIC_VECTOR(d_width-1 DOWNTO 0);

  19. signal rx_data : STD_LOGIC_VECTOR(d_width-1 DOWNTO 0) := (OTHERS => '0');

  20. signal trdy,rrdy,roe : std_logic;

  21. constant clock_period: time := 10 ns;

  22. SIGNAL mode : STD_LOGIC; --groups modes by clock polarity relation to data

  23. SIGNAL clk : STD_LOGIC; --clock

  24. SIGNAL bit_cnt : STD_LOGIC_VECTOR(d_width+8 DOWNTO 0); --'1' for active transaction bit

  25. SIGNAL wr_add : STD_LOGIC; --address of register to write ('0' = receive, '1' = status)

  26. SIGNAL rd_add : STD_LOGIC; --address of register to read ('0' = transmit, '1' = status)

  27. SIGNAL rx_buf : STD_LOGIC_VECTOR(d_width-1 DOWNTO 0) := (OTHERS => '0'); --receiver buffe SIGNAL tx_buf : STD_LOGIC_VECTOR(d_width-1 DOWNTO 0) := (OTHERS => '0'); --transmit buffer

  28. signal stop_the_clock: boolean;







  29. begin

  30. DUT : entity work.spi_slave

  31. port map (

  32. sclk => sclk,

  33. reset_n => reset_n,

  34. ss_n => ss_n,

  35. mosi => mosi,

  36. rx_req => rx_req,

  37. st_load_en => st_load_en,

  38. st_load_trdy => st_load_trdy,

  39. st_load_rrdy => st_load_rrdy,

  40. st_load_roe => st_load_roe,

  41. tx_load_en => tx_load_en,

  42. tx_load_data => tx_load_data,

  43. rx_data => rx_data,

  44. busy => busy,

  45. trdy => trdy,

  46. rrdy => rrdy,

  47. roe => roe,

  48. miso => miso

  49. );



  50. STIM: process -- stimulus

  51. begin



  52. wait for clock_period;

  53. reset_n <= '1';

  54. ss_n <= '1';

  55. wait for clock_period;

  56. reset_n <= '1';

  57. ss_n <= '0';

  58. tx_load_en <= '1';

  59. tx_load_data <= "10101010";

  60. wait for clock_period*40;

  61. stop_the_clock <= true;

  62. wait;

  63. end process;



  64. process -- clock generation

  65. begin

  66. while not stop_the_clock loop

  67. clk <= '0';

  68. wait for clock_period / 2;

  69. clk <= '1';

  70. wait for clock_period / 2;

  71. end loop;

  72. wait;

  73. end process;



  74. process -- clock generation

  75. begin

  76. while not stop_the_clock loop

  77. sclk <= '0';

  78. wait for clock_period / 2;

  79. sclk <= '1';

  80. wait for clock_period / 2;

  81. end loop;

  82. wait;

  83. end process;


  84. end;
waveforms
 

Attachments

  • Screenshot 2023-04-11 115213.png
    Screenshot 2023-04-11 115213.png
    81.9 KB · Views: 86

Aside from the fact that I'm not going to wade through 500 lines of your unformatted, uncommented code, I would suggest that you are not initializing something properly. It looks like you never assert your reset_n.

In the future, provide a little more information. Just saying "it isn't working" and throwing 500 lines of code at us is not a good way to get any help. Tell us what you're expecting vs. what you're seeing.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top