`timescale 1ns / 1ps 
module master_spi_tb;  
localparam  BYTES = 8; localparam  TCNT  = BYTES*8*2-1;  
localparam  CPOL = 1; localparam  CPHA = 1;  
reg I_clk; //系统时钟 reg [7:0] i;//计数器,用于产生SPI时钟数量 reg I_rstn; //系统复位 reg I_spi_clk;//SPI时钟 reg I_spi_ss; //SPI的Slave选通信号 reg [3:0]bit_cnt; //bit计数器 reg [7:0]spi_tx_buf; //发送缓存(移位寄存器) reg [7:0]spi_tx_buf_r; //发送化缓存,用于产生测试数据 reg first_data_flag; //是否一个时钟改变数据  
wire O_spi_rvalid; //SPI 数据接收有效,当该信号有效代表接收到一个有效数据 wire [7:0]O_spi_rdata; //SPI读数据 wire I_spi_rx;//SPI数据总线  
//tb模拟的SPI测试数据接到I_spi_rx assign I_spi_rx = spi_tx_buf[7]; //例化SPI 接收模块 uispi_rx# ( .BITS_LEN(8), .CPOL(CPOL), .CPHA(CPHA)  ) I_spi_rxnst( .I_clk(I_clk), .I_rstn(I_rstn), .I_spi_clk(I_spi_clk), .I_spi_rx(I_spi_rx), .I_spi_ss(I_spi_ss), .O_spi_rvalid(O_spi_rvalid), .O_spi_rdata(O_spi_rdata) ); initial begin     I_clk  = 1'b0;     I_rstn = 1'b0;     #100;     I_rstn = 1'b1; end  
always #10   I_clk  = ~I_clk;   //时钟信号翻转,产生系统时钟  
initial begin     #100;     i = 0;          forever begin         I_spi_clk = CPOL; //设置时钟极性         I_spi_ss  = 1; // 设置SPI的SS控制信号         #2000;         I_spi_ss  = 0;         for(i=0;i<TCNT;i=i+1) #1000 I_spi_clk = ~ I_spi_clk; //产生SPI时钟         #2000;         I_spi_ss  = 1;  
    end end  
initial begin         #100;         bit_cnt = 0;         first_data_flag =0;         spi_tx_buf[7:0] = 8'ha0;         spi_tx_buf_r[7:0] = 8'ha0;     forever begin  
//spi ss 控件用于启用传输         wait(I_spi_ss);//spi ss          bit_cnt = 0;         spi_tx_buf[7:0] = 8'ha0;         spi_tx_buf_r[7:0] = 8'ha0;  
        if((CPHA == 1 && CPOL ==0)||(CPHA == 1 && CPOL ==1))//第一个时钟沿改变数据的情况             first_data_flag = 1; //设置first_data_flag=1 下面的发送时序对应情况跳过第一个沿  
//ss低时开始数据传输                   wait(!I_spi_ss);  
        while(!I_spi_ss)begin  
//COPL=0 CPHA=0默认SCLK为低电平,对于发送方,在对于第1个bit数据提前放到总线             if(CPHA == 0 && CPOL ==0)begin               @(negedge I_spi_clk)  begin //每个时钟的下降沿更新需要发送的BIT                 if(bit_cnt == 7)begin//连续发送过程中,8bits 发送完毕后更新数据                     bit_cnt = 0;                     spi_tx_buf_r = spi_tx_buf_r + 1'b1;//产生新的测试数据                     spi_tx_buf = spi_tx_buf_r;//重新跟新发送寄存器                 end                 else begin                      spi_tx_buf = {spi_tx_buf[6:0],1'b0};//数据移位,更新数据                     bit_cnt = bit_cnt + 1'b1;//SPI发送位数计数器                 end              end             end  
//CPHA=0 COPL=1 默认SCLK为高电平,对于发送方,在对于第1个bit数据提前放到总线             if(CPHA == 0 && CPOL ==1)begin               @(posedge I_spi_clk)  begin //每个时钟的上升沿更新需要发送的BIT                 if(bit_cnt == 7)begin //连续发送过程中,8bits 发送完毕后更新数据                     bit_cnt = 0;                     spi_tx_buf_r = spi_tx_buf_r + 1'b1;//产生新的测试数据                     spi_tx_buf = spi_tx_buf_r; //重新跟新发送寄存器                 end                 else begin                     spi_tx_buf = {spi_tx_buf[6:0],1'b0};//数据移位,更新数据                     bit_cnt = bit_cnt + 1'b1;//SPI发送位数计数器                 end              end             end  
 
//CPHA=1 COPL=0 默认SCLK为低电平,对于发送方,在第1个SCLK的跳变沿更新             if(CPHA == 1 && CPOL ==0)begin               @(posedge I_spi_clk)  begin                 if(first_data_flag == 1'b1)begin //第一个时钟沿,由于前面已经提前初始化第一个需要发送的数据,因此,这里跳过第一个跳变沿沿                     first_data_flag = 0;                     //spi_tx_buf[7:0] = 8'ha0;//也可以在第一个跳变沿初始化第一个发送的数据                 end                 else begin                     if(bit_cnt == 7)begin                         bit_cnt = 0;                         spi_tx_buf_r = spi_tx_buf_r + 1'b1;//产生新的测试数据                         spi_tx_buf = spi_tx_buf_r;//重新跟新发送寄存器                     end                     else begin                          spi_tx_buf = {spi_tx_buf[6:0],1'b0}; //数据移位,更新数据                         bit_cnt = bit_cnt + 1'b1;//SPI发送位数计数器                     end                 end              end             end //CPHA=1 COPL=1 默认SCLK为高电平,对于发送方,在第1个SCLK的跳变沿更新             if(CPHA == 1 && CPOL ==1)begin               @(negedge I_spi_clk)  begin                 if(first_data_flag == 1'b1)begin //第一个时钟沿,由于前面已经提前初始化第一个需要发送的数据,因此,这里跳过第一个跳变沿沿                     first_data_flag = 0;                     //spi_tx_buf[7:0] = 8'ha0;//也可以在第一个跳变沿初始化第一个发送的数据                 end                 else begin                     if(bit_cnt == 7)begin                         bit_cnt = 0;                         spi_tx_buf_r = spi_tx_buf_r + 1'b1;//产生新的测试数据                         spi_tx_buf = spi_tx_buf_r;//重新跟新发送寄存器                     end                     else begin                          spi_tx_buf = {spi_tx_buf[6:0],1'b0};//数据移位,更新数据                         bit_cnt = bit_cnt + 1'b1;//SPI发送位数计数器                     end                 end              end             end  
        end     end end  
endmodule  |