主要思路:
1.使用 VIO 输出信号控制什么时候开始读LMK04803寄存器
2.遍历LMK04803所有寄存器,将读到的每个寄存器的值显示在VIO上。
3.遍历指的是 从 R0 开始读,R0读完接着读 R1,一直到R31 结束
4.注意的是写寄存器是 32bit (data[31:5] + addr[4:0]),读出来数据是 27bit[26:0]
部分时序
通过 ILA 抓取的波形
开始读取,从R0 开始读,接着 R1 … R31
结束读取,32个寄存器全部读取完毕
具体参考LMK04803手册读写时序:
寄存器写:
寄存器读:
/*下面是lmk04803需要读取寄存器地址的 向LMK04803的R31 写操作的值addr : R0000001F : 0
0001001F : 1
0002001F : 2
0003001F : 3
0004001F : 4
0005001F : 5
0006001F : 6
0007001F : 7
0008001F : 8
0009001F : 9
000A001F : 10
000B001F : 11
000C001F : 12
000D001F : 13
000E001F : 14
000F001F : 15
0010001F : 16
0011001F : 17
0012001F : 18
0013001F : 19
0014001F : 20
0015001F : 21
0016001F : 22
0017001F : 23
0018001F : 24
0019001F : 25
001A001F : 26
001B001F : 27
001C001F : 28
001D001F : 29
001E001F : 30
001F001F : 31*///功能: 通过 VIO 控制开始读取寄存器,接着遍历读取 lmk04803 32个寄存器地址,再通过 VIO 将所有32个寄存器值显示module lmk_rd (input i_clk ,input i_rstn ,input i_rd_data ,input i_sim_flag ,output o_wr_data ,output o_lmk_rd_le ,output o_lmk_rd_clk ,output o_vio_rd_flag
);parameter P_IDLE = 0,P_START = 1,P_WRITE = 2, // 写 R11 值 期间P_WAIT1 = 3,P_READ_PRE = 4, // 读之前 需要 向 R31 写值 期间P_WAIT2 = 5,P_READ = 6, // 读寄存器的期间P_WAIT3 = 7,P_DONE = 8;// vio singal(*dont_touch = "true"*) wire w_lmk_rd_start ;(*dont_touch = "true"*) wire [31:0] w_lmk_R11_wr ;(*dont_touch = "true"*) wire [26:0] w_lmk_R0_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R1_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R2_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R3_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R4_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R5_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R6_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R7_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R8_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R9_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R10_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R11_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R12_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R13_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R14_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R15_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R16_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R17_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R18_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R19_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R20_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R21_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R22_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R23_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R24_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R25_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R26_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R27_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R28_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R29_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R30_rd ;(*dont_touch = "true"*) wire [26:0] w_lmk_R31_rd ;wire w_read_start_pos ;reg r_lmk_clk ;
reg r_lmk_le ;
(*mark_debug = "true"*) reg [1:0] r_cnt0 ;
(*mark_debug = "true"*) reg [7:0] r_cnt1 ;
(*mark_debug = "true"*) reg [3:0] r_cu_status ;
reg [3:0] r_nx_status ;
reg [7:0] r_status_cnt ;
(*mark_debug = "true"*) reg [7:0] r_bit_cnt ;
reg r_rd_end ;
(*mark_debug = "true"*) reg [7:0] r_rd_cnt ;
reg [31:0] r_wrdata ;
reg [31:0] r_readaddr ;
reg [31:0] r_addr_write ;
(*mark_debug = "true"*) reg [26:0] r_readin ;
(*mark_debug = "true"*) reg r_read_valid ;
(*mark_debug = "true"*) reg [7:0] r_read_bit_cnt ;
(*mark_debug = "true"*) reg [7:0] r_valid_cnt ;
reg r_rd_finish ;
reg r_read_process ;
reg r_begin_read_1d ;
reg r_begin_read_2d ;
reg [26:0] LMK_R [0:31] ;assign o_vio_rd_flag = r_read_process ;
assign o_lmk_rd_le = r_lmk_le ;
assign o_lmk_rd_clk = r_lmk_clk ;
assign o_wr_data = (r_cu_status == P_WRITE)? r_wrdata[31]:r_addr_write[31];
assign w_read_start_pos = !r_begin_read_2d && r_begin_read_1d;// vio data out
assign w_lmk_R0_rd = LMK_R[0] ;
assign w_lmk_R1_rd = LMK_R[1] ;
assign w_lmk_R2_rd = LMK_R[2] ;
assign w_lmk_R3_rd = LMK_R[3] ;
assign w_lmk_R4_rd = LMK_R[4] ;
assign w_lmk_R5_rd = LMK_R[5] ;
assign w_lmk_R6_rd = LMK_R[6] ;
assign w_lmk_R7_rd = LMK_R[7] ;
assign w_lmk_R8_rd = LMK_R[8] ;
assign w_lmk_R9_rd = LMK_R[9] ;
assign w_lmk_R10_rd = LMK_R[10];
assign w_lmk_R11_rd = LMK_R[11];
assign w_lmk_R12_rd = LMK_R[12];
assign w_lmk_R13_rd = LMK_R[13];
assign w_lmk_R14_rd = LMK_R[14];
assign w_lmk_R15_rd = LMK_R[15];
assign w_lmk_R16_rd = LMK_R[16];
assign w_lmk_R17_rd = LMK_R[17];
assign w_lmk_R18_rd = LMK_R[18];
assign w_lmk_R19_rd = LMK_R[19];
assign w_lmk_R20_rd = LMK_R[20];
assign w_lmk_R21_rd = LMK_R[21];
assign w_lmk_R22_rd = LMK_R[22];
assign w_lmk_R23_rd = LMK_R[23];
assign w_lmk_R24_rd = LMK_R[24];
assign w_lmk_R25_rd = LMK_R[25];
assign w_lmk_R26_rd = LMK_R[26];
assign w_lmk_R27_rd = LMK_R[27];
assign w_lmk_R28_rd = LMK_R[28];
assign w_lmk_R29_rd = LMK_R[29];
assign w_lmk_R30_rd = LMK_R[30];
assign w_lmk_R31_rd = LMK_R[31];// vio_lmk_rd_flag vio_lmk_rd_flag_u0 (// .clk (i_clk ), // input wire clk// .probe_out0(w_lmk_rd ) // output wire [0 : 0] probe_out0
// );// vio vio_lmk_rd_flag vio_lmk_rd_flag_u0 (.clk (i_clk ), // input wire clk.probe_in0 (w_lmk_R0_rd ), // input wire [31 : 0] probe_in0.probe_in1 (w_lmk_R1_rd ), // input wire [31 : 0] probe_in1.probe_in2 (w_lmk_R2_rd ), // input wire [31 : 0] probe_in2.probe_in3 (w_lmk_R3_rd ), // input wire [31 : 0] probe_in3.probe_in4 (w_lmk_R4_rd ), // input wire [31 : 0] probe_in4.probe_in5 (w_lmk_R5_rd ), // input wire [31 : 0] probe_in5.probe_in6 (w_lmk_R6_rd ), // input wire [31 : 0] probe_in6.probe_in7 (w_lmk_R7_rd ), // input wire [31 : 0] probe_in7.probe_in8 (w_lmk_R8_rd ), // input wire [31 : 0] probe_in8.probe_in9 (w_lmk_R9_rd ), // input wire [31 : 0] probe_in9.probe_in10(w_lmk_R10_rd ), // input wire [31 : 0] probe_in10.probe_in11(w_lmk_R11_rd ), // input wire [31 : 0] probe_in11.probe_in12(w_lmk_R12_rd ), // input wire [31 : 0] probe_in12.probe_in13(w_lmk_R13_rd ), // input wire [31 : 0] probe_in13.probe_in14(w_lmk_R14_rd ), // input wire [31 : 0] probe_in14.probe_in15(w_lmk_R15_rd ), // input wire [31 : 0] probe_in15.probe_in16(w_lmk_R16_rd ), // input wire [31 : 0] probe_in16.probe_in17(w_lmk_R17_rd ), // input wire [31 : 0] probe_in17.probe_in18(w_lmk_R18_rd ), // input wire [31 : 0] probe_in18.probe_in19(w_lmk_R19_rd ), // input wire [31 : 0] probe_in19.probe_in20(w_lmk_R20_rd ), // input wire [31 : 0] probe_in20.probe_in21(w_lmk_R21_rd ), // input wire [31 : 0] probe_in21.probe_in22(w_lmk_R22_rd ), // input wire [31 : 0] probe_in22.probe_in23(w_lmk_R23_rd ), // input wire [31 : 0] probe_in23.probe_in24(w_lmk_R24_rd ), // input wire [31 : 0] probe_in24.probe_in25(w_lmk_R25_rd ), // input wire [31 : 0] probe_in25.probe_in26(w_lmk_R26_rd ), // input wire [31 : 0] probe_in26.probe_in27(w_lmk_R27_rd ), // input wire [31 : 0] probe_in27.probe_in28(w_lmk_R28_rd ), // input wire [31 : 0] probe_in28.probe_in29(w_lmk_R29_rd ), // input wire [31 : 0] probe_in29.probe_in30(w_lmk_R30_rd ), // input wire [31 : 0] probe_in30.probe_in31(w_lmk_R31_rd ), // input wire [31 : 0] probe_in31.probe_out0(w_lmk_rd_start), // output wire [0 : 0] probe_out0.probe_out1(w_lmk_R11_wr ) // output wire [31 : 0] probe_out1
);// 寄存 32 个寄存器的值
genvar i;
generate for (i = 0 ; i <= 31; i = i + 1)beginalways @ (posedge i_clk or negedge i_rstn)beginif (!i_rstn)LMK_R[i] <= 0; else if (r_read_valid && r_valid_cnt == i)LMK_R[i] <= r_readin;elseLMK_R[i] <= LMK_R[i]; endend
endgenerate// 开始标志
always @ (posedge i_clk)
beginr_begin_read_1d <= w_lmk_rd_start;// r_begin_read_1d <= i_sim_flag;r_begin_read_2d <= r_begin_read_1d;
end//status
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_cu_status <= P_IDLE;elser_cu_status <= r_nx_status;
endalways @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_status_cnt <= 0;else if (r_cu_status != r_nx_status)r_status_cnt <= 0; elser_status_cnt <= r_status_cnt + 1;
endalways @ (*)
begincase (r_cu_status) P_IDLE : beginif (w_read_start_pos) r_nx_status <= P_START;elser_nx_status <= r_cu_status; end P_START : beginif (r_status_cnt == 10) r_nx_status <= P_WRITE;elser_nx_status <= r_cu_status; endP_WRITE : beginif (r_cnt1 == 63 && r_cnt0 == 3) r_nx_status <= P_WAIT1;elser_nx_status <= r_cu_status; endP_WAIT1 : beginif (r_status_cnt == 12) r_nx_status <= P_READ_PRE;elser_nx_status <= r_cu_status; end P_READ_PRE : beginif (r_cnt1 == 63 && r_cnt0 == 3) r_nx_status <= P_WAIT2;elser_nx_status <= r_cu_status; endP_WAIT2 : beginif (r_status_cnt == 12) r_nx_status <= P_READ;elser_nx_status <= r_cu_status; end P_READ : beginif (r_rd_end) r_nx_status <= P_DONE;else if (r_cnt1 == 54 && r_cnt0 == 3)r_nx_status <= P_WAIT3; elser_nx_status <= r_cu_status; endP_WAIT3 : beginif (r_status_cnt == 10) r_nx_status <= P_READ_PRE;elser_nx_status <= r_cu_status; end P_DONE : beginif (r_status_cnt == 10) r_nx_status <= P_IDLE;elser_nx_status <= r_cu_status; enddefault: r_nx_status <= P_IDLE;endcase
end// 读操作完成信号
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_rd_finish <= 0;else if (r_cu_status == P_DONE && r_status_cnt == 8)r_rd_finish <= 1;elser_rd_finish <= 0;
end// 读操作运行期间
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_read_process <= 0;else if (w_read_start_pos)r_read_process <= 1; else if (r_rd_finish)r_read_process <= 0;elser_read_process <= r_read_process;
end// write driver
// r_cnt0 和 r_cnt1 辅助控制 lmk04803 CLK
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_cnt0 <= 0;else if (r_cu_status == P_WRITE || r_cu_status == P_READ_PRE || r_cu_status == P_READ)r_cnt0 <= r_cnt0 + 1;else r_cnt0 <= 0;
endalways @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_cnt1 <= 0;else if (r_cu_status == P_WAIT3 || r_cu_status == P_DONE)r_cnt1 <= 0; else if (r_cnt1 == 63 && r_cnt0 == 3)r_cnt1 <= 0; else if (r_cnt0 == 3)r_cnt1 <= r_cnt1 + 1;elser_cnt1 <= r_cnt1;
end// 读写操作的时候 bit 计数 ,由于读操作是 CLK 下降沿开始读,所以参考r_read_bit_cnt
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_bit_cnt <= 0;else if (r_cu_status == P_READ && r_cnt1 == 53 && r_cnt0 == 3)r_bit_cnt <= 0; else if ((r_cu_status == P_WRITE || r_cu_status == P_READ_PRE) && r_cnt1 == 63 && r_cnt0 == 3)r_bit_cnt <= 0; else if (r_cnt1[0] && r_cnt0 == 3)r_bit_cnt <= r_bit_cnt + 1;elser_bit_cnt <= r_bit_cnt;
end// 读操作时候的 bit计数
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_read_bit_cnt <= 0;else if (r_read_bit_cnt == 27 && r_cnt1 == 54 && r_cnt0 == 3)r_read_bit_cnt <= 0; else if (r_cu_status == P_READ && !r_cnt1[0] && r_cnt0 == 3)r_read_bit_cnt <= r_read_bit_cnt + 1;elser_read_bit_cnt <= r_read_bit_cnt;
end// 遍历到最后一个寄存器时刻
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_rd_end <= 0;else if (r_cu_status == P_READ && r_rd_cnt == 31 && r_cnt1 == 54 && r_cnt0 == 2)r_rd_end <= 1; elser_rd_end <= 0;
end// 读取 LMK寄存器 个数计数
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_rd_cnt <= 0;else if (r_cu_status == P_READ && r_rd_cnt == 31 && r_cnt1 == 54 && r_cnt0 == 3)r_rd_cnt <= 0;else if (r_cu_status == P_READ && r_cnt1 == 54 && r_cnt0 == 3)r_rd_cnt <= r_rd_cnt + 1; elser_rd_cnt <= r_rd_cnt;
end// 输出的 LMK CLK
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_lmk_clk <= 0;else if (r_cu_status == P_READ && r_cnt1 == 54 && r_cnt0 == 3)r_lmk_clk <= 0;else if (r_cnt0 == 3)r_lmk_clk <= ~r_lmk_clk; elser_lmk_clk <= r_lmk_clk;
end// 输出的 LMK LE
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_lmk_le <= 0;else if (r_cu_status == P_WAIT1 && r_status_cnt > 4 && r_status_cnt < 9)r_lmk_le <= 1; else if (r_cu_status == P_WAIT2 && r_status_cnt > 4 && r_status_cnt < 9)r_lmk_le <= 1; elser_lmk_le <= 0;
end// 使用 SYNC 引脚复用 当做回读引脚的时候,对 LMK R11 写操作配置,可以通过 VIO配置初始值
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_wrdata <= 32'h00000000;
// else if (r_cu_status == P_IDLE)
// r_wrdata <= 32'hAAAA5555; else if (r_cu_status == P_IDLE)r_wrdata <= w_lmk_R11_wr; else if (r_cu_status == P_WRITE && r_cnt1[0]&& r_cnt0 == 3)r_wrdata <= r_wrdata << 1; elser_wrdata <= r_wrdata;
end// 读操作的时候需要对 R31 写操作,然后回读当前寄存器的值
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_addr_write <= 32'h00000000; else if (r_cu_status == P_READ_PRE && r_status_cnt == 0)r_addr_write <= r_readaddr; else if (r_cu_status == P_READ_PRE && r_cnt1[0] && r_cnt0 == 3)r_addr_write <= r_addr_write << 1; elser_addr_write <= r_addr_write ;
end// 遍历读到哪个寄存器前需要知道要读哪个寄存器的地址
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_readaddr <= 32'h00000000; else case (r_rd_cnt) 0: r_readaddr <= 32'h0000001F ;1: r_readaddr <= 32'h0001001F ;2: r_readaddr <= 32'h0002001F ;3: r_readaddr <= 32'h0003001F ;4: r_readaddr <= 32'h0004001F ;5: r_readaddr <= 32'h0005001F ;6: r_readaddr <= 32'h0006001F ;7: r_readaddr <= 32'h0007001F ;8: r_readaddr <= 32'h0008001F ;9: r_readaddr <= 32'h0009001F ;10: r_readaddr <= 32'h000A001F ;11: r_readaddr <= 32'h000B001F ;12: r_readaddr <= 32'h000C001F ;13: r_readaddr <= 32'h000D001F ;14: r_readaddr <= 32'h000E001F ;15: r_readaddr <= 32'h000F001F ;16: r_readaddr <= 32'h0010001F ;17: r_readaddr <= 32'h0011001F ;18: r_readaddr <= 32'h0012001F ;19: r_readaddr <= 32'h0013001F ;20: r_readaddr <= 32'h0014001F ;21: r_readaddr <= 32'h0015001F ;22: r_readaddr <= 32'h0016001F ;23: r_readaddr <= 32'h0017001F ;24: r_readaddr <= 32'h0018001F ;25: r_readaddr <= 32'h0019001F ;26: r_readaddr <= 32'h001A001F ;27: r_readaddr <= 32'h001B001F ;28: r_readaddr <= 32'h001C001F ;29: r_readaddr <= 32'h001D001F ;30: r_readaddr <= 32'h001E001F ;31: r_readaddr <= 32'h001F001F ;default : r_readaddr <= 32'h00000000;endcase
end// 回读的数据
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_readin <= 0; else if (r_cu_status == P_READ_PRE )r_readin <= 0; else if (r_cu_status == P_READ && r_cnt1[0] && r_cnt0 == 3)r_readin <= {r_readin[25:0],i_rd_data}; else r_readin <= r_readin;
end//回读数据有效
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_read_valid <= 0; else if (r_cu_status == P_READ && r_cnt1 == 54 && r_cnt0 == 3)r_read_valid <= 1; else r_read_valid <= 0;
end// 记录 回读到有效寄存器值的个数
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_valid_cnt <= 0; else if (r_cu_status == P_DONE)r_valid_cnt <= 0; else if (r_read_valid)r_valid_cnt <= r_valid_cnt + 1;elser_valid_cnt <= r_valid_cnt;
endendmodule