一、协议格式

该协议时钟(SENDCK)为2MHz ,SYNC为同步信号,CHANNELX/Y 是数据信号,它有20位组成,其中C2、C1、C0是振镜运动方向值,参考值为001,D15—D0是数据位,它是16位的二进制数,用来控制振镜转过的角度大小(取值为0~65535,即将振镜轴的转动角度范围映射到0~65535);最后一位是偶校验位,当发送的数 据中有偶数个“1”时,对应的校验位为“0”。当发送的数据中有奇数个“1”时对应的校验位为“1”。
二、FPGA(Verilog)代码实现
module xy2_100(
//端口列表
rst_n,
clk50m,
send_en,
x_data,
y_data,
sendck,
sync,
chl_x,
chl_y,
TxDone,
xy2_state
);
//端口定义
input rst_n;
input clk50m;
input send_en;
input [15:0]x_data;
input [15:0]y_data;
output reg sendck;
output reg sync;
output reg chl_x;
output reg chl_y;
output reg TxDone;
output reg xy2_state;
reg [4:0]div_cnt;//分频计数器
reg [4:0]bps_cnt;//波特率时钟计数器
reg [15:0]r_data_x;
reg [15:0]r_data_y;
localparam bps_DR = 5'd24; //分频计数最大值
localparam CTRL_WD = 3'b001; //控制字
localparam MAX_BIT = 5'd20;
//发送状态信号
always@(posedge clk50m or negedge rst_n)
if(!rst_n)
xy2_state <= 1'b0;
else if(send_en)
xy2_state <= 1'b1;
else if(bps_cnt == MAX_BIT)
xy2_state <= 1'b0;
else
xy2_state <= xy2_state;
//发送数据锁存
always@(posedge clk50m or negedge rst_n)
if(!rst_n)
r_data_x <= 15'd0;
else if(send_en)
r_data_x <= x_data;
else
r_data_x <= r_data_x;
always@(posedge clk50m or negedge rst_n)
if(!rst_n)
r_data_y <= 15'd0;
else if(send_en)
r_data_y <= y_data;
else
r_data_y <= r_data_y;
//分频计数器
always@(posedge clk50m or negedge rst_n)
if(!rst_n)
div_cnt <= 5'd0;
else if(xy2_state||send_en) begin
if(div_cnt == bps_DR)
div_cnt <= 5'd0;
else
div_cnt <= div_cnt+1'b1;
end
else
div_cnt <= 5'd0;
// bps counter
always@(posedge clk50m or negedge rst_n)
if(!rst_n)
bps_cnt <= 5'd0;
else if(bps_cnt==MAX_BIT)
bps_cnt <= 5'd0;
else if(div_cnt==bps_DR)
bps_cnt <= bps_cnt + 1'b1;
else
bps_cnt <= bps_cnt;
// 发送完成信号
always@(posedge clk50m or negedge rst_n)
if(!rst_n)
TxDone <= 1'b0;
else if(bps_cnt == MAX_BIT)
TxDone <= 1'b1;
else
TxDone <= 1'b0;
// x按位发送数据
always@(posedge clk50m or negedge rst_n)
if(!rst_n)
chl_x <= 1'b0;
else if(div_cnt==5'd0) begin
case (bps_cnt)
0:chl_x <= 1'b0; //c2
1:chl_x <= 1'b0; //c1
2:chl_x <= 1'b1; //c0
3:chl_x <= r_data_x[15];
4:chl_x <= r_data_x[14];
5:chl_x <= r_data_x[13];
6:chl_x <= r_data_x[12];
7:chl_x <= r_data_x[11];
8:chl_x <= r_data_x[10];
9:chl_x <= r_data_x[9];
10:chl_x <= r_data_x[8];
11:chl_x <= r_data_x[7];
12:chl_x <= r_data_x[6];
13:chl_x <= r_data_x[5];
14:chl_x <= r_data_x[4];
15:chl_x <= r_data_x[3];
16:chl_x <= r_data_x[2];
17:chl_x <= r_data_x[1];
18:chl_x <= r_data_x[0];
19:chl_x <= ^{CTRL_WD,r_data_x}; //偶校验
default:chl_x <= 1'b0;
endcase
end
// y按位发送数据
always@(posedge clk50m or negedge rst_n)
if(!rst_n)
chl_y <= 1'b0;
else if(div_cnt==5'd0) begin
case (bps_cnt)
0:chl_y <= 1'b0; //c2
1:chl_y <= 1'b0; //c1
2:chl_y <= 1'b1; //c0
3:chl_y <= r_data_y[15];
4:chl_y <= r_data_y[14];
5:chl_y <= r_data_y[13];
6:chl_y <= r_data_y[12];
7:chl_y <= r_data_y[11];
8:chl_y <= r_data_y[10];
9:chl_y <= r_data_y[9];
10:chl_y <= r_data_y[8];
11:chl_y <= r_data_y[7];
12:chl_y <= r_data_y[6];
13:chl_y <= r_data_y[5];
14:chl_y <= r_data_y[4];
15:chl_y <= r_data_y[3];
16:chl_y <= r_data_y[2];
17:chl_y <= r_data_y[1];
18:chl_y <= r_data_y[0];
19:chl_y <= ^{CTRL_WD,r_data_y}; //偶校验
default:chl_y <= 1'b0;
endcase
end
//同步信号
always@(posedge clk50m or negedge rst_n)
if(!rst_n)
sync <= 1'b0;
else if(send_en)
sync <= 1'b1;
else if(bps_cnt==(MAX_BIT-1)) //&&(div_cnt==5'd0))
sync <= 1'b0;
else
sync <= sync;
//发送时钟信号
always@(posedge clk50m or negedge rst_n)
if(!rst_n)
sendck <= 1'b0;
else if((xy2_state||send_en)&&(bps_cnt<MAX_BIT)) begin
if(div_cnt<=bps_DR/2)
sendck <= 1'b1;
else
sendck <= 1'b0;
end
else
sendck <= 1'b0;
endmodule