微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 双口RAM——视频源截取

双口RAM——视频源截取

时间:10-02 整理:3721RD 点击:

  1. `timescale 1ns / 1ps
  2. //////////////////////////////////////////////////////////////////////////////////
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date:    09:17:24 07/31/2016
  7. // Design Name:    wuzhicheng
  8. // Module Name:    datacut
  9. // Project Name:
  10. // Target Devices:
  11. // Tool versions:
  12. // Description:   
  13. //
  14. // Dependencies: 从视频源中截取128X160像素点,假设就按从起始点截取。
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //////////////////////////////////////////////////////////////////////////////////
  21. module data_cut(
  22.        wrclk,  //写时钟 65M,
  23.                  rdclk,  //读时钟 10M,
  24.                  rst_n,  //低电平复位,同步复位,
  25.                  vsync,  //场同步信号,高电平有效,
  26.                  hsync,  //行同步信号,高电平有效,
  27.                  cmos_de, //使能信号,高电平有效,
  28.                  data_in, //输入数据,解码后24位RGB数据,
  29.                  depram_en,//输出使能,输出数据时置高,
  30.                  data_out,  //输出数据,缓存后的24位RGB数据,
  31.                  y_cnt,    //行计数器,M = 126
  32.                  wraddr,  //用于测试观察,
  33.                  rdaddr   //用于测试观察,
  34.     );
  35. //input
  36. input  wrclk;
  37. input  rdclk;
  38. input  rst_n;
  39. input  vsync;
  40. input  hsync;
  41. input  cmos_de;
  42. input  [23:0] data_in;
  43. //output
  44. output depram_en;
  45. output [23:0] data_out;
  46. output [6:0] y_cnt;
  47. output [7:0] wraddr;
  48. output [7:0] rdaddr;

  49. wire depram_en  ;
  50. wire [23:0] data_out ;
  51. wire [6:0] y_cnt;

  52. wire en_wr;
  53. wire en_rd;
  54. wire [7:0] wraddr;
  55. wire [7:0] rdaddr;

  56. ram_double ip_ram1 (
  57.   .clka(wrclk), // input clka
  58.   //.ena(cmos_de), // input ena   //选择了写使能,就把端口使能设置为一直有效,不知是否可以?
  59.   .wea(en_wr), // input [0 : 0] wea
  60.   .addra(wraddr), // input [7 : 0] addra
  61.   .dina(data_in), // input [23 : 0] dina
  62.   .clkb(rdclk), // input clkb
  63.   //.enb(en_rd), // input enb  //不知读使能如何在IP核中设置,把端口B一直设置为有效,
  64.   .addrb(rdaddr), // input [7 : 0] addrb
  65.   .doutb(data_out) // output [23 : 0] doutb
  66. );
  67. ram_wd ram_wd1 (    //该模块用于产生读写地址,和读写使能。
  68.     .wrclk(wrclk),
  69.     .rdclk(rdclk),
  70.     .rst_n(rst_n),
  71.     .vsync(vsync),
  72.     .hsync(hsync),
  73.     .cmos_de(cmos_de),
  74.     .en_wr(en_wr),
  75.     .en_rd(en_rd),
  76.     .wraddr(wraddr),
  77.     .rdaddr(rdaddr),
  78.     .y_cnt(y_cnt)
  79.     );

  80. assign depram_en = en_rd;
  81. endmodule

复制代码


读写地址产生及使能信号产生模块
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    09:17:24 07/31/2016
// Design Name:    wuzhicheng
// Module Name:    datacut
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies: 截取128X160像素点视频;
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module ram_wd(
       wrclk,  //写时钟 65M,
rdclk,  //读时钟 10M,
rst_n,  //低电平有效,
vsync,  //场同步信号,高电平有效,
hsync,  //行同步信号,高电平有效,
cmos_de, //使能信号,高电平有效,
en_wr,
en_rd,
wraddr,
rdaddr,
y_cnt
      );
//input
input  wrclk;
input  rdclk;
input  rst_n;
input  vsync;
input  hsync;
input  cmos_de;
//output
output [7:0] wraddr;
output [7:0] rdaddr;
output en_wr;
output en_rd;
output [6:0] y_cnt;
wire [7:0] wraddr;
wire [7:0] rdaddr;
reg  en_wr = 0;
reg  en_rd = 0;
reg  [6:0] y_cnt = 0; //行计数器,M=128
//---------写状态-------------
reg  [4:0]  cstate,nstate;
parameter      
                 IDLE = 5'b00000, //复位;
NEW_FRAME = 5'b00001, //有效数据开始进入;
     DATA = 5'b00010, //按行开始写人数据;
  WAIT_NEWHC = 5'b00100, //读到某行的160列,通过cmos_de判定,0-后面数据不要了;
WAIT_NEWH = 5'b01000, //等待下一行数据;判定M=128,后面数据舍弃;
  
     WAIT_VC = 5'b10000; //等待下一个场信号,等待下一帧数据;
  
//-------产生行同步信号上升沿--------
reg  [1:0] hsync_reg;
wire       hsync_up;  
always @ (posedge wrclk)
  if(!rst_n)
hsync_reg <= 0;
  else   
    hsync_reg <={hsync_reg[0],hsync};
assign hsync_up = (hsync_reg[1]&&(~hsync_reg[0]));
//------写状态第1段-------
  
always @ (posedge wrclk)
   if(!rst_n)
  cstate <= IDLE;
else
  cstate <= nstate;
//------写状态第2段------
always @ (*) begin
  case (cstate)
   IDLE: begin
  if(vsync)  nstate = NEW_FRAME;
  else       nstate = IDLE;
   end

NEW_FRAME: begin
  if(cmos_de) nstate = DATA;
  else        nstate = NEW_FRAME;
end
   DATA: begin
  if(wraddr_cnt == 160)
    nstate = WAIT_NEWHC;
  else
       nstate = DATA;
  
end

WAIT_NEWHC: begin
  if(!cmos_de)
     nstate = WAIT_NEWH;
  else
     nstate = WAIT_NEWHC;
end
   WAIT_NEWH: begin
  if(y_cnt == 128)
    nstate = WAIT_VC;
  else if(cmos_de == 1)
    nstate = DATA;
    else
    nstate = WAIT_NEWH;
end

WAIT_VC: begin
  if(!vsync)
    nstate = NEW_FRAME;
  else
    nstate = WAIT_VC;
end
default :nstate = IDLE;
  endcase
end
//------写状态第三段------
reg  [7:0] wraddr_cnt = 0;//写地址计数器,max=160
always @ (posedge wrclk) begin
  if(!rst_n) begin
wraddr_cnt <= 0;
y_cnt <= 0;
end
  else case(cstate)
  DATA: begin
    if(wraddr_cnt >= 160) begin
en_wr <= 0;
end
    else if (hsync) begin   
      wraddr_cnt <= wraddr_cnt + 1'b1;
      en_wr <= 1;
    end
  end
  WAIT_NEWH: begin
   wraddr_cnt <= 0;
   if(y_cnt == 128)
  y_cnt <= 0;
    else if(hsync_up)
  y_cnt <= y_cnt + 1'b1;
  end
  endcase
end
//-------读数据部分---------
reg  [7:0] rdaddr_cnt = 0; //读地址计数器,max=160
always @(posedge rdclk) begin
   if(!cmos_de) begin
  rdaddr_cnt <=0;
  en_rd <= 0;
end
else
if(vsync == 1) begin
  if(rdaddr_cnt >= 160) begin
  en_rd <= 0;
  end
  else
    if(wraddr_cnt >= 3) begin
   rdaddr_cnt <= rdaddr_cnt + 1'b1;
   en_rd <= 1;
       end
    end
end
assign wraddr = wraddr_cnt;
assign rdaddr = rdaddr_cnt;
endmodule

测试文件:
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:   14:48:03 08/16/2016
// Design Name:   data_cut
// Module Name:   F:/FPGA/projet/test/cmos_cut/data_cut_tb.v
// Project Name:  cmos_cut
// Target Device:  
// Tool versions:  
// Description:
//
// Verilog Test Fixture created by ISE for module: data_cut
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
module data_cut_tb;

// Inputs
reg wrclk;
reg rdclk;
reg rst_n;
reg vsync;
reg hsync;
reg cmos_de;
reg [23:0] data_in;

// Outputs
wire depram_en;
wire [23:0] data_out;
wire [6:0] y_cnt;
wire  [7:0] wraddr;
   wire  [7:0] rdaddr;
localparam  T = 15;//写时钟为65Mhz,读时钟为10Mhz,暂近似处理;
data_cut uut (
.wrclk(wrclk),
.rdclk(rdclk),
.rst_n(rst_n),
.vsync(vsync),
.hsync(hsync),
.cmos_de(cmos_de),
.data_in(data_in),
.depram_en(depram_en),
.data_out(data_out),
.y_cnt(y_cnt),
.wraddr(wraddr),
.rdaddr(rdaddr)
);
  always  begin
   wrclk = 0;
#(T/2);
wrclk = 1;
#(T/2);
  end
  always  begin
   rdclk = 0;
#(13/4*T);
rdclk = 1;
#(13/4*T);
  end
  initial begin
   rst_n = 0;
#(T);
rst_n = 1;
  end
  always begin
   cmos_de = 0;
#(320*T);
cmos_de = 1;
#(1024*T);
  end
  initial begin  //在场信号有效的情况下处理;暂只考虑一场数据;
   vsync = 0;
#(1*T);
vsync = 1;
  end
  always begin  //一行像素点为1024,考虑到行消隐时间,所以把行周期定为1024x1.05=1344
   hsync = 0;
#(320*T);
hsync = 1;
#(1024*T);
  end
  always @(posedge wrclk) begin
    if(!rst_n)begin
   data_in <=8'd0;
    end

else begin
      if( data_in < 8'd255 )
        data_in <= data_in + 1'b1;
      else
        data_in <= 0;
    end
end
endmodule



为什么没有输出数据,实在是找不出原因,有感兴趣可以一块看看,我把工程发给你,

我也正在做这个,用来进行主从高速数据交换。有兴趣一起研究。



   好啊,加个好友,这是我们老师的项目,目前就我一个人在做,很乐意有人可以一起讨论学习。

请问小编使用哪一款芯片?



   spartan_6 xc6slx45tm,我们有配套的硬件,只是技术是从国外买来的,只有生成的代码,所以我们要自己学习编写代码。方面以后产品升级。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top