module src_timecode_parser #( parameter REG_START_ADD = 0 ) ( input clk, //clock input input rst_n, //asynchronous reset input, low active //regbus interface output reg [31:0] addr, input [31:0] wr_data, input wr_en, inout wire [31:0] rd_data, //received serial data // 输入 input timecode_signal_in, //输出 output wire timecode_signal_orgin_output, //ttl原始数据 output wire timecode_freq_trigger_signal ); /******************************************************************************* * 寄存器读写 * *******************************************************************************/ // // @功能: // 1. 采样TIMECODE信号 // 2. 转发TIMECODE信号 // 3. TIMECODE信号成功解析 // 4. TIMECODE采样计数 // // @寄存器列表: // 地址 读写 默认 描述 // 0x00 wr 0x0 timecode bit周期 // 0x01 r 0x0 flag bit[0]:timecode_ready_flag // 0x02 r 0x0 timecode [31:0] // 0x03 r 0x0 timecode [63:32] // 0x04 r 0x0 timecode_ready_signal_pluse_width //识别到一帧timecode信号后,输出一个脉冲信号,用于同步其他模块 parameter REG_TIMECODE_BIT_PERIOD_ADD = REG_START_ADD + 0; //timecode bit周期寄存器地址 parameter ADD_NUM = 5; //寄存器数量 parameter REG_END_ADD = REG_START_ADD + ADD_NUM - 1; //寄存器结束地址 reg [31:0] register[REG_START_ADD:REG_END_ADD]; integer i; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin for (i = 0; i < ADD_NUM; i = i + 1) begin register[i] <= 0; end end else begin if (wr_en && addr >= REG_START_ADD && addr <= REG_END_ADD) register[addr] <= wr_data; end end assign rd_data = (addr >= REG_START_ADD && addr <= REG_END_ADD) ? register[addr] : 31'bz; // 416us 500us 520us // 边沿触发--> 采样偏移同步 // // 416us采用 160byte 采样到同步 // 电平变化修正采样计数 // // 配置: // 1. 制式 // 2. // 边沿信号捕获 reg [160-1:0] tc_bit_2x; //timecode 每1/2bit reg [79:0] tc_bit; //timecode 每1bit reg sample_signal; //采样信号 reg [31:0] sample_time_cnt; //采样计数 wire sample_time_calibrate_signal; //采样信号修正器 reg time_code_signal_edge; //timecode原始信号的边沿信号,即timecode上升沿或者下降沿时,置1 assign timecode_signal_in_a = timecode_signal_in; // reg timecode_signal_in_b; // reg tc_sync_signal_edge; // timecode捕获到同步信号时,置1,此时可以解析timecode信号,并将其存放到寄存中 /******************************************************************************* * timecode边沿信号捕获 * *******************************************************************************/ always @(posedge clk or negedge rst_n) begin if (!rst_n) begin timecode_signal_in_b <= 0; end else begin timecode_signal_in_b <= timecode_signal_in_a; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin time_code_signal_edge <= 0; end else begin if (timecode_signal_in_a != timecode_signal_in_b) begin time_code_signal_edge <= 1; end else begin time_code_signal_edge <= 0; end end end assign sample_time_calibrate_signal = time_code_signal_edge; /******************************************************************************* * BIT信号映射 * *******************************************************************************/ // // 采样点 采样点 采样点 采样点 // + + + + // ___------------_______-------- // 0 1 // timecode的每个bit要通过两个点进行判断,所以需要2x的采样率 // always @(*) begin for (i = 0; i < 79; i = i + 1) begin tc_bit[i] = !tc_bit_2x[i*2] & tc_bit_2x[i*2+1]; end end /******************************************************************************* * 采样信号生成器 * *******************************************************************************/ // // 1. 当捕获到timecode原始信号的边沿时,校准采样信号计数器 // 2. 当采样信号计数器到达采样点时,输出采样信号 // 3. 当采样信号计数器到达2倍采样点时,重置采样信号计数器 // assign timecode_sample_cnt_reset_signal = ( sample_time_calibrate_signal|| sample_time_cnt >= (register[REG_TIMECODE_BIT_PERIOD_ADD] << 1) ); always @(posedge clk or negedge rst_n) begin if (!rst_n) begin sample_time_cnt <= 0; sample_signal <= 0; end else begin if (timecode_sample_cnt_reset_signal) begin sample_time_cnt <= 0; sample_signal <= 0; end else if (sample_time_cnt == register[REG_TIMECODE_BIT_PERIOD_ADD]) begin sample_time_cnt <= sample_time_cnt + 1; sample_signal <= 1; end else begin sample_time_cnt <= sample_time_cnt + 1; sample_signal <= 0; end end end // // 根据sample_signal捕获timecode信号 // always @(posedge clk or negedge rst_n) begin if (!rst_n) begin tc_bit_2x <= 0; end else begin if (sample_signal) begin tc_bit_2x <= {tc_bit_2x[158:0], timecode_signal_in}; end else begin tc_bit_2x <= tc_bit_2x; end end end /******************************************************************************* * tc_sync_signal_edge * *******************************************************************************/ // ___------------_______-------- // 0 1 // // 捕获timecode同步信号 // // 同步信号 // 0011_1111_11111_1101 // 1111_0101__0101_0101__0101_0101__0101_1101 // reg [31:0] sync_code_pattern = 32'b1111_0101__0101_0101__0101_0101__0101_1101; assign tc_sync_signal = (tc_bit == sync_code_pattern); reg tc_sync_signal_b; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin tc_sync_signal_b <= 0; end else begin tc_sync_signal_b <= tc_sync_signal; if (tc_sync_signal & !tc_sync_signal_b) begin tc_sync_signal_edge <= 1; end else begin tc_sync_signal_edge <= 0; end end end assign timecode_freq_trigger_signal = tc_sync_signal_edge; endmodule