院赛调通的通信,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
*/