6 changed files with 502 additions and 113 deletions
-
142led_test.pds
-
193source/src/timecode/timecode_decoder.v
-
53source/src/timecode/timecode_sample_sig_generator.v
-
113source/src/timecode_input.v
-
30source/src/top.v
-
84source/test/test_timecode_decoder.v
@ -0,0 +1,193 @@ |
|||||
|
module timecode_decoder #( |
||||
|
parameter SYS_CLOCK_FREQ = 10000000 |
||||
|
) ( |
||||
|
input clk, //clock input |
||||
|
input rst_n, //asynchronous reset input, low active |
||||
|
|
||||
|
input timecode_in, |
||||
|
output timecode_in_state, |
||||
|
|
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* TIMECODE输出 * |
||||
|
*******************************************************************************/ |
||||
|
output reg timecode_tigger_sig, |
||||
|
output reg [63:0] timecode_data, |
||||
|
// output [31:0] timecode_format, |
||||
|
output timecode_serial_data |
||||
|
); |
||||
|
|
||||
|
// Rate 1/2Fe 1Fe |
||||
|
// 23.98 F/s 260.7 us 521.4 us |
||||
|
// 24.00 F/s 260.4 us 520.8 us |
||||
|
// 25.00 F/s 250.0 us 500.0 us |
||||
|
// 29.97 F/s 208.5 us 417.1 us |
||||
|
// 30.00 F/s 208.3 us 416.7 us |
||||
|
|
||||
|
// 260->520 -->130 |
||||
|
// 208->416 -->104 |
||||
|
// ---> 117us 351us |
||||
|
// |
||||
|
// 由于TIMECODE的频率范围是固定的,所以这里采用117,和351作为其采样点,这样既可以采样23.98也可以采样30.00 |
||||
|
// 对应的采样频率为1000000/117=8547HZ |
||||
|
// |
||||
|
|
||||
|
// 原始数据输出 |
||||
|
assign timecode_serial_data = timecode_in; |
||||
|
assign timecode_in_state = timecode_in; |
||||
|
|
||||
|
wire timecode_sample_sig_generator_rest_sig; |
||||
|
wire timecode_in_edge; |
||||
|
assign timecode_sample_sig_generator_rest_sig = !timecode_in_edge & rst_n; |
||||
|
zutils_edge_detecter _signal_in ( |
||||
|
.clk(clk), |
||||
|
.rst_n(rst_n), |
||||
|
.in_signal(timecode_in), |
||||
|
.in_signal_edge(timecode_in_edge) |
||||
|
); |
||||
|
wire sample_sig; |
||||
|
timecode_sample_sig_generator #( |
||||
|
.SYS_CLOCK_FREQ(SYS_CLOCK_FREQ), |
||||
|
.SAMPLE_RATE(854700) |
||||
|
) timecode_sample_sig_generator ( |
||||
|
.clk(clk), |
||||
|
.rst_n(timecode_sample_sig_generator_rest_sig), |
||||
|
.sample_sig(sample_sig) |
||||
|
); |
||||
|
|
||||
|
|
||||
|
// 采样+缓存采样数据 |
||||
|
reg [159:0] timecode_data_cache; |
||||
|
always @(posedge clk or negedge rst_n) begin |
||||
|
if (!rst_n) begin |
||||
|
timecode_data_cache <= 0; |
||||
|
end else begin |
||||
|
if (sample_sig) begin |
||||
|
timecode_data_cache <= {timecode_in,timecode_data_cache[159:1]}; |
||||
|
end else begin |
||||
|
timecode_data_cache <= timecode_data_cache; |
||||
|
end |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
//译码 |
||||
|
reg [79:0] timecode_bit_cache; |
||||
|
// integer i; |
||||
|
always @(*) begin |
||||
|
// for (i = 0; i < 79; i = i + 1) begin |
||||
|
// timecode_bit_cache[i] = timecode_data_cache[i*2] & !timecode_data_cache[i*2+1]; |
||||
|
// end |
||||
|
|
||||
|
timecode_bit_cache[0] = timecode_data_cache[0] ^ timecode_data_cache[1]; |
||||
|
timecode_bit_cache[1] = timecode_data_cache[2] ^ timecode_data_cache[3]; |
||||
|
timecode_bit_cache[2] = timecode_data_cache[4] ^ timecode_data_cache[5]; |
||||
|
timecode_bit_cache[3] = timecode_data_cache[6] ^ timecode_data_cache[7]; |
||||
|
timecode_bit_cache[4] = timecode_data_cache[8] ^ timecode_data_cache[9]; |
||||
|
timecode_bit_cache[5] = timecode_data_cache[10] ^ timecode_data_cache[11]; |
||||
|
timecode_bit_cache[6] = timecode_data_cache[12] ^ timecode_data_cache[13]; |
||||
|
timecode_bit_cache[7] = timecode_data_cache[14] ^ timecode_data_cache[15]; |
||||
|
timecode_bit_cache[8] = timecode_data_cache[16] ^ timecode_data_cache[17]; |
||||
|
timecode_bit_cache[9] = timecode_data_cache[18] ^ timecode_data_cache[19]; |
||||
|
timecode_bit_cache[10] = timecode_data_cache[20] ^ timecode_data_cache[21]; |
||||
|
timecode_bit_cache[11] = timecode_data_cache[22] ^ timecode_data_cache[23]; |
||||
|
timecode_bit_cache[12] = timecode_data_cache[24] ^ timecode_data_cache[25]; |
||||
|
timecode_bit_cache[13] = timecode_data_cache[26] ^ timecode_data_cache[27]; |
||||
|
timecode_bit_cache[14] = timecode_data_cache[28] ^ timecode_data_cache[29]; |
||||
|
timecode_bit_cache[15] = timecode_data_cache[30] ^ timecode_data_cache[31]; |
||||
|
timecode_bit_cache[16] = timecode_data_cache[32] ^ timecode_data_cache[33]; |
||||
|
timecode_bit_cache[17] = timecode_data_cache[34] ^ timecode_data_cache[35]; |
||||
|
timecode_bit_cache[18] = timecode_data_cache[36] ^ timecode_data_cache[37]; |
||||
|
timecode_bit_cache[19] = timecode_data_cache[38] ^ timecode_data_cache[39]; |
||||
|
timecode_bit_cache[20] = timecode_data_cache[40] ^ timecode_data_cache[41]; |
||||
|
timecode_bit_cache[21] = timecode_data_cache[42] ^ timecode_data_cache[43]; |
||||
|
timecode_bit_cache[22] = timecode_data_cache[44] ^ timecode_data_cache[45]; |
||||
|
timecode_bit_cache[23] = timecode_data_cache[46] ^ timecode_data_cache[47]; |
||||
|
timecode_bit_cache[24] = timecode_data_cache[48] ^ timecode_data_cache[49]; |
||||
|
timecode_bit_cache[25] = timecode_data_cache[50] ^ timecode_data_cache[51]; |
||||
|
timecode_bit_cache[26] = timecode_data_cache[52] ^ timecode_data_cache[53]; |
||||
|
timecode_bit_cache[27] = timecode_data_cache[54] ^ timecode_data_cache[55]; |
||||
|
timecode_bit_cache[28] = timecode_data_cache[56] ^ timecode_data_cache[57]; |
||||
|
timecode_bit_cache[29] = timecode_data_cache[58] ^ timecode_data_cache[59]; |
||||
|
timecode_bit_cache[30] = timecode_data_cache[60] ^ timecode_data_cache[61]; |
||||
|
timecode_bit_cache[31] = timecode_data_cache[62] ^ timecode_data_cache[63]; |
||||
|
timecode_bit_cache[32] = timecode_data_cache[64] ^ timecode_data_cache[65]; |
||||
|
timecode_bit_cache[33] = timecode_data_cache[66] ^ timecode_data_cache[67]; |
||||
|
timecode_bit_cache[34] = timecode_data_cache[68] ^ timecode_data_cache[69]; |
||||
|
timecode_bit_cache[35] = timecode_data_cache[70] ^ timecode_data_cache[71]; |
||||
|
timecode_bit_cache[36] = timecode_data_cache[72] ^ timecode_data_cache[73]; |
||||
|
timecode_bit_cache[37] = timecode_data_cache[74] ^ timecode_data_cache[75]; |
||||
|
timecode_bit_cache[38] = timecode_data_cache[76] ^ timecode_data_cache[77]; |
||||
|
timecode_bit_cache[39] = timecode_data_cache[78] ^ timecode_data_cache[79]; |
||||
|
timecode_bit_cache[40] = timecode_data_cache[80] ^ timecode_data_cache[81]; |
||||
|
timecode_bit_cache[41] = timecode_data_cache[82] ^ timecode_data_cache[83]; |
||||
|
timecode_bit_cache[42] = timecode_data_cache[84] ^ timecode_data_cache[85]; |
||||
|
timecode_bit_cache[43] = timecode_data_cache[86] ^ timecode_data_cache[87]; |
||||
|
timecode_bit_cache[44] = timecode_data_cache[88] ^ timecode_data_cache[89]; |
||||
|
timecode_bit_cache[45] = timecode_data_cache[90] ^ timecode_data_cache[91]; |
||||
|
timecode_bit_cache[46] = timecode_data_cache[92] ^ timecode_data_cache[93]; |
||||
|
timecode_bit_cache[47] = timecode_data_cache[94] ^ timecode_data_cache[95]; |
||||
|
timecode_bit_cache[48] = timecode_data_cache[96] ^ timecode_data_cache[97]; |
||||
|
timecode_bit_cache[49] = timecode_data_cache[98] ^ timecode_data_cache[99]; |
||||
|
timecode_bit_cache[50] = timecode_data_cache[100] ^ timecode_data_cache[101]; |
||||
|
timecode_bit_cache[51] = timecode_data_cache[102] ^ timecode_data_cache[103]; |
||||
|
timecode_bit_cache[52] = timecode_data_cache[104] ^ timecode_data_cache[105]; |
||||
|
timecode_bit_cache[53] = timecode_data_cache[106] ^ timecode_data_cache[107]; |
||||
|
timecode_bit_cache[54] = timecode_data_cache[108] ^ timecode_data_cache[109]; |
||||
|
timecode_bit_cache[55] = timecode_data_cache[110] ^ timecode_data_cache[111]; |
||||
|
timecode_bit_cache[56] = timecode_data_cache[112] ^ timecode_data_cache[113]; |
||||
|
timecode_bit_cache[57] = timecode_data_cache[114] ^ timecode_data_cache[115]; |
||||
|
timecode_bit_cache[58] = timecode_data_cache[116] ^ timecode_data_cache[117]; |
||||
|
timecode_bit_cache[59] = timecode_data_cache[118] ^ timecode_data_cache[119]; |
||||
|
timecode_bit_cache[60] = timecode_data_cache[120] ^ timecode_data_cache[121]; |
||||
|
timecode_bit_cache[61] = timecode_data_cache[122] ^ timecode_data_cache[123]; |
||||
|
timecode_bit_cache[62] = timecode_data_cache[124] ^ timecode_data_cache[125]; |
||||
|
timecode_bit_cache[63] = timecode_data_cache[126] ^ timecode_data_cache[127]; |
||||
|
timecode_bit_cache[64] = timecode_data_cache[128] ^ timecode_data_cache[129]; |
||||
|
timecode_bit_cache[65] = timecode_data_cache[130] ^ timecode_data_cache[131]; |
||||
|
timecode_bit_cache[66] = timecode_data_cache[132] ^ timecode_data_cache[133]; |
||||
|
timecode_bit_cache[67] = timecode_data_cache[134] ^ timecode_data_cache[135]; |
||||
|
timecode_bit_cache[68] = timecode_data_cache[136] ^ timecode_data_cache[137]; |
||||
|
timecode_bit_cache[69] = timecode_data_cache[138] ^ timecode_data_cache[139]; |
||||
|
timecode_bit_cache[70] = timecode_data_cache[140] ^ timecode_data_cache[141]; |
||||
|
timecode_bit_cache[71] = timecode_data_cache[142] ^ timecode_data_cache[143]; |
||||
|
timecode_bit_cache[72] = timecode_data_cache[144] ^ timecode_data_cache[145]; |
||||
|
timecode_bit_cache[73] = timecode_data_cache[146] ^ timecode_data_cache[147]; |
||||
|
timecode_bit_cache[74] = timecode_data_cache[148] ^ timecode_data_cache[149]; |
||||
|
timecode_bit_cache[75] = timecode_data_cache[150] ^ timecode_data_cache[151]; |
||||
|
timecode_bit_cache[76] = timecode_data_cache[152] ^ timecode_data_cache[153]; |
||||
|
timecode_bit_cache[77] = timecode_data_cache[154] ^ timecode_data_cache[155]; |
||||
|
timecode_bit_cache[78] = timecode_data_cache[156] ^ timecode_data_cache[157]; |
||||
|
timecode_bit_cache[79] = timecode_data_cache[158] ^ timecode_data_cache[159]; |
||||
|
end |
||||
|
|
||||
|
// 识别信号捕获 |
||||
|
wire [15:0] synccode; |
||||
|
assign synccode = timecode_bit_cache[79:64]; |
||||
|
assign detect_sync_code = (synccode == 16'b1011_1111_1111_1100); |
||||
|
|
||||
|
|
||||
|
wire detect_sync_code_sig; |
||||
|
zutils_edge_detecter detect_sync_code_detect ( |
||||
|
.clk(clk), |
||||
|
.rst_n(rst_n), |
||||
|
.in_signal(detect_sync_code), |
||||
|
.in_signal_rising_edge(detect_sync_code_sig) |
||||
|
); |
||||
|
|
||||
|
//输出时码识别信号 |
||||
|
|
||||
|
always @(posedge clk or negedge rst_n) begin |
||||
|
if (!rst_n) begin |
||||
|
timecode_tigger_sig <= 0; |
||||
|
timecode_data <= 0; |
||||
|
end else begin |
||||
|
if (detect_sync_code_sig) begin |
||||
|
timecode_tigger_sig <= 1; |
||||
|
timecode_data <= timecode_bit_cache[63:0]; |
||||
|
end else begin |
||||
|
timecode_tigger_sig <= 0; |
||||
|
end |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
endmodule |
@ -0,0 +1,53 @@ |
|||||
|
module timecode_sample_sig_generator #( |
||||
|
parameter SYS_CLOCK_FREQ = 10000000, |
||||
|
parameter SAMPLE_RATE = 8547 |
||||
|
) ( |
||||
|
input clk, //clock input |
||||
|
input rst_n, //asynchronous reset input, low active |
||||
|
|
||||
|
output reg sample_sig |
||||
|
); |
||||
|
|
||||
|
|
||||
|
// |
||||
|
// sampleSig ______|____________|____________|____________| |
||||
|
// |
||||
|
|
||||
|
localparam COUNT = (SYS_CLOCK_FREQ * 100) / SAMPLE_RATE; |
||||
|
reg [31:0] counter; |
||||
|
reg [1:0] sub_counter; |
||||
|
|
||||
|
wire counter_clear; |
||||
|
always @(posedge clk or negedge rst_n) begin |
||||
|
if (!rst_n) begin |
||||
|
counter <= 0; |
||||
|
sub_counter <= 1; |
||||
|
end else begin |
||||
|
|
||||
|
if (counter == COUNT) begin |
||||
|
counter <= 0; |
||||
|
|
||||
|
if (sub_counter == 1) begin |
||||
|
sample_sig <= 1; |
||||
|
sub_counter <= 0; |
||||
|
end else begin |
||||
|
sub_counter <= 1; |
||||
|
end |
||||
|
|
||||
|
end else begin |
||||
|
counter <= counter + 1; |
||||
|
sample_sig <= 0; |
||||
|
end |
||||
|
|
||||
|
end |
||||
|
end |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
endmodule |
@ -0,0 +1,113 @@ |
|||||
|
module timecode_input_parser #( |
||||
|
parameter REG_START_ADD = 0, |
||||
|
parameter SYS_CLOCK_FREQ = 10000000 |
||||
|
) ( |
||||
|
input clk, //clock input |
||||
|
input rst_n, //asynchronous reset input, low active |
||||
|
|
||||
|
//寄存器读写接口 |
||||
|
input [31:0] addr, |
||||
|
input [31:0] wr_data, |
||||
|
input wr_en, |
||||
|
output wire [31:0] rd_data, |
||||
|
|
||||
|
input timecode_bnc_in, |
||||
|
input timecode_headphone_in, |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* TIMECODE输出 * |
||||
|
*******************************************************************************/ |
||||
|
output timecode_tigger_sig, |
||||
|
output [31:0] timecode_format, |
||||
|
output [63:0] timecode_data, |
||||
|
output timecode_serial_data, |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 指示灯状态输出 * |
||||
|
*******************************************************************************/ |
||||
|
output timecode_headphone_in_state_led, |
||||
|
output timecode_bnc_in_state_led |
||||
|
|
||||
|
); |
||||
|
|
||||
|
|
||||
|
reg [31:0] r0_timecode_sig_selt; //信号源选择 0:off,1:bnc,2:headphone |
||||
|
reg [31:0] r1_timecode_format; // |
||||
|
reg [31:0] r2_timecode0; // |
||||
|
reg [31:0] r3_timecode1; // |
||||
|
wire [31:0] reg_wr_index; |
||||
|
zutils_register_advanced #( |
||||
|
.REG_START_ADD(REG_START_ADD) |
||||
|
) _register ( |
||||
|
.clk(clk), |
||||
|
.rst_n(rst_n), |
||||
|
.addr(addr), |
||||
|
.wr_data(wr_data), |
||||
|
.wr_en(wr_en), |
||||
|
.rd_data(rd_data), |
||||
|
|
||||
|
.reg0(r0_timecode_sig_selt), |
||||
|
.reg1(r1_timecode_format), |
||||
|
.reg2(r2_timecode0), |
||||
|
.reg3(r3_timecode1), |
||||
|
|
||||
|
.reg_wr_sig(reg_wr_sig), |
||||
|
.reg_index (reg_wr_index) |
||||
|
); |
||||
|
|
||||
|
always @(posedge clk or negedge rst_n) begin |
||||
|
if (!rst_n) begin |
||||
|
r0_timecode_sig_selt <= 0; |
||||
|
r1_timecode_format <= 0; |
||||
|
end else begin |
||||
|
if (reg_wr_sig) begin |
||||
|
case (reg_wr_index) |
||||
|
31'h0: r0_timecode_sig_selt <= wr_data; |
||||
|
31'h1: r1_timecode_format <= wr_data; |
||||
|
default: begin |
||||
|
end |
||||
|
endcase |
||||
|
end |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
wire timecode_in_af_selt; |
||||
|
zutils_multiplexer_4t1 _signal_select ( |
||||
|
.chooseindex(r0_timecode_sig_selt), |
||||
|
.signal0(1'b0), |
||||
|
.signal1(timecode_bnc_in), |
||||
|
.signal2(timecode_headphone_in), |
||||
|
.signalout(timecode_in_af_selt) |
||||
|
); |
||||
|
|
||||
|
timecode_decoder #( |
||||
|
.SYS_CLOCK_FREQ(10000000) |
||||
|
) timecode_decoder_ins ( |
||||
|
.clk(clk), |
||||
|
.rst_n(rst_n), |
||||
|
.timecode_in(timecode_in_af_selt), // 时码输入 |
||||
|
.timecode_tigger_sig(timecode_tigger_sig), // |
||||
|
.timecode_data(timecode_data), //[63:0] |
||||
|
.timecode_serial_data(timecode_serial_data) // |
||||
|
); |
||||
|
|
||||
|
|
||||
|
|
||||
|
always @(posedge clk or negedge rst_n) begin |
||||
|
if (!rst_n) begin |
||||
|
r2_timecode0 <= 0; |
||||
|
r3_timecode1 <= 0; |
||||
|
end else begin |
||||
|
if (timecode_tigger_sig) begin |
||||
|
r2_timecode0 <= timecode_data[31:0]; |
||||
|
r3_timecode1 <= timecode_data[63:32]; |
||||
|
end |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
assign timecode_format = r1_timecode_format; |
||||
|
assign timecode_headphone_in_state_led = 1; |
||||
|
assign timecode_bnc_in_state_led = 1; |
||||
|
|
||||
|
|
||||
|
endmodule |
@ -0,0 +1,84 @@ |
|||||
|
`timescale 10ns / 10ns |
||||
|
module test_timecode_decoder; |
||||
|
reg sys_clk; |
||||
|
reg rst_n; |
||||
|
|
||||
|
reg timecode_in; |
||||
|
|
||||
|
reg one_timecode_end; |
||||
|
reg datanow; |
||||
|
|
||||
|
wire timecode_in_state; |
||||
|
wire timecode_tigger_sig; |
||||
|
wire [63:0] timecode_data; |
||||
|
wire timecode_serial_data; |
||||
|
reg [7:0] offset; |
||||
|
|
||||
|
timecode_decoder #( |
||||
|
.SYS_CLOCK_FREQ(10000000) |
||||
|
) timecode_decoder_inst ( |
||||
|
.clk (sys_clk), |
||||
|
.rst_n(rst_n), |
||||
|
|
||||
|
.timecode_in(timecode_in), |
||||
|
.timecode_in_state(timecode_in_state), |
||||
|
|
||||
|
.timecode_tigger_sig(timecode_tigger_sig), |
||||
|
.timecode_data(timecode_data), |
||||
|
.timecode_serial_data(timecode_serial_data) |
||||
|
); |
||||
|
|
||||
|
|
||||
|
// 250us |
||||
|
task timecode_generator; |
||||
|
input [79:0] data; |
||||
|
integer i; |
||||
|
begin |
||||
|
for (i = 0; i < 80; i = i + 1) begin |
||||
|
offset = i; |
||||
|
if (data[i]) begin |
||||
|
datanow = 1; |
||||
|
end else begin |
||||
|
datanow = 0; |
||||
|
end |
||||
|
timecode_in = ~timecode_in; |
||||
|
#25000; |
||||
|
if (data[i]) begin |
||||
|
timecode_in = ~timecode_in; |
||||
|
end |
||||
|
#25000; |
||||
|
end |
||||
|
end |
||||
|
endtask |
||||
|
|
||||
|
initial begin |
||||
|
sys_clk = 0; |
||||
|
rst_n = 0; |
||||
|
#100; |
||||
|
rst_n = 1; |
||||
|
timecode_in = 0; |
||||
|
one_timecode_end = 0; |
||||
|
#100; |
||||
|
|
||||
|
// |
||||
|
// timecode_generator(79'h1234_4321_1234_4321_CFFB); |
||||
|
// timecode_generator(79'h0000_0000_0000_0000_CFFB); |
||||
|
timecode_generator(80'hBFFC_0000_0000_0000_0000); |
||||
|
// timecode_generator(79'b1011_1111_1111_1100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000); |
||||
|
//FFFF |
||||
|
//4444 |
||||
|
//16+16+16+16+16 |
||||
|
// 32 32 80 |
||||
|
// |
||||
|
|
||||
|
// timecode_generator(79'hBFFC_0000_0000_0000_0000); |
||||
|
// timecode_generator(79'hBFFC_0000_0000_0000_0000); |
||||
|
one_timecode_end = 1; |
||||
|
#1000000; |
||||
|
timecode_generator(80'hBFFC_0102_0304_0506_0102); |
||||
|
|
||||
|
#100000000; |
||||
|
$stop; |
||||
|
end |
||||
|
always #5 sys_clk = ~sys_clk; // 50MHZ时钟 |
||||
|
endmodule |
Write
Preview
Loading…
Cancel
Save
Reference in new issue