主要思路:
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 : R
0000001F : 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)
begin
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
LMK_R[i] <= 0;
else if (r_read_valid && r_valid_cnt == i)
LMK_R[i] <= r_readin;
else
LMK_R[i] <= LMK_R[i];
end
end
endgenerate
// 开始标志
always @ (posedge i_clk)
begin
r_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)
begin
if (!i_rstn)
r_cu_status <= P_IDLE;
else
r_cu_status <= r_nx_status;
end
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
r_status_cnt <= 0;
else if (r_cu_status != r_nx_status)
r_status_cnt <= 0;
else
r_status_cnt <= r_status_cnt + 1;
end
always @ (*)
begin
case (r_cu_status)
P_IDLE : begin
if (w_read_start_pos)
r_nx_status <= P_START;
else
r_nx_status <= r_cu_status;
end
P_START : begin
if (r_status_cnt == 10)
r_nx_status <= P_WRITE;
else
r_nx_status <= r_cu_status;
end
P_WRITE : begin
if (r_cnt1 == 63 && r_cnt0 == 3)
r_nx_status <= P_WAIT1;
else
r_nx_status <= r_cu_status;
end
P_WAIT1 : begin
if (r_status_cnt == 12)
r_nx_status <= P_READ_PRE;
else
r_nx_status <= r_cu_status;
end
P_READ_PRE : begin
if (r_cnt1 == 63 && r_cnt0 == 3)
r_nx_status <= P_WAIT2;
else
r_nx_status <= r_cu_status;
end
P_WAIT2 : begin
if (r_status_cnt == 12)
r_nx_status <= P_READ;
else
r_nx_status <= r_cu_status;
end
P_READ : begin
if (r_rd_end)
r_nx_status <= P_DONE;
else if (r_cnt1 == 54 && r_cnt0 == 3)
r_nx_status <= P_WAIT3;
else
r_nx_status <= r_cu_status;
end
P_WAIT3 : begin
if (r_status_cnt == 10)
r_nx_status <= P_READ_PRE;
else
r_nx_status <= r_cu_status;
end
P_DONE : begin
if (r_status_cnt == 10)
r_nx_status <= P_IDLE;
else
r_nx_status <= r_cu_status;
end
default: r_nx_status <= P_IDLE;
endcase
end
// 读操作完成信号
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
r_rd_finish <= 0;
else if (r_cu_status == P_DONE && r_status_cnt == 8)
r_rd_finish <= 1;
else
r_rd_finish <= 0;
end
// 读操作运行期间
always @ (posedge i_clk or negedge i_rstn)
begin
if (!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;
else
r_read_process <= r_read_process;
end
// write driver
// r_cnt0 和 r_cnt1 辅助控制 lmk04803 CLK
always @ (posedge i_clk or negedge i_rstn)
begin
if (!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;
end
always @ (posedge i_clk or negedge i_rstn)
begin
if (!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;
else
r_cnt1 <= r_cnt1;
end
// 读写操作的时候 bit 计数 ,由于读操作是 CLK 下降沿开始读,所以参考r_read_bit_cnt
always @ (posedge i_clk or negedge i_rstn)
begin
if (!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;
else
r_bit_cnt <= r_bit_cnt;
end
// 读操作时候的 bit计数
always @ (posedge i_clk or negedge i_rstn)
begin
if (!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;
else
r_read_bit_cnt <= r_read_bit_cnt;
end
// 遍历到最后一个寄存器时刻
always @ (posedge i_clk or negedge i_rstn)
begin
if (!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;
else
r_rd_end <= 0;
end
// 读取 LMK寄存器 个数计数
always @ (posedge i_clk or negedge i_rstn)
begin
if (!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;
else
r_rd_cnt <= r_rd_cnt;
end
// 输出的 LMK CLK
always @ (posedge i_clk or negedge i_rstn)
begin
if (!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;
else
r_lmk_clk <= r_lmk_clk;
end
// 输出的 LMK LE
always @ (posedge i_clk or negedge i_rstn)
begin
if (!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;
else
r_lmk_le <= 0;
end
// 使用 SYNC 引脚复用 当做回读引脚的时候,对 LMK R11 写操作配置,可以通过 VIO配置初始值
always @ (posedge i_clk or negedge i_rstn)
begin
if (!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;
else
r_wrdata <= r_wrdata;
end
// 读操作的时候需要对 R31 写操作,然后回读当前寄存器的值
always @ (posedge i_clk or negedge i_rstn)
begin
if (!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;
else
r_addr_write <= r_addr_write ;
end
// 遍历读到哪个寄存器前需要知道要读哪个寄存器的地址
always @ (posedge i_clk or negedge i_rstn)
begin
if (!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)
begin
if (!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)
begin
if (!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)
begin
if (!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;
else
r_valid_cnt <= r_valid_cnt;
end
endmodule