fpga与stm32 spi 通信代码备份

院赛调通的通信,fpga作为从机,stm32作为主机,主要是stm32给fpga发送数据

spi_slave 






module spi_slave(
   clk      ,  //50MHz时钟
   rst_n    ,  //复位
   data_in  ,  //要发送的数据
   data_out ,  //接收到的数据
   spi_sck  ,  //主机时钟
   spi_miso ,  //主收从发(从机)
   spi_mosi ,  //主发从收(从机)
   spi_cs   ,  //主机片选,低有效(从机)
   tx_en    ,  //发送使能
   tx_done  ,  //发送完成标志位
   rx_done     //接收完成标志位
);
//改DATA_W的参数即可实现任意字节的发送和接收,现在是两字节发送和接收
parameter DATA_W  =  16;
 
parameter SYNC_W  =  2;
 
//计数器参数
parameter CNT_W   =  4;
parameter CNT_N   =  DATA_W;
 
input                   clk;
input                   rst_n;
input    [DATA_W-1:0]   data_in;
input                   spi_sck;
input                   spi_mosi;
input                   spi_cs;
input                   tx_en;
 
output   [DATA_W-1:0]   data_out;
output                  spi_miso;
output                  tx_done;
output                  rx_done;
 
reg      [DATA_W-1:0]   data_out;
reg                     spi_miso;
reg                     tx_done;
reg                     rx_done;
 
//中间变量
reg      [SYNC_W-1:0]   spi_sync;
wire                    nedge;
wire                    pedge;
reg                     spi_mosi_reg;
reg                     spi_mosi_reg1;
//计数器变量
reg      [CNT_W-1:0]    cnt_rxbit;
wire                    add_cnt_rxbit;
wire                    end_cnt_rxbit;
 
reg      [CNT_W-1:0]    cnt_txbit;
wire                    add_cnt_txbit;
wire                    end_cnt_txbit;
reg                     tx_flag;
 
//边沿检测
always @(posedge clk or negedge rst_n)begin
   if(!rst_n)
      //SCK时钟空闲状态位高电平,工作模式3
      spi_sync <= 2'b11;
   else
      spi_sync <= {spi_sync[0],spi_sck};
end
assign nedge = spi_sync[1:0] == 2'b10;
assign pedge = spi_sync[1:0] == 2'b01;
 
//上升沿接收,工作模式三
always @(posedge clk or negedge rst_n)begin
   if(!rst_n)
      cnt_rxbit <= 0;
   else if(add_cnt_rxbit)begin
      if(end_cnt_rxbit)
         cnt_rxbit <= 0;
      else
         cnt_rxbit <= cnt_rxbit + 1'b1;
   end
end
assign add_cnt_rxbit = pedge;
assign end_cnt_rxbit = add_cnt_rxbit && cnt_rxbit == CNT_N - 1;
 
//下降沿发送,工作模式三
always @(posedge clk or negedge rst_n)begin
   if(!rst_n)
      cnt_txbit <= 0;
   else if(add_cnt_txbit)begin
      if(end_cnt_txbit)
         cnt_txbit <= 0;
      else
         cnt_txbit <= cnt_txbit + 1'b1;
   end
end
assign add_cnt_txbit = nedge && tx_flag;
assign end_cnt_txbit = add_cnt_txbit && cnt_txbit == CNT_N - 1;
 
//因为异步信号同步化的原因,为了与延后的下降沿对齐,多打2拍
always @(posedge clk or negedge rst_n)begin
   if(!rst_n)
      spi_mosi_reg <= 0;
   else
      spi_mosi_reg <= spi_mosi;
end
always @(posedge clk or negedge rst_n)begin
   if(!rst_n)
      spi_mosi_reg1 <= 0;
   else
      spi_mosi_reg1 <= spi_mosi_reg;
end
 
//下降沿 接收主机发来的数据
always @(posedge clk or negedge rst_n)begin
   if(!rst_n)  
      data_out <= 0;
   else if(!spi_cs)  // cs低电平使能
      data_out[CNT_N - 1 - cnt_rxbit ] <= spi_mosi_reg1;
end
 
//上升沿发送数据
always @(posedge clk or negedge rst_n)begin
   if(!rst_n)
      spi_miso <= 0;
   else if(!spi_cs && tx_flag)
      spi_miso <= data_in[CNT_N - 1 - cnt_txbit];
   else
      spi_miso <= 0;
end
 
always @(posedge clk or negedge rst_n)begin
   if(!rst_n)
      rx_done <= 0;
   else if(end_cnt_rxbit)
      rx_done <= 1;
   else
      rx_done <= 0;
end
 
always @(posedge clk or negedge rst_n)begin
   if(!rst_n)
      tx_done <= 0;
   else if(end_cnt_txbit)
      tx_done <= 1;
   else
      tx_done <= 0;
end
 
 
always @(posedge clk or negedge rst_n)begin
   if(!rst_n)
      tx_flag <= 0;
   else if(tx_en)
      tx_flag <= 1;
   else if(end_cnt_txbit)
      tx_flag <= 0;
end
 
endmodule

 spi_ctrl

状态机接收数据的逻辑



module spi_ctrl(
    input clk,
    input rst_n,

    input spi_sck,
    output spi_miso,     //主收从发(从机)
    input spi_mosi,     //主发从收(从机)
    input spi_cs,       //主机片选,低有效(从机)

    output reg [1:0] wave_c,
    output reg [47:0] f_word,
    output reg [11:0] set_phase=0      // 设定的锁相值

);

wire [15:0] data_in;  // 此处没有要发送给32的数据
wire [15:0] data_out;     // 32发来的频率、波形种类信息--------A波形、A频率、B波形、B频率
// 在这道题目里面,发送两个16位spi数据,第一个发送波形,第二个发送频率
wire rx_done;
reg [3:0] state = 4'b0001;
parameter IDLE = 4'b0001;  // 空闲状态 1
parameter SEND_1 = 4'b0010;    // 第一次接收 2
parameter SEND_2 = 4'b0100;  // 4
parameter SEND_3 = 4'b1000;  // 8

always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        state <= IDLE;
        wave_c <= 2'b0;
        f_word <= 48'd0;
        set_phase <= 14'd0;
    end
    else if(rx_done && state == IDLE) begin
        state <= SEND_1;    // 完成第一次接收----------波形种类
        wave_c <= data_out;
    end
    else if(rx_done && state == SEND_1) begin
        state <= SEND_2;    // 完成第二次接收-----------波形频率
        f_word <= (data_out * 48'd4294967296) / 48'd50000000;  
    end
    else if(rx_done && state == SEND_2) begin
        state <= SEND_3;    // 完成第三次接收------------设置相位差
        set_phase <= data_out;
    end
    else if(state == SEND_3) begin
        state <= IDLE;    // 完成第四次接收
    end
    else 
        state <= state;
end

spi_slave spi_slave_inst(
    .clk(clk),
    .rst_n(rst_n),
    .data_in(data_in),      // 待发送给主机的数据
    .data_out(data_out),     // 接收主机的数据
    .spi_sck(spi_sck),
    .spi_miso(spi_miso),     //主收从发(从机)
    .spi_mosi(spi_mosi),     //主发从收(从机)
    .spi_cs(spi_cs),       //主机片选,低有效(从机)
    .tx_en(0),        //发送使能
    //.tx_done(),     //发送完成标志位
    .rx_done(rx_done)      //接收完成标志位
);


ila_2 ila_2_inst(
    .clk(clk),
    .probe0(data_out),     
    .probe1(rx_done),
    .probe2(state),
    .probe3(wave_c),
    .probe4(f_word),
    .probe5(set_phase),
    .probe6(spi_sck),
    .probe7(spi_miso),
    .probe8(spi_mosi),
    .probe9(spi_cs)
);



endmodule

校赛的spi_ctrl



module spi_ctrl(
    input clk,
    input rst_n,

    input spi_sck,
    output spi_miso,     //主收从发(从机)
    input spi_mosi,     //主发从收(从机)
    input spi_cs,       //主机片选,低有效(从机)

    output reg [1:0] wave_c,
    output reg [47:0] f_word,
    output reg [4:0] amplitude,
    output reg [3:0] amp=1,   //倍频的系数 1-5


    input [33:0] wave_freq,  // 测得波的频率
    input [15:0] phase      // 发送给主机的测出的相位差

);
reg tx_en=0;  //发送使能

wire [15:0] data_out;   //stm32主机发送的数据



wire rx_done;
// // 这里似乎不需要写状态机
// always@(posedge clk or negedge rst_n) begin
//     if(!rst_n) begin
//         f_word <= 'd0;
//         wave_c <= 2'b00;  // 方波 3V
//         amplitude <= 5'd1;
//         amp <= 4'd1;
//         tx_en <= 1'b0;
//     end
//     else if(rx_done) begin
//         if(data_out==16'd10) begin
//             f_word <= 'd42949;
//             wave_c <= 2'b11;  // 方波 3V
//             amplitude <= 5'd2; 
//         end
//         else if(data_out == 16'd11) begin
//             f_word <= 'd171799;
//             wave_c <= 2'b00;  // 正弦波 6V
//             amplitude <= 5'd1;
//         end
//         else if(data_out == 16'd12) begin
//             f_word <= 'd257698;
//             wave_c <= 2'b01;  // 三角波 1V
//             amplitude <= 5'd6;
//         end
//         else if(data_out <16'd6) begin
//             //amp <= data_out;   // 1~5
//             f_word <= (wave_freq*48'd4294967296)/48'd50000000;       // 倍频信号freq_cd4046
//             wave_c <= 2'b00;  // 正弦波
//             amplitude <= 5'd3;  // Vpp = 2V
//             tx_en <= amp==1?1'b1:1'b0;  //只有一倍频(即同频)时输出相位差
//         end
//     end

// end



reg [3:0] state = 4'b0001;
parameter IDLE = 4'b0001;  // 
parameter SEND_1 = 4'b0010;    // 
parameter SEND_2 = 4'b0100;  // 
parameter SEND_3 = 4'b1000;  // 

//   200   数据     100
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin  // reset
        state <= IDLE;
        amp <= 4'd1;
        wave_c <= 2'b00;
        f_word <= 'd0;
        amplitude <= 5'd1;
    end
    else if(rx_done && state == IDLE && data_out ==200) begin    // 帧头
        state <= SEND_1; 
        tx_en <= 1'b0;  
    end
    else if(rx_done && state == SEND_1) begin   // 数据
         case (data_out)
            16'd10: begin
                f_word <= 'd42949;
                wave_c <= 2'b11;  // 方波 3V
                amplitude <= 5'd2; 
            end
            16'd11: begin
                f_word <= 'd171799;
                wave_c <= 2'b00;  // 正弦波 6V
                amplitude <= 5'd1;
            end
            16'd12: begin
                f_word <= 'd257698;
                wave_c <= 2'b01;  // 三角波 1V
                amplitude <= 5'd6;
            end
            16'd100: begin
                f_word <= (wave_freq*48'd4294967296)/48'd50000000;       // 倍频信号freq_cd4046
                wave_c <= 2'b00;  // 正弦波
                amplitude <= 5'd3;  // Vpp = 2V
                amp <= 4'd1;   // 1倍频
                 
            end
            16'd200: begin
                f_word <= (wave_freq*48'd4294967296)/48'd50000000;       // 倍频信号freq_cd4046
                wave_c <= 2'b00;  // 正弦波
                amplitude <= 5'd3;  // Vpp = 2V
                amp <= 4'd2;   // 2倍频
                 
            end
            16'd300: begin
                f_word <= (wave_freq*48'd4294967296)/48'd50000000;       // 倍频信号freq_cd4046
                wave_c <= 2'b00;  // 正弦波
                amplitude <= 5'd3;  // Vpp = 2V
                amp <= 4'd3;   // 3倍频
            end
            16'd400: begin
                f_word <= (wave_freq*48'd4294967296)/48'd50000000;       // 倍频信号freq_cd4046
                wave_c <= 2'b00;  // 正弦波
                amplitude <= 5'd3;  // Vpp = 2V
                amp <= 4'd4;   // 4倍频
            end
            16'd500: begin
                f_word <= (wave_freq*48'd4294967296)/48'd50000000;       // 倍频信号freq_cd4046
                wave_c <= 2'b00;  // 正弦波
                amplitude <= 5'd3;  // Vpp = 2V
                amp <= 4'd5;   // 5倍频
            end
            16'd8:begin
                tx_en <= 1'b1;

            end
            default:; 
         endcase
         state <= SEND_2; 
    end
    else if(rx_done && state == SEND_2 && data_out ==100) begin     //  帧尾
        state <= IDLE;
        tx_en <= 1'b0;    
    end
    else 
        state <= state;
        tx_en <= 1'b0;
end


spi_slave spi_slave_inst(
    .clk(clk),
    .rst_n(rst_n),
    .data_in(phase),      // 待发送给主机的数据
    .data_out(data_out),     // 接收主机的数据
    .spi_sck(spi_sck),
    .spi_miso(spi_miso),     //主收从发(从机)
    .spi_mosi(spi_mosi),     //主发从收(从机)
    .spi_cs(spi_cs),       //主机片选,低有效(从机)
    .tx_en(tx_en),        //发送使能
    //.tx_done(),     //发送完成标志位
    .rx_done(rx_done)      //接收完成标志位
);


ila_2 ila_2_inst(
    .clk(clk),
    .probe0(data_out),     
    .probe1(rx_done),
    .probe2(state),
    .probe3(wave_c),
    .probe4(f_word),
    .probe5(amp),
    .probe6(spi_sck),
    .probe7(spi_miso),
    .probe8(spi_mosi),
    .probe9(spi_cs)
);



endmodule

/*
wire [15:0] data_in;  // 此处没有要发送给32的数据
wire [15:0] data_out;     // 32发来的频率、波形种类信息--------A波形、A频率、B波形、B频率
// 在这道题目里面,发送两个16位spi数据,第一个发送波形,第二个发送频率
wire rx_done;
reg [3:0] state = 4'b0001;
parameter IDLE = 4'b0001;  // 空闲状态 1
parameter SEND_1 = 4'b0010;    // 第一次接收 2
parameter SEND_2 = 4'b0100;  // 4
parameter SEND_3 = 4'b1000;  // 8

always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        state <= IDLE;
        wave_c <= 2'b0;
        f_word <= 48'd0;
        set_phase <= 14'd0;
    end
    else if(rx_done && state == IDLE) begin
        state <= SEND_1;    // 完成第一次接收----------波形种类
        wave_c <= data_out;
    end
    else if(rx_done && state == SEND_1) begin
        state <= SEND_2;    // 完成第二次接收-----------波形频率
        f_word <= (data_out * 48'd4294967296) / 48'd50000000;  
    end
    else if(rx_done && state == SEND_2) begin
        state <= SEND_3;    // 完成第三次接收------------设置相位差
        set_phase <= data_out;
    end
    else if(state == SEND_3) begin
        state <= IDLE;    // 完成第四次接收
    end
    else 
        state <= state;
end



reg [3:0] state = 4'b0001;
parameter IDLE = 4'b0001;  // 
parameter SEND_1 = 4'b0010;    // 
parameter SEND_2 = 4'b0100;  // 
parameter SEND_3 = 4'b1000;  // 

always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin  // reset
        state <= IDLE;
        amp <= 'd0;
        wave_c <= 2'b00;
    end
    else if(rx_done && state == IDLE) begin
        f_word <= 'd42949;
        wave_c <= 2'b11;  // 方波 3V
        amplitude <= 5'd2;   
        state <= SEND_1; 
    end
    else if(rx_done && state == SEND_1) begin
        f_word <= 'd171799;
        wave_c <= 2'b00;  // 正弦波 6V
        amplitude <= 5'd1;
        state <= SEND_2;
    end
    else if(rx_done && state == SEND_2) begin
        f_word <= 'd257698;
        wave_c <= 2'b01;  // 三角波 1V
        amplitude <= 5'd6;
        state <= SEND_3;
    end
    else if(rx_done && state == SEND_3) begin
        amp <= data_out;
        f_word <= (amp*wave_freq*48'd4294967296)/48'd50000000;       // 倍频信号freq_cd4046
        wave_c <= 2'b00;  // 正弦波
        amplitude <= 5'd3;  // Vpp = 2V
    end
    else 
        state <= state;
end
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值