DAC7512配置 spi通信 verilog

spi通信相关内容大家可以找找,然后我以DAC7512,进行spi书写

下边是代码

module dac7512_dinayuan(
    input clk,          // 输入时钟
    input rst_n,        // 复位信号
    input start,        // 启动信号
    input [15:0] data_in,  // 输入数据
 
    // DAC7512输入
    output reg SCLK,    // 时钟信号
    output reg DIN,     // 输入数据信号
    output reg CS,      // 芯片选择信号
    
    //测试接口
    //output reg en,
    //output reg [6:0] SCLK_CNT,
    //output reg cnt_flag,
    
    output reg done     // 完成信号
    );
    
    //reg done;
    reg en;              // 使能信号
    reg [3:0] cnt;       // 分频计数
    reg [6:0] SCLK_CNT;  // 输出时钟计数
    reg cnt_flag;        // 计数标志
    reg [15:0] data_out; // 输出数据
	reg en1;			 //使能信号寄存1
	reg en2;             //使能信号寄存2
	wire pos;             //抓取到的使能信号的上升沿
 
    parameter cnt_threshold  = 4;//时钟分频阈值,
                                //输出时钟频率为输入时钟频率的1/(cnt_threshold+1)
								
	//使能信号上升沿检测
	    always @(posedge clk or negedge rst_n)
    begin
        if (!rst_n)begin
            en1 <= 1'b0; 
			en2 <= 1'b0;
		end
        else begin
            en1 <= en;   // 使能信号锁存
			en2 <= en1;
		end
    end
	
	 assign pos=en1&(!en2);
 
    // 接收数据
    always @(posedge clk or negedge rst_n)
    begin
        if (!rst_n)
            data_out <= 16'b0;     
        else 
            data_out <= data_in;   // 在启动时加载输入数据  
    end
	
    // 使能信号
    always @(posedge clk or negedge rst_n)
    begin
        if (!rst_n)
            en <= 1'b0;            
        else if (start)
            en <= 1'b1;            // 在启动时使能信号为高电平
        else if (done)
            en <= 1'b0;            // 在传输完成后禁用使能信号
        else
            en <= en;              
    end
    // 分频计数
    always @(posedge clk or negedge rst_n)
    begin
        if (!rst_n)
        begin
            cnt <= 4'b0;           
            cnt_flag <= 1'b0;      
        end
        else if (en)
        begin
            if (cnt == cnt_threshold)
            begin
                cnt <= 4'b0;       // 达到分频阈值时清零分频计数
                cnt_flag <= 1'b1;  // 设置计数标志
            end
            else
            begin
                cnt <= cnt + 4'b1;  // 增加分频计数
                cnt_flag <= 1'b0;  // 清零计数标志
            end
        end
        else
            cnt <= 0;              // 禁用时清零分频计数
    end
 
    // 输出时钟计数
    always @(posedge clk or negedge rst_n)
    begin
        if (!rst_n)
            SCLK_CNT <= 7'b0;      
        else if (en)
        begin
            if (cnt_flag && (SCLK_CNT == 7'd32))
                SCLK_CNT <= 7'b0;     // 达到输出时钟计数阈值时清零计数
            else if (cnt_flag)
                SCLK_CNT <= SCLK_CNT + 1'b1;  // 增加输出时钟计数
            else
                SCLK_CNT <= SCLK_CNT;  // 其他情况下保持输出时钟计数不变
        end
        else
            SCLK_CNT <= 0;           // 禁用时清零输出时钟计数
    end
 
    // 开启数据传输,线性序列机,每个时钟周期按照固定的步骤依次执行
	//always @(posedge clk or negedge rst_n)
   // begin
       // if (!rst_n)begin
           // DIN <= 1'b1;
           // CS <= 1'b1;
        //end                          
       // else if(pos)begin
			//DIN <= data_out[15];
			//CS <= 1'b0;
		//end
	//end
		
    always @(posedge clk or negedge rst_n)
    begin
        if (!rst_n)
        begin
            SCLK <= 1'b1;            
            DIN <= 1'b1;             
            CS <= 1'b1;             
        end
        else if (en)
        begin
            if (cnt_flag)
            begin
                case (SCLK_CNT)
					7'd0: begin CS <= 1'b0;  DIN <= data_out[15]; end//CS <= 1'b0;
                    7'd2: begin SCLK <= 1'b1; DIN <= data_out[14]; end
                    7'd4: begin SCLK <= 1'b1; DIN <= data_out[13]; end
                    7'd6: begin SCLK <= 1'b1; DIN <= data_out[12]; end
                    7'd8: begin SCLK <= 1'b1; DIN <= data_out[11]; end
                    7'd10: begin SCLK <= 1'b1; DIN <= data_out[10]; end
                    7'd12: begin SCLK <= 1'b1; DIN <= data_out[9]; end
                    7'd14: begin SCLK <= 1'b1; DIN <= data_out[8]; end
                    7'd16: begin SCLK <= 1'b1; DIN <= data_out[7]; end
                    7'd18: begin SCLK <= 1'b1; DIN <= data_out[6]; end
                    7'd20: begin SCLK <= 1'b1; DIN <= data_out[5]; end
                    7'd22: begin SCLK <= 1'b1; DIN <= data_out[4]; end
                    7'd24: begin SCLK <= 1'b1; DIN <= data_out[3]; end
                    7'd26: begin SCLK <= 1'b1; DIN <= data_out[2]; end
                    7'd28: begin SCLK <= 1'b1; DIN <= data_out[1]; end
                    7'd30: begin SCLK <= 1'b1; DIN <= data_out[0]; end
                    7'd1,7'd3,7'd5,7'd7,7'd9,7'd11,7'd13,7'd15,7'd17,
                    7'd19,7'd21,7'd23,7'd25,7'd27,7'd29,7'd31: begin SCLK <= 1'b0; end
                    7'd32: begin SCLK <= 1'b1;CS <= 1'b1; end // 全部数据输出后,cs信号马上拉高
                endcase
            end
            else ;
        end
        else
        begin
            SCLK <= 1'b1;  
            DIN <= 1'b1;   
            CS <= 1'b1;   
        end
    end
    // 传输完成
    always @(posedge clk or negedge rst_n)
    begin
        if (!rst_n)
            done <= 1'b0;  
        else if (cnt_flag && (SCLK_CNT == 7'd32))
            done <= 1'b1;  // 达到输出时钟计数阈值时设置完成信号为高电平
        else
            done <= 1'b0;  
    end
       
endmodule

代码是子模块,一些输入在顶层模块中,仿真过没问题。

参考大哥的文章:FPGA DAC模块 SPI通信_fpga spi通信-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_42565324/article/details/131097074?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170176795616777224459049%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=170176795616777224459049&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-131097074-null-null.142^v96^pc_search_result_base6&utm_term=DAC8830&spm=1018.2226.3001.4187

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值