📄 freedev_bt656.v
字号:
//---------------------------------------------------------------
//模块名称:freedev_bt656
//功能说明:BT656视频采集处理模块
// 1、通过slave port设置模块工作参数和模式
// 2、视频采集部分以输入视频时钟采集数据并缓存到视频FIFO
// 3、avalone master部分读视频FIFO数据,存放到内存
//日 期:20070630
//备 注:
// 1、Avalone总线Slave设备
// 2、Avalon总线Master设备 burst传输
// 3、视频采集
//
//公司:杭州自由电子科技
//电话:0571-85084089
//网址:www.freefpga.com
//邮件:tech@freefpga.com
//----------------------------------------------------------------
module freedev_bt656(
clk,
rst_n,
//从端口
s_irq,
s_chipselect_n,
s_read_n,
s_write_n,
s_address,
s_readdata,
s_writedata,
//主端口
m_waitrequest,
m_address,
m_read,
m_readdata,
m_write,
m_writedata,
m_byteenable,
m_burstcount,
m_readdatavalid,
//视频信号
v_clk,
v_data
);
input clk; // clk
input rst_n; // reset
//slave 接口信号
output s_irq; // interrupt request
input s_chipselect_n; // chip select
input s_read_n; // read signal
input s_write_n; // write signal
input [3:0]s_address; // address
output [31:0]s_readdata; // out data
input [31:0]s_writedata; // in data
//master 接口信号
input m_waitrequest; // 等待
output [31:0]m_address; // master 地址
output m_read; // 读信号
input [31:0]m_readdata; // 读数据
output m_write; // 写信号
output [31:0]m_writedata; // 写数据
output [3:0]m_byteenable; // 字节选择
output [7:0]m_burstcount; // 突发传输数
input m_readdatavalid; // 突发传输读数据有效
//视频信号
input v_clk; // 视频数据时钟
input [7:0]v_data; // 8bit YCbCr视频数据
/////////////////////////////avalone slave部分//////////////////////////////////////
// 寄存器定义
reg [31:0] mode; // 模式寄存器 0x00
reg [31:0] command; // 命令寄存器 0x01
reg [31:0] status; // 状态寄存器 0x02
reg [31:0] irq_mask; // 中断屏蔽寄存器 0x03
reg [31:0] video_buff; // 视频存储地址 0x04
reg [31:0] test_reg1; // 测试调试寄存器 0x05
reg rirq,wirq;
reg [31:0] s_readdata; // out data
// 模块软件复位
wire s_rst = command[0];
wire capture_enable = command[1]; // 数据采集控制位
wire write_enable = command[2]; // 数据存储控制位
// 总线写信号
wire write_req = ~s_chipselect_n & ~s_write_n;
// 总线读信号
wire read_req = ~s_chipselect_n & ~s_read_n;
// 写寄存器
always @(posedge clk or negedge rst_n)
if (!rst_n )
begin
mode <= #1 32'h00000000; //模式寄存器清0
command <= #1 32'h00000000; //命令寄存器清0
irq_mask <= #1 32'hffffffff; //默认屏蔽中断
video_buff <= #1 32'hffff0000; //默认视频存储地址
end
else
begin
if ( write_req )
begin
case ( s_address )
4'b0000 : mode <= #1 s_writedata; // 写模式寄存器
4'b0001 : command <= #1 s_writedata; // 写命令
4'b0010 : status <= #1 s_writedata; // 状态
4'b0011 : irq_mask <= #1 s_writedata; // 写中断屏蔽寄存器
4'b0100 : video_buff <= #1 s_writedata; // 视频存储地址
4'b0101 : test_reg1 <= #1 s_writedata; // 测试调试寄存器
default: ;
endcase
end
end
always @(posedge clk)
begin
if( read_req )
case (s_address)
4'b0000: s_readdata <= #1 mode;
4'b0001: s_readdata <= #1 command;
4'b0010: s_readdata <= #1 status;
4'b0011: s_readdata <= #1 irq_mask;
4'b0100: s_readdata <= #1 video_buff;
4'b0101: s_readdata <= #1 fifo_writedata;
4'b0110: s_readdata <= #1 {{30{1'b0}},wrfull,wrempty};
4'b0111: s_readdata <= #1 {{26{1'b0}},current_state}; // 状态机当前状态;
4'b1000: s_readdata <= #1 {{23{1'b0}},wrusedw};
4'b1001: s_readdata <= #1 {{23{1'b0}},rdusedw};
4'b1010: s_readdata <= #1 count_8010;
4'b1011: s_readdata <= #1 count_ycbcr;
4'b1100: s_readdata <= #1 count_total;
4'b1101: s_readdata <= #1 line_total;
4'b1110: s_readdata <= #1 odd_line;
4'b1111: s_readdata <= #1 even_line;
endcase
end
/////////////////////Avalon Master//////////////////////////////////
// 读视频FIFO数据,每次一行432个DWORD存放到内存 突发传输
reg [31:0]m_address; // master 地址
reg m_read; // 读信号
reg m_write; // 写信号
//reg [31:0]m_writedata; // 写数据
reg [3:0]m_byteenable; // 字节选择
reg [7:0]m_burstcount; // 突发传输次数
reg [5:0] next_state,current_state;
reg [31:0] readdata; // 读数据
reg [31:0] transfer_count; // 传输计数
reg [31:0] remain_count; // 剩余传输
reg [7:0] burstcount; // 突发传输次数
reg [31:0] count; // 一次突发传输内计数
reg [31:0] v_line; // 行计数
wire [31:0] c_line=test_reg1; // 存储行数
parameter [5:0]
IDLE = 6'b000001, // 空闲 0x01
R_START0 = 6'b000010, // 读地址准备0 0x02
R_START1 = 6'b000100, // 等待wait无效 0x04
R_DATA = 6'b001000, // 读数据0 0x08
W_START = 6'b010000, // 写地址准备 0x10
W_DATA = 6'B100000; // 写数据 0x20
// Avalon Master bust memory write control
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
current_state <= #1 IDLE;
m_address <= #1 32'hzzzzzzzz;
m_read <= #1 1'b0;
m_write <= #1 1'b0;
//m_writedata <= #1 32'hxxxxxxxx;
m_byteenable <= #1 4'h0;
m_burstcount <= #1 8'h00;
transfer_count <= #1 32'h00000000;
v_line <= #1 32'd0;
end
else
begin
case(current_state)
IDLE: begin
m_address <= #1 32'hzzzzzzzz;
m_read <= #1 1'b0;
m_write <= #1 1'b0;
m_byteenable <= #1 4'h0;
if( (rdusedw >= 9'd432) && write_enable == 1'b1 )// 一行数据 并且写内存控制位等于1
begin
burstcount <= #1 128; // 突发传输次数128
remain_count <= #1 432 ; // 剩余传输数
current_state <= #1 W_START;
if( v_line < 624)
v_line <= v_line+1;
else
v_line <= 0;
if(v_line == 0)
transfer_count <= #1 32'h00000000;
end
else current_state <= #1 IDLE;
end
W_START: begin
m_address <= #1 video_buff + (transfer_count*4);
m_write <= #1 1'b1;
m_byteenable <= #1 4'hf;
m_burstcount <= #1 burstcount;
count <= #1 32'h00000000;
remain_count <= #1 remain_count - {{24{1'b0}},burstcount};//剩余传输数
current_state <= #1 W_DATA;
end
W_DATA: begin
if ( m_waitrequest == 1'b1 )
begin
current_state <= #1 W_DATA;
end
else begin
count <= count +1;
if(count == (burstcount-1)) // 本次突发写传输完成
begin
m_write <= #1 1'b0;
transfer_count <= #1 transfer_count+ burstcount;
if( remain_count == 32'h00000000)
begin
current_state <= IDLE;
end
else begin
burstcount <= #1 (remain_count < 128) ? {remain_count[6:0]}:128; // 下一次突发传输次数
current_state <= #1 W_START; // 再一次启动读和写
end
end
else
current_state <= #1 W_DATA; // 突发传输未完成,继续
end
end
default: current_state <= #1 IDLE;
endcase
end
/////////////////////////// bt656视频数据参数检测部分 ///////////////////////////////////////////
// 视频参数检测,应用程序通过Avalon slave接口读取相关参数
wire [31:0]count_8010;
wire [31:0]count_ycbcr;
wire [31:0]count_total;
wire [31:0]line_total;
wire [31:0]odd_line;
wire [31:0]even_line;
bt656_detection the_bt656_detection(
.v_clk(v_clk),
.v_data(v_data),
.count_8010(count_8010),
.count_ycbcr(count_ycbcr),
.count_total(count_total),
.line_total(line_total),
.odd_line(odd_line),
.even_line(even_line)
);
/////////////////////////// bt656视频数据采集部分 ///////////////////////////////////////////////
// 视频数据采集,每4字节做一次FIFO存储
reg [7:0]RR1,RR2,RR3;
always @(posedge v_clk)
begin
RR1 <= #1 v_data;
RR2 <= #1 RR1;
RR3 <= #1 RR2;
end
// EAV SAV CODE检测
wire av_flag = (( RR3 == 8'hff) && ( RR2 == 8'h00 ) && ( RR1 == 8'h00)) ? 1 : 0;
// FIFO写数据生成
wire [31:0]dwdata={RR3,RR2,RR1,v_data};
// 奇场数据行开始
wire [1:0]odd_even={fvh[2],v_data[6]};
// SAV and EAV
reg [2:0] fvh;
wire f_flag = v_data[6]; // field flag
wire v_flag = v_data[5]; // blanking flag
wire h_flag = v_data[4]; // h=0 at SAV , h=1 at EAV
// 相关起始标志
reg capture_start; // 数据采集起始
reg capture_stop; // 数据采集终止
reg h_start; // 行起始信号 检测到EAV开始到p_count到1727结束
reg v_start; // 帧起始信号 检测到偶场到奇场切换开始 到 h_start到624行结束
reg [10:0]p_count; // 27M时钟计数 MAX 1728字节(432DWORD)
reg [9:0]h_count; // 行计数 MAX 625行
reg line0_flag; // 测试行0标志
wire [1:0]mod4 = {p_count[1:0]};
// 写FIFO请求
reg wreq;
always @(posedge v_clk)
if(capture_enable == 1'b1) // 采集控制位==1
begin
if( av_flag == 1'b1 && h_flag == 1'b1 ) // 行EAV
begin
fvh <= v_data[6:4];
if ( odd_even == 2'b10 ) // 帧起始行
begin
// 遇到帧开始,数据采集开始
capture_start <= #1 1'b1;
// 行计数清0
h_count <= #1 0;
// 置第0行标志为1
line0_flag <= #1 1'b1;
// 第一个帧起始 capture_start还是0,所以需要此处特定置wreq 将EAV写入队列
if( capture_start == 1'b0)
begin
wreq <= #1 1'b1;
fifo_writedata <= #1 dwdata;
end
end else if(capture_start) // 非帧起始行
begin
//capture_stop <= 1'b1;
// 置第0行标志为0
line0_flag <= 1'b0;
// 行计数增加1
h_count <= h_count + 1;
end
// EAV数据写入队列
if( capture_start == 1'b1)
begin
wreq <= #1 1'b1;
fifo_writedata <= #1 dwdata;
end
p_count <= #1 4; // 重置行内字节计数
end
else
if( capture_start == 1'b1 ) //开始采集
begin
p_count <= p_count + 1;
if( mod4 == 2'b11)
begin
wreq <= #1 1'b1;
fifo_writedata <= #1 dwdata;
end
end
if(wreq == 1'b1) // wreq 只持续1 v_clk
wreq <= #1 1'b0;
end else
begin
capture_start <= #1 1'b0;
capture_stop <= #1 1'b0;
end
//////////////////////////// 视频缓冲FIFO ///////////////////////////////////////////////////////
wire fifo_wrreq = wreq ; //FIFO写请求 受命令控制位capture_enable控制
wire fifo_rdreq = (current_state == W_DATA) & (m_waitrequest == 1'b0); //FIFO 读请求
wire [8:0] rdusedw,wrusedw;
reg[31:0] fifo_writedata;
wire rdempty,rdfull;
wire wrempty,wrfull;
//缓存FIFO
bt656_fifo in_fifo(
.aclr(s_rst), // 异步清除
.rdclk(clk), // 读时钟
.rdreq(fifo_rdreq), // 读请求
.q(m_writedata), // 读数据
.rdfull(rdfull), // 读满标志
.rdempty(rdempty), // 读空标志
.rdusedw(rdusedw), // 读使用计数
.wrclk(v_clk), // 写时钟
.wrreq(fifo_wrreq), // 写请求
.data(fifo_writedata), // 写数据
.wrfull(wrfull), // 写满标志
.wrempty(wrempty), // 写空标志
.wrusedw(wrusedw) // 写使用计数
);
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -