LMK04821的 SPI Driver 24bit 调试(1)

分别为驱动和tb tb_spi_master0_driver.v spi_master0_driver.v LMK04821的最大SCLK 20MHz 结合tb文件可以实现:

  • 两个24bit 有间隔写入slave

  • 10MHz SCLK

接下来的工作:

  1. 把tb文件中的虚拟时钟,改为使用clock ip做一个20MHz clk,那么SCLK 即10MHz

  2. 把tb文件中的给tx_data操作,改为使用fifo ip做fifo_buffer,要实现fifo数据的自动发给spi_master0_driver

  3. 构造顶层top文件,把spi_master0_driver和fifo_buffer包含

    alt text 豆包生成的模块图

https://blog.csdn.net/qq_22168673/article/details/104925474

保存modelsim波形和数据,以及再次打开的方法


`timescale 1ns / 1ps
module tb_spi_master0_driver();

	reg          clk       		;
	reg          rst_n     		;
	reg			 tx_en			;
	reg          tx_de     		;
	reg   [23:0]  tx_data   		;
	
	wire         tx_done   		;
	wire         spi_clk 		;
	wire         spi_cs  		;
	wire         spi_mosi    	;
	
spi_master0_driver u1_spi_master0_driver(
    .clk     	(clk  		) ,
    .rst_n   	(rst_n		) ,

    .tx_en		(tx_en		) ,
	.tx_de   	(tx_de  	) ,
	.tx_data 	(tx_data	) ,
	.tx_done 	(tx_done	) ,

    .spi_clk 	(spi_clk 	) ,
	.spi_cs  	(spi_cs  	) ,
    .spi_mosi	(spi_mosi 	)   	
    );

initial 	clk =	1;
always 	#25 clk	=~clk;

initial begin
	rst_n  	=	0	;
	tx_en	=	0	;
	tx_de   =	0	;
	tx_data =	0	;
	
//释放复位
	#100;
	rst_n = 1;
	#50;
	
// --- 发送第一个字节:8'hA5 (10100101) ---
    // 第一步:锁存数据
    @(posedge clk);
    tx_data = 24'hA5A5A5;
    tx_de = 1;      // 给一个周期的锁存脉冲
    @(posedge clk);
    tx_de = 0;	
// 第二步:启动发送
    @(posedge clk);
    tx_en = 1;      // 拉高使能	
// 第三步:等待发送完成 (tx_done)
    wait(tx_done == 1);
	@(posedge clk);
    tx_en = 0;
	
	#60;
	@(posedge clk);
    tx_data = 24'hCDCDCD;
    tx_de = 1;      
    @(posedge clk);
    tx_de = 0;	

    @(posedge clk);
    tx_en = 1;      

    wait(tx_done == 1);
	@(posedge clk);
    tx_en = 0;

    #500;
    $display("Simulation Finished!");
    $stop;
end

endmodule



`timescale 1ns / 1ps
//master0 模式下 空闲电平为低电平
//spi_master0_driver要负责:
/* 
1.数据锁存
2.在开始时拉低片选CS,结束时拉高片选CS
3.数据准备和数据的发收 
*/

module spi_master0_driver(
    input               clk       		,
    input               rst_n     		,

    input				tx_en			,
	input               tx_de     		,
	input       [23:0]  tx_data   		,
	output  reg         tx_done   		,

//	input				rx_en			,
//	output				rx_de			,
//	output  	 [7:0]  rx_data 		,
//	output  reg         rx_done   		,

    output  reg         spi_clk 		,
	output  reg         spi_cs  		,
//  input               spi_miso  		,
    output  reg         spi_mosi    	
    );
	
reg [23:0]		tx_latch        ;
reg [23:0]   	tx_state        ; 

//数据锁存
always@(posedge clk)
    if(!rst_n)
		tx_latch <= 0;
	else if(tx_de==1'b1)
		tx_latch <= tx_data;	
	else
		tx_latch <= tx_latch;
//开始发送 即spi_cs拉低
always@(posedge clk)
    if(!rst_n)
		spi_cs <= 1'b1;
	else if(tx_en==1'b1)
		spi_cs <= 1'b0;
	else
		spi_cs <= 1'b1;

//状态机 24bit数据连续写
always@(posedge clk)
    if(!rst_n)
        begin
            spi_clk   	<=  0    ;
            spi_mosi  	<=  0    ;
            tx_done     <=  0    ;
			tx_state  	<=  0    ;	
        end
	else if(tx_en==1'b1)
		case(tx_state)
			2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46:  //制造spi_clk上升沿采样时刻
				begin
					spi_clk   <=  1'b1                	;
					tx_state  <=  tx_state + 1'b1   	;
				end			
			0:  //打一拍确保CS第一次拉低时的时序
				begin
					spi_mosi  <=  1'b0        			;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			1:  //数据放到spi_mosi寄存器,等待clk上升沿总线mosi采样
				begin
					spi_mosi  <=  tx_latch[23]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			3: 	//数据放到spi_mosi寄存器,等待clk上升沿总线mosi采样
				begin
					spi_mosi  <=  tx_latch[22]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			5: 	//数据放到spi_mosi寄存器,等待clk上升沿总线mosi采样
				begin
					spi_mosi  <=  tx_latch[21]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end 
			7:  //数据放到spi_mosi寄存器,等待clk上升沿总线mosi采样
				begin
					spi_mosi  <=  tx_latch[20]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end 
			9: 	//数据放到spi_mosi寄存器,等待clk上升沿总线mosi采样
				begin
					spi_mosi  <=  tx_latch[19]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end                            
			11:	//数据放到spi_mosi寄存器,等待clk上升沿总线mosi采样
				begin
					spi_mosi  <=  tx_latch[18]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end 
			13: //数据放到spi_mosi寄存器,等待clk上升沿总线mosi采样
				begin
					spi_mosi  <=  tx_latch[17]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end 
			15: //数据放到spi_mosi寄存器,等待clk上升沿总线mosi采样
				begin
					spi_mosi  <=  tx_latch[16]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			17:
				begin
					spi_mosi  <=  tx_latch[15]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			19:
				begin
			    	spi_mosi  <=  tx_latch[14]        	;
			    	spi_clk   <=  1'b0                	;
			    	tx_state  <=  tx_state + 1'b1   	;
			    end
			21:
				begin
			    	spi_mosi  <=  tx_latch[13]        	;
			    	spi_clk   <=  1'b0                	;
			    	tx_state  <=  tx_state + 1'b1   	;
			    end
			23:
				begin
			    	spi_mosi  <=  tx_latch[12]        	;
			    	spi_clk   <=  1'b0                	;
			    	tx_state  <=  tx_state + 1'b1   	;
			    end
			25:
				begin
			    	spi_mosi  <=  tx_latch[11]        	;
			    	spi_clk   <=  1'b0                	;
			    	tx_state  <=  tx_state + 1'b1   	;
			    end
			27:
				begin
					spi_mosi  <=  tx_latch[10]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end

			29:
				begin
					spi_mosi  <=  tx_latch[9]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end	
			31:
				begin
					spi_mosi  <=  tx_latch[8]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			33:
				begin
					spi_mosi  <=  tx_latch[7]        	;		
			    	spi_clk   <=  1'b0                	;
			    	tx_state  <=  tx_state + 1'b1   	;
			    end
			35:
				begin
					spi_mosi  <=  tx_latch[6]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			37:
				begin
					spi_mosi  <=  tx_latch[5]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			39:
				begin
					spi_mosi  <=  tx_latch[4]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			41:
				begin
					spi_mosi  <=  tx_latch[3]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			43:
				begin
					spi_mosi  <=  tx_latch[2]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			45:
				begin
					spi_mosi  <=  tx_latch[1]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			47:
				begin
					spi_mosi  <=  tx_latch[0]        	;
					spi_clk   <=  1'b0                	;
					tx_state  <=  tx_state + 1'b1   	;
				end
			48: //3个字节发送完的标志tx_done
				begin
					spi_clk   <=  1'b1                	;
					tx_state  <=  tx_state + 1'b1   	;
					tx_done   <=  1'b1                	;   
				end
			49: //发送完 回到master0默认的clk mosi 低电平
				begin
					spi_mosi  <=  1'b0        			;
					spi_clk   <=  1'b0                	;
					tx_state  <=  0   					;
					tx_done   <=  1'b0                	;
				end
			default:
				begin
					spi_mosi  <=  1'b0        			;
					spi_clk   <=  1'b0                	;
					tx_state  <=  0   					;
					tx_done   <=  1'b0                	;
				end
		endcase
    else
        begin
            tx_state  <=  0    ;
            tx_done	  <=  0    ;
            spi_clk   <=  0    ;
            spi_mosi  <=  0    ;
        end 
		
endmodule

alt text


本文章使用limfx的vscode插件快速发布