基于SPI实现stm32与fpga通信(三)

使用stm32与fpga之间的spi通信,stm32通过fpga控制DAC输出模拟电压,使用三线制。

使用FPGA驱动MS5541,采用3线制,输出时钟(20MHz),片选信号,输出信号,主机端时钟为100MHz,将时钟5分频,然后设置片选信号与并行转串行输出信号在20MHz时钟上升沿输出

inputclk
inputrst

input

start
input

i16_dac_data

output

o_dac_sclk

output

o_dac_cs

output

o_dac_MOSI

module dac_core(
    input				clk,	                                 
    input				rst,	                          
    input				start,
	input	[15:0]		i16_dac_data,	                  
    
	output  wire       	o_dac_sclk,	                       
	output  reg      	o_dac_cs,		           
    output  reg      	o_dac_mosi	           
    );	

reg	                    [5:0]	            tri_cnt;
reg                     [4:0] 	            data_count;
reg                     [15:0]	            i16_dac_data_reg;
wire                                        sclk_posedge;
reg                                         o_dac_sclk_buf;

/**************************************************************************
                            100MHz 5分频
**************************************************************************/
reg		[3:0]	state1;
reg		[3:0]	state2;

always@(posedge clk)
    begin
        if(rst)
            begin
            state1 <= 4'b0000;
            end
        else
            begin
                case(state1)
                    4'b0000: state1 <= 4'b0010;
                    4'b0010: state1 <= 4'b0110;
                    4'b0110: state1 <= 4'b0001;
                    4'b0001: state1 <= 4'b0011;
                    4'b0011: state1 <= 4'b0000;
                    default: state1 <= 4'b0000;
                endcase
            end
    end

always@(negedge clk)
    begin
        if(rst)
            begin
            state2 <= 4'b0 ;
            end
        else
            begin
                case(state2)
                    4'b0000: state2 <= 4'b0010;
                    4'b0010: state2 <= 4'b0110;
                    4'b0110: state2 <= 4'b0001;
                    4'b0001: state2 <= 4'b0011;
                    4'b0011: state2 <= 4'b0000;
                    default: state2 <= 4'b0000;
                endcase
            end
    end
 
assign o_dac_sclk = state1[0] | state2[0];
/******************************************************************************
                                输出时钟边沿   
******************************************************************************/
always@(posedge clk) begin
    if(rst) begin
        o_dac_sclk_buf <= 1'b0;
    end
    else begin
        o_dac_sclk_buf <= o_dac_sclk;
    end
end

assign sclk_posedge = (o_dac_sclk_buf == 1'b0 && o_dac_sclk == 1'b1);
/**************************************************************************
                                 状态转移  
**************************************************************************/  
reg                     [2:0]                       cnt;   
reg                     [2:0]                       state_cur;
reg                     [2:0]                       state_nex;
parameter                                           SM01  =  3'b001,  
                                                    SM02  =  3'b010,  
                                                    SM03  =  3'b100;
always@(posedge clk) begin
    if(rst) begin
        cnt <= 2'd0;
    end
    else begin
        if((state_cur == 3'd0 && cnt <3'd3)) begin
                cnt <= cnt + 1'b1;
        end
        else begin
            cnt <= 3'd0;
        end
    end
end
always@(*) begin
    if(rst) begin
        state_cur       <= 3'd0;
    end
    else begin
        state_cur       <= state_nex;
    end
end
always @(posedge clk) begin         
	if (rst) begin                                 
		o_dac_cs 		<= 1'b1;
		o_dac_mosi		<= 1'b0;
		data_count	    <= 4'd0;
		i16_dac_data_reg<= i16_dac_data;
        state_nex       <= 3'b0;
		tri_done 	    <= 1'b0;
    end
    else begin
        case(state_cur)
            SM01: begin
                o_dac_cs 	        <= 1'b1;
                o_dac_mosi	        <= 1'b0;
                tri_done            <= 1'b0;			
                if(cnt == 3'd3) begin
                    state_nex       <= SM02;
                    i16_dac_data_reg<= i16_dac_data;
                end
            end
            SM02: begin
                tri_done <= 1'b1;
                if (start) begin
                    if(o_dac_cs == 1'b1) begin
                        o_dac_cs 			        <= 1'b0;
                        data_count		            <= 4'd0;
                        o_dac_mosi 	 	            <= i16_dac_data_reg[15];
                        i16_dac_data_reg 	        <= i16_dac_data_reg << 1;
                    end
                    else begin
                        if(sclk_posedge == 1'b1)begin
                            if (data_count < 4'd15) begin
                                o_dac_mosi 	        <= i16_dac_data_reg[15];
                                i16_dac_data_reg    <= i16_dac_data_reg << 1;
                                data_count 	        <= data_count + 4'd1;
                            end
                            else begin
                                data_count <= 2'd0;
                                o_dac_mosi	        <= 1'b0;
                                state_nex	        <= SM03;
                                o_dac_cs 	        <= 1'b1;
                            end
                        end
                        else begin
                                o_dac_cs 			<= o_dac_cs;
                                data_count		    <= data_count;
                                o_dac_mosi 	 	    <= o_dac_mosi;
                                i16_dac_data_reg 	<= i16_dac_data_reg;
                        end
                    end
                end
            end
            SM03: begin
                state_nex	<= SM01;
            end
        endcase
    end
end
endmodule	
	

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值