异步16信号同步输出
module firemap_channel_align #(
parameter [4:0] HEADER_FF_NUM = 5'd16
)(
input wire clk_i, // 250M时钟
input wire rst_n_i, // 同步低有效复位
input wire cap_pulse_i, // 原始采样脉冲
input wire [7:0] fmr_i, // 原始FMR0~7
input wire [7:0] fml_i, // 原始FML0~7
input wire aligned_ready_i, // 后级可接收
output reg [7:0] aligned_fmr_o, // 对齐后FMR0~7
output reg [7:0] aligned_fml_o, // 对齐后FML0~7
output reg aligned_valid_o, // 对齐后数据有效
output reg aligned_frame_done_o,// 一帧64点输出完成
output wire busy_o, // 忙
output reg overflow_o // 对齐溢出
);
localparam [2:0] CH_FIND = 3'b001; // 通道找帧头
localparam [2:0] CH_DATA = 3'b010; // 通道收64bit数据
localparam [2:0] CH_DONE = 3'b100; // 通道本帧完成
localparam [3:0] ST_IDLE = 4'b0001; // 输出空闲
localparam [3:0] ST_SEND = 4'b0010; // 输出有效
localparam [3:0] ST_GAP = 4'b0100; // 输出间隔
localparam [3:0] ST_DONE = 4'b1000; // 输出完成
reg cap_pulse_d1; // cap延迟
wire cap_pos_w; // cap上升沿
reg [2:0] ch_state_r [0:15]; // 每通道状态
reg [4:0] head_cnt_r [0:15]; // 每通道帧头计数
reg [5:0] bit_cnt_r [0:15]; // 每通道数据bit计数
reg [63:0] buf0_r [0:15]; // buffer0
reg [63:0] buf1_r [0:15]; // buffer1
reg [15:0] done_mask_r; // 当前写bank通道完成标志
reg wr_bank_r; // 当前写bank
reg rd_bank_r; // 当前读bank
reg buf0_full_r; // buffer0满
reg buf1_full_r; // buffer1满
reg [3:0] state_r; // 输出状态
reg [3:0] state_nxt; // 输出下一状态
reg [5:0] out_pix_idx_r; // 输出像素序号0~63
reg [1:0] gap_cnt_r; // 输出间隔计数
wire [15:0] ch_bit_w; // 16通道输入bit
wire all_ch_done_w; // 16通道全部完成
wire rd_buf_full_w; // 当前读bank满
wire out_fire_w; // 输出握手成功
integer ch_i; // 循环变量
assign cap_pos_w = cap_pulse_i & ~cap_pulse_d1;
assign ch_bit_w = {fml_i, fmr_i};
assign all_ch_done_w = (done_mask_r == 16'hffff);
assign rd_buf_full_w = rd_bank_r ? buf1_full_r : buf0_full_r;
assign out_fire_w = aligned_valid_o && aligned_ready_i;
assign busy_o = buf0_full_r | buf1_full_r | (done_mask_r != 16'd0) | (state_r != ST_IDLE);
// cap上升沿
always @(posedge clk_i) begin
if (!rst_n_i) begin
cap_pulse_d1 <= 1'b0;
end
else begin
cap_pulse_d1 <= cap_pulse_i;
end
end
// 每通道独立帧头识别 + 64bit缓存
always @(posedge clk_i) begin
if (!rst_n_i) begin
done_mask_r <= 16'd0;
wr_bank_r <= 1'b0;
buf0_full_r <= 1'b0;
buf1_full_r <= 1'b0;
overflow_o <= 1'b0;
for (ch_i = 0; ch_i < 16; ch_i = ch_i + 1) begin
ch_state_r[ch_i] <= CH_FIND;
head_cnt_r[ch_i] <= 5'd0;
bit_cnt_r[ch_i] <= 6'd0;
end
end
else begin
if (aligned_frame_done_o) begin
if (rd_bank_r == 1'b0) begin
buf0_full_r <= 1'b0;
end
else begin
buf1_full_r <= 1'b0;
end
end
if (cap_pos_w) begin
for (ch_i = 0; ch_i < 16; ch_i = ch_i + 1) begin
case (ch_state_r[ch_i])
CH_FIND: begin
if (ch_bit_w[ch_i]) begin
if (head_cnt_r[ch_i] == (HEADER_FF_NUM - 5'd1)) begin
head_cnt_r[ch_i] <= 5'd0;
bit_cnt_r[ch_i] <= 6'd0;
ch_state_r[ch_i] <= CH_DATA;
end
else begin
head_cnt_r[ch_i] <= head_cnt_r[ch_i] + 5'd1;
end
end
else begin
head_cnt_r[ch_i] <= 5'd0;
end
end
CH_DATA: begin
if (wr_bank_r == 1'b0) begin
buf0_r[ch_i][bit_cnt_r[ch_i]] <= ch_bit_w[ch_i];
end
else begin
buf1_r[ch_i][bit_cnt_r[ch_i]] <= ch_bit_w[ch_i];
end
if (bit_cnt_r[ch_i] == 6'd63) begin
bit_cnt_r[ch_i] <= 6'd0;
ch_state_r[ch_i] <= CH_DONE;
done_mask_r[ch_i] <= 1'b1;
end
else begin
bit_cnt_r[ch_i] <= bit_cnt_r[ch_i] + 6'd1;
end
end
CH_DONE: begin
// 等所有通道收齐后统一切bank
end
default: begin
ch_state_r[ch_i] <= CH_FIND;
head_cnt_r[ch_i] <= 5'd0;
bit_cnt_r[ch_i] <= 6'd0;
end
endcase
end
end
if (all_ch_done_w) begin
if ((wr_bank_r == 1'b0) && buf0_full_r) begin
overflow_o <= 1'b1;
end
else if ((wr_bank_r == 1'b1) && buf1_full_r) begin
overflow_o <= 1'b1;
end
else begin
if (wr_bank_r == 1'b0) begin
buf0_full_r <= 1'b1;
end
else begin
buf1_full_r <= 1'b1;
end
wr_bank_r <= ~wr_bank_r;
done_mask_r <= 16'd0;
for (ch_i = 0; ch_i < 16; ch_i = ch_i + 1) begin
ch_state_r[ch_i] <= CH_FIND;
head_cnt_r[ch_i] <= 5'd0;
bit_cnt_r[ch_i] <= 6'd0;
end
end
end
end
end
// 输出状态寄存器
always @(posedge clk_i) begin
if (!rst_n_i) begin
state_r <= ST_IDLE;
end
else begin
state_r <= state_nxt;
end
end
// 输出状态切换
always @(*) begin
state_nxt = state_r;
case (state_r)
ST_IDLE: begin
if (rd_buf_full_w) begin
state_nxt = ST_SEND;
end
end
ST_SEND: begin
if (aligned_ready_i) begin
if (out_pix_idx_r == 6'd63) begin
state_nxt = ST_DONE;
end
else begin
state_nxt = ST_GAP;
end
end
end
ST_GAP: begin
if (gap_cnt_r == 2'd2) begin
state_nxt = ST_SEND;
end
end
ST_DONE: begin
state_nxt = ST_IDLE;
end
default: begin
state_nxt = ST_IDLE;
end
endcase
end
// 输出对齐后的16通道数据
always @(posedge clk_i) begin
if (!rst_n_i) begin
rd_bank_r <= 1'b0;
out_pix_idx_r <= 6'd0;
gap_cnt_r <= 2'd0;
aligned_fmr_o <= 8'd0;
aligned_fml_o <= 8'd0;
aligned_valid_o <= 1'b0;
aligned_frame_done_o <= 1'b0;
end
else begin
aligned_valid_o <= 1'b0;
aligned_frame_done_o <= 1'b0;
case (state_r)
ST_IDLE: begin
out_pix_idx_r <= 6'd0;
gap_cnt_r <= 2'd0;
if (rd_buf_full_w) begin
rd_bank_r <= buf0_full_r ? 1'b0 : 1'b1;
end
end
ST_SEND: begin
if (rd_bank_r == 1'b0) begin
aligned_fmr_o[0] <= buf0_r[0][out_pix_idx_r];
aligned_fmr_o[1] <= buf0_r[1][out_pix_idx_r];
aligned_fmr_o[2] <= buf0_r[2][out_pix_idx_r];
aligned_fmr_o[3] <= buf0_r[3][out_pix_idx_r];
aligned_fmr_o[4] <= buf0_r[4][out_pix_idx_r];
aligned_fmr_o[5] <= buf0_r[5][out_pix_idx_r];
aligned_fmr_o[6] <= buf0_r[6][out_pix_idx_r];
aligned_fmr_o[7] <= buf0_r[7][out_pix_idx_r];
aligned_fml_o[0] <= buf0_r[8][out_pix_idx_r];
aligned_fml_o[1] <= buf0_r[9][out_pix_idx_r];
aligned_fml_o[2] <= buf0_r[10][out_pix_idx_r];
aligned_fml_o[3] <= buf0_r[11][out_pix_idx_r];
aligned_fml_o[4] <= buf0_r[12][out_pix_idx_r];
aligned_fml_o[5] <= buf0_r[13][out_pix_idx_r];
aligned_fml_o[6] <= buf0_r[14][out_pix_idx_r];
aligned_fml_o[7] <= buf0_r[15][out_pix_idx_r];
end
else begin
aligned_fmr_o[0] <= buf1_r[0][out_pix_idx_r];
aligned_fmr_o[1] <= buf1_r[1][out_pix_idx_r];
aligned_fmr_o[2] <= buf1_r[2][out_pix_idx_r];
aligned_fmr_o[3] <= buf1_r[3][out_pix_idx_r];
aligned_fmr_o[4] <= buf1_r[4][out_pix_idx_r];
aligned_fmr_o[5] <= buf1_r[5][out_pix_idx_r];
aligned_fmr_o[6] <= buf1_r[6][out_pix_idx_r];
aligned_fmr_o[7] <= buf1_r[7][out_pix_idx_r];
aligned_fml_o[0] <= buf1_r[8][out_pix_idx_r];
aligned_fml_o[1] <= buf1_r[9][out_pix_idx_r];
aligned_fml_o[2] <= buf1_r[10][out_pix_idx_r];
aligned_fml_o[3] <= buf1_r[11][out_pix_idx_r];
aligned_fml_o[4] <= buf1_r[12][out_pix_idx_r];
aligned_fml_o[5] <= buf1_r[13][out_pix_idx_r];
aligned_fml_o[6] <= buf1_r[14][out_pix_idx_r];
aligned_fml_o[7] <= buf1_r[15][out_pix_idx_r];
end
aligned_valid_o <= 1'b1;
if (aligned_ready_i) begin
if (out_pix_idx_r == 6'd63) begin
aligned_frame_done_o <= 1'b1;
out_pix_idx_r <= 6'd0;
end
else begin
out_pix_idx_r <= out_pix_idx_r + 6'd1;
end
end
end
ST_GAP: begin
if (gap_cnt_r == 2'd2) begin
gap_cnt_r <= 2'd0;
end
else begin
gap_cnt_r <= gap_cnt_r + 2'd1;
end
end
ST_DONE: begin
aligned_fmr_o <= 8'd0;
aligned_fml_o <= 8'd0;
end
default: begin
out_pix_idx_r <= 6'd0;
gap_cnt_r <= 2'd0;
end
endcase
end
end
endmodule

浙公网安备 33010602011771号