主要思路:
 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