XY2-100的Verilog实现
xy2_100.v
module xy2_100(
input clk,
input tx_init, //当产生上升沿时,开始发数据
input wire [15:0]x_pos,
input wire [15:0]y_pos,
input wire [15:0]z_pos,
output clk_2MHz_o,//输出2MHz时钟
output sync_o,
output x_ch_o,
output y_ch_o,
output z_ch_o,
output tx_done_o
);
reg clk_2MHz=1'd1;
reg sync=1'd0;
reg x_ch=1'd0;
reg y_ch=1'd0;
reg z_ch=1'd0;
reg tx_done=1'd0;
assign clk_2MHz_o=clk_2MHz;
assign sync_o=sync;
assign x_ch_o=x_ch;
assign y_ch_o=y_ch;
assign z_ch_o=z_ch;
assign tx_done_o=tx_done;
reg tx_init1=1'd0;
reg tx_init2=1'd0;
wire start_transaction;
assign start_transaction= tx_init1 & (~tx_init2);
reg [5:0]generate_clk_2MHz_cnt=6'd0;
reg [6:0]clk_2MHz_cnt=7'd0;
localparam RefFreq=125000000;
localparam XY2_100_2MHz=2000000;
localparam XY2_100_2MHz_Reverse_Cnt=RefFreq/(2*XY2_100_2MHz);
localparam MaxCnt=2*XY2_100_2MHz_Reverse_Cnt+1;
always@(posedge clk)
begin
if(generate_clk_2MHz_cnt==XY2_100_2MHz_Reverse_Cnt)
begin
generate_clk_2MHz_cnt<=6'd0;
clk_2MHz<=~clk_2MHz;
end
else
generate_clk_2MHz_cnt<=generate_clk_2MHz_cnt + 6'd1;
if(clk_2MHz_cnt==MaxCnt)
clk_2MHz_cnt<=7'd0;
else
clk_2MHz_cnt<=clk_2MHz_cnt+7'd1;
tx_init1<=tx_init;
tx_init2<=tx_init1;
end
localparam Idle=5'd0;
localparam Wait_First_2MHz_Posedge=5'd1;
localparam C2=5'd2;
localparam C1=5'd3;
localparam C0=5'd4;
localparam D15=5'd5;
localparam D14=5'd6;
localparam D13=5'd7;
localparam D12=5'd8;
localparam D11=5'd9;
localparam D10=5'd10;
localparam D9=5'd11;
localparam D8=5'd12;
localparam D7=5'd13;
localparam D6=5'd14;
localparam D5=5'd15;
localparam D4=5'd16;
localparam D3=5'd17;
localparam D2=5'd18;
localparam D1=5'd19;
localparam D0=5'd20;
localparam P=5'd21;
reg [4:0]status=Idle;
always@(posedge clk)
begin
if(status==Idle)
begin
tx_done<=1'd0;
if(start_transaction==1'd1)
status<=Wait_First_2MHz_Posedge;
else
status<=status;
end
else if(status==Wait_First_2MHz_Posedge)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
sync<=1'd1;
x_ch<=1'd0;
y_ch<=1'd0;
z_ch<=1'd0;
status<=C2;
end
else
status<=status;
end
else if(status==C2)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=1'd0;
y_ch<=1'd0;
z_ch<=1'd0;
status<=C1;
end
else
status<=status;
end
else if(status==C1)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=1'd1;
y_ch<=1'd1;
z_ch<=1'd1;
status<=C0;
end
else
status<=status;
end
else if(status==C0)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[15];
y_ch<=y_pos[15];
z_ch<=z_pos[15];
status<=D15;
end
else
status<=status;
end
else if(status==D15)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[14];
y_ch<=y_pos[14];
z_ch<=z_pos[14];
status<=D14;
end
else
status<=status;
end
else if(status==D14)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[13];
y_ch<=y_pos[13];
z_ch<=z_pos[13];
status<=D13;
end
else
status<=status;
end
else if(status==D13)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[12];
y_ch<=y_pos[12];
z_ch<=z_pos[12];
status<=D12;
end
else
status<=status;
end
else if(status==D12)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[11];
y_ch<=y_pos[11];
z_ch<=z_pos[11];
status<=D11;
end
else
status<=status;
end
else if(status==D11)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[10];
y_ch<=y_pos[10];
z_ch<=z_pos[10];
status<=D10;
end
else
status<=status;
end
else if(status==D10)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[9];
y_ch<=y_pos[9];
z_ch<=z_pos[9];
status<=D9;
end
else
status<=status;
end
else if(status==D9)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[8];
y_ch<=y_pos[8];
z_ch<=z_pos[8];
status<=D8;
end
else
status<=status;
end
else if(status==D8)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[7];
y_ch<=y_pos[7];
z_ch<=z_pos[7];
status<=D7;
end
else
status<=status;
end
else if(status==D7)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[6];
y_ch<=y_pos[6];
z_ch<=z_pos[6];
status<=D6;
end
else
status<=status;
end
else if(status==D6)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[5];
y_ch<=y_pos[5];
z_ch<=z_pos[5];
status<=D5;
end
else
status<=status;
end
else if(status==D5)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[4];
y_ch<=y_pos[4];
z_ch<=z_pos[4];
status<=D4;
end
else
status<=status;
end
else if(status==D4)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[3];
y_ch<=y_pos[3];
z_ch<=z_pos[3];
status<=D3;
end
else
status<=status;
end
else if(status==D3)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[2];
y_ch<=y_pos[2];
z_ch<=z_pos[2];
status<=D2;
end
else
status<=status;
end
else if(status==D2)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[1];
y_ch<=y_pos[1];
z_ch<=z_pos[1];
status<=D1;
end
else
status<=status;
end
else if(status==D1)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
x_ch<=x_pos[0];
y_ch<=y_pos[0];
z_ch<=z_pos[0];
status<=D0;
end
else
status<=status;
end
else if(status==D0)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
sync<=1'd0;
x_ch<=1'd0;
y_ch<=1'd0;
z_ch<=1'd0;
status<=P;
end
else
status<=status;
end
else if(status==P)
begin
if(clk_2MHz_cnt==MaxCnt)
begin
tx_done<=1'd1;
status<=Idle;
end
else
status<=status;
end
end
endmodule
仿真测试tb.v:
`timescale 1ns/1ps
module tb();
//被测模块的输入信号必须在tb中必须是reg型
reg clk;
reg tx_init;
reg [15:0]x_pos;
reg [15:0]y_pos;
reg [15:0]z_pos;
wire clk_2MHz_o;
wire sync_o;
wire x_ch_o;
wire y_ch_o;
wire z_ch_o;
wire tx_done_o;
xy2_100 u1(
.clk (clk ) ,
.tx_init (tx_init ) , //当产生上升沿时,开始发数据
.x_pos (x_pos ) ,
.y_pos (y_pos ) ,
.z_pos (z_pos ) ,
.clk_2MHz_o (clk_2MHz_o ) ,//输出2MHz时钟
.sync_o (sync_o ) ,
.x_ch_o (x_ch_o ) ,
.y_ch_o (y_ch_o ) ,
.z_ch_o (z_ch_o ) ,
.tx_done_o (tx_done_o )
);
//产生时钟激励
initial clk = 1;
always #4 clk = ~clk;
//输入激励
initial begin
tx_init=0;
x_pos=16'd43690;
y_pos=16'd43690;
z_pos=16'd43690;
#10;
tx_init = 1;
end
endmodule
仿真波形: