14位相机转为8位数据Verilog代码

1 模拟14位相机时序输出

这是一个模拟相机输出时序的Verilog模块。输入信号为系统时钟信号,系统复位信号。输出信号为像素时钟,14位像素数据,帧有效信号,行有效信号,此时输出的像素在这一帧中的序号。
 输出像素数量、行有效信号间隔(每行最后一个像素后多少个时钟周期开始下一行),帧有效信号间隔(例如每帧结束到下一帧开始的时钟周期数)可通过parameter调节。
系统时钟信号直接输出为像素时钟信号,14位像素数据从0开始依次增加,增加到某个可调的阈值后归零继续增加。

1.1 代码

module camera_output (
    input             sys_clk,      // 系统时钟信号
    input             sys_rst_n,    // 系统复位信号,低电平有效
    output            pixel_clk,    // 像素时钟
    output reg [13:0] pixel_data,   // 14位像素数据
    output reg        frame_valid,  // 帧有效信号
    output reg        line_valid,   // 行有效信号
    output reg [18:0] pixel_num     // 像素序号
);

  // 参数定义
  parameter PIXEL_COLUMNS = 64;  // 每一行的像素数量,列数
  parameter PIXEL_ROWS = 51;  // 每一帧有多少行,行数
  parameter LINE_INTERVAL = 5;  // 行有效信号间隔
  parameter FRAME_INTERVAL = 10;  // 帧有效信号间隔
  parameter PIXEL_THRESHOLD = 16383;  // 像素数据增加到这个值后归零



  reg [18:0] col_counter;  // 列计数器

  // 像素时钟直接输出为系统时钟
  assign pixel_clk = sys_clk;

  // 计算此时输出的像素值所在列
  always @(posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n) begin
      col_counter <= 0;
    end else if (pixel_counter == (PIXEL_COLUMNS + LINE_INTERVAL) * PIXEL_ROWS + FRAME_INTERVAL - 1) begin
      col_counter <= 0;
    end else if (col_counter == PIXEL_COLUMNS + LINE_INTERVAL - 1) begin
      col_counter <= 0;
    end else begin
      col_counter <= col_counter + 1;
    end
  end

  // 生成行有效信号
  always @(posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n) begin
      line_valid <= 0;
    end else if (pixel_counter >= (PIXEL_COLUMNS + LINE_INTERVAL) * PIXEL_ROWS - 1) begin
      line_valid <= 0;
    end else if (col_counter <= PIXEL_COLUMNS - 1) begin
      line_valid <= 1;
    end else begin
      line_valid <= 0;
    end
  end

  reg [18:0] pixel_counter;  // 一帧全部像素计数器
  // 计算此时一帧中输出像素的数量
  always @(posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n) begin
      pixel_counter <= 0;
    end else if (pixel_counter == (PIXEL_COLUMNS + LINE_INTERVAL) * PIXEL_ROWS + FRAME_INTERVAL - 1) begin
      pixel_counter <= 0;
    end else begin
      pixel_counter <= pixel_counter + 1;
    end
  end

  // 生成帧有效信号
  always @(posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n) begin
      frame_valid <= 0;
    end else if (pixel_counter <= (PIXEL_COLUMNS + LINE_INTERVAL) * PIXEL_ROWS - 1) begin
      frame_valid <= 1;
    end else begin
      frame_valid <= 0;
    end
  end

  // 像素数据生成
  always @(posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n) begin
      pixel_data <= 0;
    end else if (pixel_counter > (PIXEL_COLUMNS + LINE_INTERVAL) * PIXEL_ROWS - 1) begin
      pixel_data <= 0;
    end else if (pixel_data == PIXEL_THRESHOLD) begin
      pixel_data <= 0;
    end else if (frame_valid && line_valid) begin
      pixel_data <= pixel_data + 1;
    end else begin
      pixel_data <= pixel_data;
    end
  end

  // 像素序号
  always @(posedge sys_clk or negedge sys_rst_n) begin
    if (!sys_rst_n) begin
      pixel_num <= 0;
    end else if (pixel_counter > (PIXEL_COLUMNS + LINE_INTERVAL) * PIXEL_ROWS - 1) begin
      pixel_num <= 0;
    end else if (frame_valid && line_valid) begin
      pixel_num <= pixel_num + 1;
    end else begin
      pixel_num <= pixel_num;
    end
  end


endmodule

1.2 仿真激励代码

`timescale 1ns / 1ps


module camera_output_tb;


  reg clk;
  reg rest_n;
  wire pixel_clk;
  wire [13:0] pixel_data;
  wire frame_valid;
  wire line_valid;
  wire [18:0] pixel_num;

  // DUT (Device Under Test)
  camera_output DUT (
      .sys_clk(clk),
      .sys_rst_n(rest_n),
      .pixel_clk(pixel_clk),
      .pixel_data(pixel_data),
      .frame_valid(frame_valid),
      .line_valid(line_valid),
      .pixel_num(pixel_num)
  );


  // 时钟生成
  initial begin
    clk = 0;
    forever #10 clk = ~clk;  // 产生50MHz的时钟信号
  end

  // 测试序列
  initial begin
    rest_n = 0;  // 初始复位
    #100;  // 等待100ns以确保时钟稳定
    rest_n = 1;  // 释放复位
  end


endmodule

1.3 测试波形

2 写入一块bram

2.1代码

`timescale 1ns / 1ps


module camera_tobram (
    input             rest_n,
    input             pixel_clk,
    input      [13:0] pixel_data,   // 14位像素数据
    input             frame_valid,  // 帧有效信号
    input             line_valid,   // 行有效信号
    output reg        bram_we,      // 写入BRAM的写使能信号,高电平有效
    output reg [15:0] bram_data,    // 写入BRAM的数据
    output reg [18:0] bram_addr     // 写入BRAM的地址
);

  localparam PIXEL_SIZE = 64 * 51;  //输入像素数量



  reg [23:0] addr_cnt;  //地址计数器

  //计算地址,一个像素代表一个地址
  always @(posedge pixel_clk or negedge rest_n) begin
    if (!rest_n) begin
      addr_cnt <= 0;
    end else begin
      if (frame_valid == 0) begin
        addr_cnt <= 0;
      end else if (addr_cnt == PIXEL_SIZE - 1) begin
        addr_cnt <= 0;
      end else if (frame_valid & line_valid) begin
        addr_cnt <= addr_cnt + 1;
      end else begin
        addr_cnt <= addr_cnt;
      end
    end
  end


  //对地址进行打一拍处理
  always @(posedge pixel_clk or negedge rest_n) begin
    if (!rest_n) begin
      bram_addr <= 0;
    end else begin
      bram_addr <= addr_cnt;
    end
  end



  //设置写使能、输出数据
  always @(posedge pixel_clk or negedge rest_n) begin
    if (!rest_n) begin
      bram_we   <= 0;
      bram_data <= 0;
    end else begin
      if (frame_valid == 0) begin
        bram_we   <= 0;
        bram_data <= 0;
      end else if (bram_addr == PIXEL_SIZE - 1) begin
        bram_we   <= 0;
        bram_data <= 0;
      end else if (frame_valid & line_valid) begin
        bram_we   <= 1;
        bram_data <= pixel_data;
      end else begin
        bram_we   <= 0;
        bram_data <= 0;
      end
    end
  end



endmodule

2.2 测试代码

sim_top.v

`timescale 1ns / 1ps


module sim_top (
    input         clk,
    input         rest_n,
    output        bram_we,    // 写入BRAM的写使能信号,高电平有效
    output [15:0] bram_data,  // 写入BRAM的数据
    output [18:0] bram_addr   // 写入BRAM的地址
);

  wire pixel_clk;
  wire [13:0] pixel_data;
  wire frame_valid;
  wire line_valid;

  camera_output DUT (
      .sys_clk(clk),
      .sys_rst_n(rest_n),
      .pixel_clk(pixel_clk),
      .pixel_data(pixel_data),
      .frame_valid(frame_valid),
      .line_valid(line_valid),
      .pixel_num()
  );


  camera_tobram uut (
      .rest_n(rest_n),
      .pixel_clk(pixel_clk),
      .pixel_data(pixel_data),  // 14位像素数据
      .frame_valid(frame_valid),  // 帧有效信号
      .line_valid(line_valid),  // 行有效信号
      .bram_we(bram_we),  // 写入BRAM的写使能信号,高电平有效
      .bram_data(bram_data),  // 写入BRAM的数据
      .bram_addr(bram_addr)  // 写入BRAM的地址
  );










endmodule

camera_output_tb.v

`timescale 1ns / 1ps


module camera_output_tb;


  reg clk;
  reg rest_n;
  wire bram_we;  // 写入BRAM的写使能信号,高电平有效
  wire [15:0] bram_data;  // 写入BRAM的数据
  wire [18:0] bram_addr;  // 写入BRAM的地址

  // DUT (Device Under Test)
  sim_top uuu (
      .clk(clk),
      .rest_n(rest_n),
      .bram_we(bram_we),  // 写入BRAM的写使能信号,高电平有效
      .bram_data(bram_data),  // 写入BRAM的数据
      .bram_addr(bram_addr)  // 写入BRAM的地址
  );


  // 时钟生成
  initial begin
    clk = 0;
    forever #10 clk = ~clk;  // 产生50MHz的时钟信号
  end

  // 测试序列
  initial begin
    rest_n = 0;  // 初始复位
    #100;  // 等待100ns以确保时钟稳定
    rest_n = 1;  // 释放复位
  end


endmodule

2.3 测试波形

3 缓存一帧,写入两块bram(只有写入部分,无输出部分)

 3.1 代码

`timescale 1ns / 1ps

//帧缓存模块,可以对输入的连续摄像头数据进行一帧的缓存
module image_frame_buffer (
    input reset_n,
    input camera_clk,
    input camera_frame_valid_i,
    input camera_line_valid_i,
    input [13:0] camera_data_i,
    output reg [13:0] camera_data_to_bram,
    output reg [18:0] write_addr,
    output buffer0_write_en,
    output buffer1_write_en
);

  localparam PIXEL_SIZE = 64 * 51;  //输入的每帧像素数量&每个bram深度

  reg buffer0_write_flag, buffer1_write_flag;
  reg  camera_frame_valid_i_d0;
  reg  camera_line_valid_i_d0;
  wire frame_rise_edge;



  //对帧有效信号和行有效信号打一拍
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      camera_frame_valid_i_d0 <= 0;
      camera_line_valid_i_d0  <= 0;
    end else begin
      camera_frame_valid_i_d0 <= camera_frame_valid_i;
      camera_line_valid_i_d0  <= camera_line_valid_i;
    end
  end

  //检测帧有效信号的上升沿
  assign frame_rise_edge = camera_frame_valid_i && !camera_frame_valid_i_d0;

  //每一帧开始换另一个bram写
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      buffer0_write_flag <= 0;
      buffer1_write_flag <= 1;
    end else begin
      if (frame_rise_edge == 1) begin
        buffer0_write_flag <= ~buffer0_write_flag;
        buffer1_write_flag <= ~buffer1_write_flag;
      end else begin
        buffer0_write_flag <= buffer0_write_flag;
        buffer1_write_flag <= buffer1_write_flag;
      end
    end
  end

  //对于每一个bram的写有效信号
  assign buffer0_write_en = buffer0_write_flag && camera_frame_valid_i_d0 && camera_line_valid_i_d0;
  assign buffer1_write_en = buffer1_write_flag && camera_frame_valid_i_d0 && camera_line_valid_i_d0;

  //计算写入地址
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      write_addr <= 0;
    end else begin
      if (camera_frame_valid_i_d0 == 0) begin
        write_addr <= 0;
      end else if (write_addr == PIXEL_SIZE - 1) begin
        write_addr <= 0;
      end else if (camera_line_valid_i_d0 == 0) begin
        write_addr <= write_addr;
      end else begin
        write_addr <= write_addr + 1;
      end
    end
  end



  //写入bram的数据要打一拍,对齐写使能和写地址
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      camera_data_to_bram <= 0;
    end else begin
      camera_data_to_bram <= camera_data_i;
    end
  end


endmodule

3.2 测试代码

 sim_top.v

`timescale 1ns / 1ps


module sim_top (
    input         clk,
    input         rest_n,
    output [13:0] camera_data_to_bram,
    output [18:0] write_addr,
    output        buffer0_write_en,
    output        buffer1_write_en
);

  wire pixel_clk;
  wire [13:0] pixel_data;
  wire frame_valid;
  wire line_valid;

  camera_output DUT (
      .sys_clk(clk),
      .sys_rst_n(rest_n),
      .pixel_clk(pixel_clk),
      .pixel_data(pixel_data),
      .frame_valid(frame_valid),
      .line_valid(line_valid),
      .pixel_num()
  );


  image_frame_buffer u_image_frame_buffer (
      .reset_n(rest_n),
      .camera_clk(pixel_clk),
      .camera_frame_valid_i(frame_valid),
      .camera_line_valid_i(line_valid),
      .camera_data_i(pixel_data),
      .camera_data_to_bram(camera_data_to_bram),
      .write_addr(write_addr),
      .buffer0_write_en(buffer0_write_en),
      .buffer1_write_en(buffer1_write_en)
  );




endmodule

tb_top.v

`timescale 1ns / 1ps


module camera_output_tb;


  reg         clk;
  reg         rest_n;
  wire [13:0] camera_data_to_bram;
  wire [18:0] write_addr;
  wire        buffer0_write_en;
  wire        buffer1_write_en;

  // DUT (Device Under Test)
  sim_top uuu (
      .clk(clk),
      .rest_n(rest_n),
      .camera_data_to_bram(camera_data_to_bram),
      .write_addr(write_addr),
      .buffer0_write_en(buffer0_write_en),
      .buffer1_write_en(buffer1_write_en)
  );


  // 时钟生成
  initial begin
    clk = 0;
    forever #10 clk = ~clk;  // 产生50MHz的时钟信号
  end

  // 测试序列
  initial begin
    rest_n = 0;  // 初始复位
    #100;  // 等待100ns以确保时钟稳定
    rest_n = 1;  // 释放复位
  end


endmodule

3.3 波形图

4 缓存一帧,写入两块bram,输出像素数据和这一帧的最大值最小值

4.1代码

`timescale 1ns / 1ps

//帧缓存模块,可以对输入的连续摄像头数据进行一帧的缓存,缓存完输出数据和这一帧的最大值最小值
module image_frame_buffer (
    input reset_n,
    input camera_clk,
    input camera_frame_valid_i,
    input camera_line_valid_i,
    input [13:0] camera_data_i,
    output camera_frame_valid_o,
    output [13:0] camera_data_o,
    output [13:0] data_max,
    output [13:0] data_min,
    output [18:0] bram_read_addr,
    output bram0_read_flag,
    output bram1_read_flag
);

  localparam PIXEL_SIZE = 64 * 51;  //输入的每帧像素数量&每个bram深度

  reg buffer0_write_flag, buffer1_write_flag;
  reg camera_frame_valid_i_d0;
  reg camera_line_valid_i_d0;
  wire frame_rise_edge;

  reg [13:0] camera_data_to_bram;
  reg [18:0] write_addr;
  wire buffer0_write_en;
  wire buffer1_write_en;


  //对帧有效信号和行有效信号打一拍
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      camera_frame_valid_i_d0 <= 0;
      camera_line_valid_i_d0  <= 0;
    end else begin
      camera_frame_valid_i_d0 <= camera_frame_valid_i;
      camera_line_valid_i_d0  <= camera_line_valid_i;
    end
  end

  //检测帧有效信号的上升沿
  assign frame_rise_edge = camera_frame_valid_i && !camera_frame_valid_i_d0;

  //每一帧开始换另一个bram写
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      buffer0_write_flag <= 0;
      buffer1_write_flag <= 1;
    end else begin
      if (frame_rise_edge == 1) begin
        buffer0_write_flag <= ~buffer0_write_flag;
        buffer1_write_flag <= ~buffer1_write_flag;
      end else begin
        buffer0_write_flag <= buffer0_write_flag;
        buffer1_write_flag <= buffer1_write_flag;
      end
    end
  end

  //对于每一个bram的写有效信号
  assign buffer0_write_en = buffer0_write_flag && camera_frame_valid_i_d0 && camera_line_valid_i_d0;
  assign buffer1_write_en = buffer1_write_flag && camera_frame_valid_i_d0 && camera_line_valid_i_d0;

  //计算写入地址
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      write_addr <= 0;
    end else begin
      if (camera_frame_valid_i_d0 == 0) begin
        write_addr <= 0;
      end else if (write_addr == PIXEL_SIZE - 1) begin
        write_addr <= 0;
      end else if (camera_line_valid_i_d0 == 0) begin
        write_addr <= write_addr;
      end else begin
        write_addr <= write_addr + 1;
      end
    end
  end



  //写入bram的数据要打一拍,对齐写使能和写地址
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      camera_data_to_bram <= 0;
    end else begin
      camera_data_to_bram <= camera_data_i;
    end
  end



  //两块bram对一帧进行缓存再输出
  image_buffe_0 bram0 (
      .clka(camera_clk),  // input wire clka
      .wea(buffer0_write_en),  // input wire [0 : 0] wea
      .addra(write_addr),  // input wire [11 : 0] addra
      .dina(camera_data_to_bram),  // input wire [13 : 0] dina
      .clkb(camera_clk),  // input wire clkb
      .addrb(read_addr),  // input wire [11 : 0] addrb
      .doutb(buffer0_read_data)  // output wire [13 : 0] doutb
  );
  image_buffe_1 bram1 (
      .clka(camera_clk),  // input wire clka
      .wea(buffer1_write_en),  // input wire [0 : 0] wea
      .addra(write_addr),  // input wire [11 : 0] addra
      .dina(camera_data_to_bram),  // input wire [13 : 0] dina
      .clkb(camera_clk),  // input wire clkb
      .addrb(read_addr),  // input wire [11 : 0] addrb
      .doutb(buffer1_read_data)  // output wire [13 : 0] doutb
  );




  reg [18:0] read_addr;
  reg buffer0_read_flag, buffer1_read_flag;
  wire [13:0] buffer0_read_data;
  wire [13:0] buffer1_read_data;
  reg frame_valid_o;


  //设置对每块bram的读标志,读标志和读地址对齐,比读出的数据和帧有效信号早一拍
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      buffer0_read_flag <= 0;
      buffer1_read_flag <= 0;
    end else begin
      if (read_addr == PIXEL_SIZE) begin
        buffer0_read_flag <= 0;
        buffer1_read_flag <= 0;
      end else if (write_addr == PIXEL_SIZE - 1 && buffer0_write_flag == 1) begin
        buffer0_read_flag <= 1;
        buffer1_read_flag <= 0;
      end else if (write_addr == PIXEL_SIZE - 1 && buffer1_write_flag == 1) begin
        buffer0_read_flag <= 0;
        buffer1_read_flag <= 1;
      end else begin
        buffer0_read_flag <= buffer0_read_flag;
        buffer1_read_flag <= buffer1_read_flag;
      end
    end
  end

  //计算读地址,因为bram读出数据要在地址延后一拍才出,所以要把读地址+1,让数据全部从bram出来再清零
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      read_addr <= 0;
    end else begin
      if (buffer0_read_flag == 0 && buffer1_read_flag == 0) begin
        read_addr <= 0;
      end else if (read_addr == PIXEL_SIZE) begin
        read_addr <= 0;
      end else begin
        read_addr <= read_addr + 1;
      end
    end
  end


  //设置帧有效标志
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      frame_valid_o <= 0;
    end else begin
      if (buffer0_read_flag == 0 && buffer1_read_flag == 0) begin
        frame_valid_o <= 0;
      end else if (read_addr == PIXEL_SIZE) begin
        frame_valid_o <= 0;
      end else begin
        frame_valid_o <= 1;
      end
    end
  end

  //输出帧有效标志
  assign camera_frame_valid_o = frame_valid_o;


  //设置两个bram的输出标志
  wire bram0_out_flag, bram1_out_flag;
  assign bram0_out_flag = (buffer0_read_flag == 1) && (frame_valid_o == 1);
  assign bram1_out_flag = (buffer1_read_flag == 1) && (frame_valid_o == 1);

  //输出读到的数据
  assign camera_data_o = bram0_out_flag ? buffer0_read_data : (bram1_out_flag ? buffer1_read_data : 0);


  reg [13:0] bram0_max, bram0_min;
  reg [13:0] bram1_max, bram1_min;

  reg [13:0] bram0_buffer_max, bram0_buffer_min;
  reg [13:0] bram1_buffer_max, bram1_buffer_min;

  //计算此时输入的图像数据的最大值最小值
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      bram0_max <= 0;
      bram0_min <= 16383;
    end else begin
      if (buffer0_write_flag && camera_frame_valid_i_d0 == 0) begin
        bram0_max <= 0;
        bram0_min <= 16383;
      end else begin
        bram0_max <= (camera_data_to_bram > bram0_max) ? camera_data_to_bram : bram0_max;
        bram0_min <= (camera_data_to_bram < bram0_min) ? camera_data_to_bram : bram0_min;
      end
    end
  end

  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      bram1_max <= 0;
      bram1_min <= 16383;
    end else begin
      if (buffer1_write_flag && camera_frame_valid_i_d0 == 0) begin
        bram1_max <= 0;
        bram1_min <= 16383;
      end else begin
        bram1_max <= (camera_data_to_bram > bram1_max) ? camera_data_to_bram : bram1_max;
        bram1_min <= (camera_data_to_bram < bram1_min) ? camera_data_to_bram : bram1_min;
      end
    end
  end

  //缓存最大值最小值
  always @(posedge camera_clk or negedge reset_n) begin
    if (!reset_n) begin
      bram0_buffer_max <= 0;
      bram0_buffer_min <= 0;
      bram1_buffer_max <= 0;
      bram1_buffer_min <= 0;
    end else begin
      if (write_addr == PIXEL_SIZE - 1) begin
        bram0_buffer_max <= bram0_max;
        bram0_buffer_min <= bram0_min;
        bram1_buffer_max <= bram1_max;
        bram1_buffer_min <= bram1_min;
      end else begin
        bram0_buffer_max <= bram0_buffer_max;
        bram0_buffer_min <= bram0_buffer_min;
        bram1_buffer_max <= bram1_buffer_max;
        bram1_buffer_min <= bram1_buffer_min;
      end
    end
  end


  //输出最大值和最小值
  assign data_max = bram0_out_flag ? bram0_buffer_max : bram1_out_flag ? bram1_buffer_max : 16383;
  assign data_min = bram0_out_flag ? bram0_buffer_min : bram1_out_flag ? bram1_buffer_min : 0;




  assign bram_read_addr = read_addr;
  assign bram0_read_flag = buffer0_read_flag;
  assign bram1_read_flag = buffer1_read_flag;



endmodule

4.2 测试文件

`timescale 1ns / 1ps


module sim_top (
    input         clk,
    input         rest_n,
    output        camera_frame_valid_o,
    output [13:0] camera_data_o,
    output [13:0] data_max,
    output [13:0] data_min,
    output [18:0] bram_read_addr,
    output        bram0_read_flag,
    output        bram1_read_flag
);

  wire pixel_clk;
  wire [13:0] pixel_data;
  wire frame_valid;
  wire line_valid;

  camera_output DUT (
      .sys_clk(clk),
      .sys_rst_n(rest_n),
      .pixel_clk(pixel_clk),
      .pixel_data(pixel_data),
      .frame_valid(frame_valid),
      .line_valid(line_valid),
      .pixel_num()
  );


  image_frame_buffer u_image_frame_buffer (
      .reset_n(rest_n),
      .camera_clk(pixel_clk),
      .camera_frame_valid_i(frame_valid),
      .camera_line_valid_i(line_valid),
      .camera_data_i(pixel_data),
      .camera_frame_valid_o(camera_frame_valid_o),
      .camera_data_o(camera_data_o),
      .data_max(data_max),
      .data_min(data_min),
      .bram_read_addr(bram_read_addr),
      .bram0_read_flag(bram0_read_flag),
      .bram1_read_flag(bram1_read_flag)
  );




endmodule
`timescale 1ns / 1ps


module camera_output_tb;


  reg         clk;
  reg         rest_n;
  wire        camera_frame_valid_o;
  wire [13:0] camera_data_o;
  wire [13:0] data_max;
  wire [13:0] data_min;
  wire [18:0] bram_read_addr;
  wire        bram0_read_flag;
  wire        bram1_read_flag;

  // DUT (Device Under Test)
  sim_top uuu (
      .clk(clk),
      .rest_n(rest_n),
      .camera_frame_valid_o(camera_frame_valid_o),
      .camera_data_o(camera_data_o),
      .data_max(data_max),
      .data_min(data_min),
      .bram_read_addr(bram_read_addr),
      .bram0_read_flag(bram0_read_flag),
      .bram1_read_flag(bram1_read_flag)
  );


  // 时钟生成
  initial begin
    clk = 0;
    forever #10 clk = ~clk;  // 产生50MHz的时钟信号
  end

  // 测试序列
  initial begin
    rest_n = 0;  // 初始复位
    #100;  // 等待100ns以确保时钟稳定
    rest_n = 1;  // 释放复位
  end


endmodule

 

4.3 波形图 

 

 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值