所用:vivado 2018.3

一、原理图

二、调试ADV7391的I2C口,上Block design

三、上干货

module I2C_7391
(
     input   wire       en_clk,             //27MHz
 //   input               reset_ok,
     input   wire       rst_n,
     output  wire       mreset,
     output  wire       SCL,
     inout   wire       SDA,
     output  wire   [2:0] cnt_o,
     output  wire       sda_r_out,
  output wire [7:0]  d_r_out,   
  output wire [23:0]  data_out,
     output   wire       led2
);
reg       mreset_r;
reg       reset1=0;
reg [31:0]  Mdelay;
//assign mreset = mreset_r;
always @  (posedge en_clk or negedge rst_n) begin
//always @ (*) begin //27000/400=67.5  300/4=75   300/1 = 300
        if ((rst_n==0)) begin
            Mdelay <= 0;
            mreset_r <= 1'b0;
            reset1 <= 1'b0;
        end else begin
            if (Mdelay <=  (32'd27_000_000*6)) begin  // 延时 ?s
                Mdelay <= Mdelay+1;
                mreset_r <= 1'b0;
                if (Mdelay ==  (32'd27_000_000*2)) reset1 <= 0;
                else reset1 <= 1'b1;
            end else begin
                mreset_r <= 1'b1;
                reset1 <= 1'b1;
            end
        end
end

//****************frequency******************
reg [8:0] cnt_delay;
reg [2:0]cnt;
//always @ (posedge CLK or negedge RST_N) begin 
//   if(!RST_N) begin 
always @ (posedge en_clk/*CLK or negedge RST_N*/) begin 
   //if(!RST_N) 
   if (reset1==0) begin
     cnt_delay <= 9'd0;
    end
    //else if(cnt_delay>=9'd125)  cnt_delay <=9'd0;    //SCL = 400KHZ ; T=10us
    else if(cnt_delay>=9'd240)  cnt_delay <=9'd0;    //270000/125=215   270000/240 `= 120         27000/300=90khz  27000/500 = 54khz
    else cnt_delay <= cnt_delay +1'b1;               
end
always @ (posedge en_clk/*CLK or negedge RST_N*/) begin 
   //if(!RST_N) 
   if (reset1==0) cnt <=3'd0;
      else begin 
      case (cnt_delay)
               9'd60: cnt <= 3'd1;                       //SCL高电平中间采样点 
               9'd120: cnt <= 3'd2;                     //SCL下降沿
               9'd180: cnt <= 3'd3;                     //SCL低电平中间采样点,用于数据的变化
               9'd0:   cnt <= 3'd0;                     //SCL上升沿
             default : cnt <= 3'd5;
             
      endcase
     end              
end
`define  SCL_POS  (cnt==3'd0)
`define  SCL_HIG  (cnt==3'd1)
`define  SCL_NEG  (cnt==3'd2)
`define  SCL_LOW  (cnt==3'd3)

reg scl_r; //定义SCL的时序脉冲,1为高电平,0为低电平

always @ (posedge en_clk/*CLK or negedge RST_N*/) begin 
   //if(!RST_N) 
   if (reset1==0) 
    scl_r <= 1'b0;
    else if(cnt == 3'd2)  scl_r<= 1'b0;       //
    else if(cnt == 3'd0)  scl_r<= 1'b1;       //
end

parameter            IDLE    =     4'd0,
                    Start    =     4'd1,
                    Add1    =    4'd2, 
                    Ack1    =    4'd3,
                    Add2    =    4'd4,
                    Ack2    =   4'd5,
                    Data    =    4'd6,
                    Ack3    =   4'd7,
                    Ass     =    4'd8,
                    End     =   4'd9,
                    Ack4    =   4'd10;

reg [6:0]state;                  //状态寄存器
reg [7:0] db_r;               //IIC上要传送的数据寄存器
reg sda_r;                    //输出数据寄存器
reg sda_link;                 //双向传输控制
reg [3:0]sda_num;              //并转串数据发送计数器寄存器
//reg ack;
reg[23:0]data;
reg[1:0]    state1;
reg[4:0] LUT_INDEX;       
reg[15:0]LUT_DATA;
reg scl_bp_r = 0;
reg [7:0] num;
assign cnt_o = cnt;
assign SCL =  scl_bp_r ? 1 : scl_r;
assign SDA = sda_link ? sda_r:1'bz;
parameter    LUT_SIZE    =    8;//3;

always @  (posedge en_clk ) //CLK /*or negedge RST_N*/)
//if(!RST_N) begin 
   if (reset1==0) begin
       state    <= IDLE;
       sda_r     <= 1'b1;
       sda_link <= 1'b0;
       sda_num  <= 4'd0;
       num      <= 8'd0;
//ack        <= 1'b0;
   end
   else begin
       case(state)
          IDLE:begin
                   if (`SCL_NEG)  begin
                       sda_num <= sda_num + 1'd1;
//                       if (sda_num == 8'd15) begin   //250 = 25  不行 , 15 行
                       if (sda_num == 4'd2) begin   //250 = 25  不行 , 15=10 行
                           state <= Start;
                       end else begin
                           sda_link    <=    1;
                           sda_r        <=    1;
                           state <= IDLE;
                       end
                   end else begin
                         sda_link    <=    1;
                         sda_r        <=    1;
                         state      <= IDLE;
                   end 
                   /*      sda_link    <=    1;
                         sda_r        <=    1;
                         state      <= Start;
                */
            end
            Start:begin
                     if(`SCL_HIG)begin
                                sda_link         <=1'b1;
                                sda_r             <=1'b0;         //SCL在高电平期间将SDA拉低
                                sda_num            <=4'd0;
                                state             <= Ass;
                     end
                     else     state <= Start;
                  end
            Ass:begin  
                     if (LUT_INDEX == 6)
                        data   = {8'h8a,LUT_DATA};
                     else
                        data   = {8'h54,LUT_DATA};
                     db_r                = data[23:16];
                     state                 = Add1;
                     sda_link             = 1'b1;
                     sda_num            = 4'd0;
                 end
            Add1:begin 
                       if(`SCL_LOW) begin 
                           if(sda_num==4'd8)begin    
                              sda_r     <= 1'b1;                  //数据发送完毕后释放SDA总线
                              sda_link <= 1'b0;               //双向输入输出口设为高阻态
                              sda_num     <= 4'd0;
                              state     <= Ack1;
                            end
                            else begin 
                              sda_num     <= sda_num +1'b1;
                              sda_link     <= 1'b1;
                              state         <= Add1;
                              case (sda_num)              //串行数据传送,从高位开始传送
                                     4'd0 : sda_r <= db_r[7];
                                     4'd1 : sda_r <= db_r[6]; 
                                     4'd2 : sda_r <= db_r[5];
                                     4'd3 : sda_r <= db_r[4];
                                     4'd4 : sda_r <= db_r[3];
                                     4'd5 : sda_r <= db_r[2];
                                     4'd6 : sda_r <= db_r[1];
                                     4'd7 : sda_r <= db_r[0];
                                     default : ;
                              endcase                      
                           end
                        end
                        else state <=Add1;
                 end
            Ack1:begin
                    if(`SCL_NEG)begin
                            state <= Add2;
                            db_r     <= data[15:8];
                    end
                    else     state <= Ack1;
                 end
            Add2:begin
                   if(`SCL_LOW) begin 
                          if(sda_num==4'd8)begin    
                                sda_r     <= 1'b1;                  //数据发送完毕后释放SDA总线
                                sda_link <= 1'b0;               //双向输入输出口设为高阻态
                                sda_num     <= 4'd0;
                                state     <= Ack2;
                         end
                         else begin 
                                sda_num     <= sda_num +1'b1;
                                sda_link <= 1'b1;
                                state     <= Add2;
                             case (sda_num)              //串行数据传送,从高位开始传送
                                     4'd0 : sda_r <= db_r[7];
                                     4'd1 : sda_r <= db_r[6]; 
                                     4'd2 : sda_r <= db_r[5];
                                     4'd3 : sda_r <= db_r[4];
                                     4'd4 : sda_r <= db_r[3];
                                     4'd5 : sda_r <= db_r[2];
                                     4'd6 : sda_r <= db_r[1];
                                     4'd7 : sda_r <= db_r[0];
                                     default : ;
                             endcase                      
                           end
                        end
                        else state <=Add2;
                 end
                 
            Ack2:begin
                  if(`SCL_NEG)begin
                         state     <= Data;
                         db_r     <= data[7:0];
                    end
                    else state <= Ack2;
                 end
            Data:begin
                    if(`SCL_LOW) begin 
                         if(sda_num==4'd8)begin    
                             sda_r        <= 1'b1;                  //数据发送完毕后释放SDA总线
                              sda_link    <= 1'b0;               //双向输入输出口设为高阻态
                              sda_num     <= 4'd0;
                              state         <= Ack3;
                             
                         end
                         else begin 
                              sda_num     <= sda_num +1'b1;
                              sda_link     <= 1'b1;
                              state     <= Data;
                             case (sda_num)              //串行数据传送,从高位开始传送
                                     4'd0 : sda_r <= db_r[7];
                                     4'd1 : sda_r <= db_r[6]; 
                                     4'd2 : sda_r <= db_r[5];
                                     4'd3 : sda_r <= db_r[4];
                                     4'd4 : sda_r <= db_r[3];
                                     4'd5 : sda_r <= db_r[2];
                                     4'd6 : sda_r <= db_r[1];
                                     4'd7 : sda_r <= db_r[0];
                                     default : ;
                             endcase                      
                           end
                        end
                    else state <=Data;
                 end
            Ack3:begin
        
                    if(`SCL_NEG)begin
                        if (LUT_INDEX == LUT_SIZE-1 ) begin
                            LUT_INDEX = 0;
                            num = num+8'd1;
                        end
                        else
                            LUT_INDEX = LUT_INDEX +1;
                        if (num > 8'd10)   state  <= End;      //删此则永远反复便于观察
                        else                                   //删此则永远反复便于观察
                        if (LUT_INDEX==6) begin
                                state   <=  Ass;
                               
                        end else  begin
                                state   <=  IDLE;                      
                        end
                    end
                     else begin
                        state <= Ack3;                    
                    end 
               end
            End:begin 
                    if(`SCL_LOW)begin
                        sda_r <= 1'b1; //原来=0
                        sda_link <= 1'b1;
                        scl_bp_r <= 1'b1;
                        state <= End;
                    end
                    else begin 
                        state <= End;
                    end
                end
          default:  state <= IDLE;
        endcase
    end
    
assign d_r_out = db_r;    
assign data_out = data;
assign sda_r_out = sda_r;

/    Config Data LUT      //    
/*
always @(*)                       // 配置ADV7390芯片,输出内部测试图案
begin
    case (LUT_INDEX)
 // 0      : LUT_DATA = 16'h1702 ;   // 软件复位
  0      : LUT_DATA = 16'h001c ;   // 所有DAC使能。PLL使能(16×)
  1      : LUT_DATA = 16'h82cb ;   //
  2      : LUT_DATA = 16'h8440 ;   //
//  3      : LUT_DATA = 16'hFFFF ;   //
//  4      : LUT_DATA = 16'hFFFF ;   //

default    : LUT_DATA = 0;
  endcase
end
*/
always @(*)                        // 配置ADV7390芯片,输出PAL制式的视频流
begin
    case (LUT_INDEX)
//  0      : LUT_DATA = 16'h1702 ;   // 软件复位
  0      : LUT_DATA = 16'h001c ;   // 所有DAC使能。PLL使能(16×)
  1      : LUT_DATA = 16'h001c ;   // 所有DAC使能。PLL使能(16×)
  2      : LUT_DATA = 16'h0100 ;   // 标清输入模式
  3      : LUT_DATA = 16'h8011 ;   // PAL标准。SSAF亮度滤波器使能。1.3 MHz色度滤波器使能
  4      : LUT_DATA = 16'h82c3 ;   // 像素数据有效。CVBS/Y-C(S视频)输出
  5      : LUT_DATA = 16'h8ccb ;   // PAL模式(27 MHz输入时钟)下CVBS和/或S视频(Y-C)输出的副载波频率寄存器:
  6      : LUT_DATA = 16'h092a ;   // 
//  6      : LUT_DATA = 16'h8d8a ;   //
//  7      : LUT_DATA = 16'h8e09 ;   //
//  8      : LUT_DATA = 16'h8f2a ;   //
  7      : LUT_DATA = 16'h001c ;   // 所有DAC使能。PLL使能(16×)
   default    : LUT_DATA = 0;
  endcase
end

reg led2_t;
    assign led2 = led2_t;    
    reg[31:0] timer_cnt2;

always @ (posedge en_clk)  //27000/400=67.5  300/4=75   300/1 = 300
    if (reset1==0) begin 
       //cnt_delay <= 9'd0;
    end
    else begin       
      if(timer_cnt2 >=(32'd13_500_000))  //模拟1S时间     30MHz=30_000_000Hz  
      begin
        // timer_cntx <= timer_cntx+1;
        led2_t<=~led2_t;
        timer_cnt2<=32'd0;
      end
      else
      begin
        //timer_cntx <= timer_cntx;
        led2_t<=led2_t;
        timer_cnt2<=timer_cnt2+32'd1;
      end 
   end

endmodule

看一看波形图:

我原来程序由于副载波频率可能IIC有问题,干脆8c\8d\8e\8f四个同一次传,终于搞定。

四、再来干货
`timescale 1 ns / 1 ps
    module video_axi4 
    (
        input           rst_n,    
        output  [7:0]   en_d,
        output          en_vs,
        output          en_hs,
        input           en_clk,
        output [10:0]   colp,
        output [9:0]    rowp        
     );

reg [10:0] cols = 0; //0---1727
reg [9:0] row = 0;  //0---624

reg [7:0] data;          //8位数据
//                     y      cb     cr
reg [23:0] white = {8'heb, 8'h80, 8'h80};//{8'd235, 8'd128, 8'd128};
reg [23:0] yellow = {8'hd2, 8'h10, 8'h92};//{8'd162, 8'd44, 8'd142};
reg [23:0] cyan = {8'haa, 8'ha6, 8'h10};//{8'd131, 8'd156, 8'd44};
reg [23:0] green = {8'h91, 8'h36, 8'h22};//{8'd112, 8'd72, 8'd58};
reg [23:0] magenta = {8'h6a, 8'hca, 8'hde};//{8'd84, 8'd184, 8'd198};
reg [23:0] red = {8'h51, 8'h5a, 8'hf0};//{8'd65, 8'd100, 8'd212};
reg [23:0] blue = {8'h29, 8'hf0, 8'h6e};//{8'd35, 8'd212, 8'd114};
reg [23:0] black = {8'h10, 8'h80, 8'h80};//{8'd16, 8'd128, 8'd128};

reg [23:0] cur_color;
//产生图像数据,数据 8 个 8 个出
function [7:0] colorValue;
    input [10:0] cols;  //col = 288~1727
    begin
        if(452 > cols)
            cur_color = black;
        else if(652 >cols)
            cur_color = blue;
        else if(812 > cols)
            cur_color = red;
        else if(992 > cols)
            cur_color = magenta;
        else if(1172 > cols)
            cur_color = green;
        else if(1352 > cols)
            cur_color = cyan;
        else if(1532 > cols)
            cur_color = yellow;
        else
            cur_color = white;
        //* Y
        if(cols[0] == 1'b1)   //288 = 120h  
            colorValue = cur_color[23:16];// y
        //* Cr and Cb
        else if(cols[1] == 1'b0)
            colorValue = cur_color[15:8]; //* cb
        else
            colorValue = cur_color[7:0]; //* Cr
    end
endfunction

function [7:0] EAV;
    input [9:0] row;
    begin
        if (row <= 311) begin
            if (row < 22) 
                EAV = 8'hb6; 
            else if (row < 310)
                EAV = 8'h9d;
            else
                EAV = 8'hb6;
        end else begin
           if (row < 335) 
                EAV = 8'hf1; 
            else if (row < 623)
                EAV = 8'hda;
            else
                EAV = 8'hf1;            
        end
    end
endfunction
function [7:0] SAV;
    input [9:0] row;
    begin
        if (row <= 311) begin
            if (row < 22) 
                SAV = 8'hab; 
            else if (row < 310)
                SAV = 8'h80;
            else
                SAV = 8'hab;
        end else begin
           if (row < 335) 
                SAV = 8'hec; 
            else if (row < 623)
                SAV = 8'hc7;
            else
                SAV = 8'hec;            
        end
    end
endfunction
reg hsvs;
 always@(negedge en_clk)  //仿真用
    begin 
         if ((rst_n==0))begin
            cols = 11'd0;
            row = 10'd0;
            data = 8'd0;
            hsvs = 0;
         end else begin
            hsvs = ~hsvs;
//           0  1 2 3     4 <= col <= 283   284 285 286 287   288 <= col <=1727
//0~21行     FF 0 0 B6    0x80和0x10交替    FF  0   0   AB    0x80和0x10交替 
//22~309行   FF 0 0 9d    0x80和0x10交替    FF  0   0   80    视频数据 
//310~311行  FF 0 0 b6    0x80和0x10交替    FF  0   0   ab    0x80和0x10交替 
//312~334行  FF 0 0 f1    0x80和0x10交替    FF  0   0   ec    0x80和0x10交替 
//335~622行  FF 0 0 da    0x80和0x10交替    FF  0   0   c7    视频数据 
//623~624行  FF 0 0 f1    0x80和0x10交替    FF  0   0   ec    0x80和0x10交替 
                 if (cols <= 11'd283) begin
                    if (cols < 11'd3) begin
                        case (cols) 
                            0:data = 8'hff;                        //0
                            1:data = 8'h00;                        //1
                            2:data = 8'h00;                        //2
                        endcase
                    end else begin
                        if (cols==11'd3) begin
                            data = EAV(row);                       //3
                        end else begin
                            data = (cols[0] == 0) ? 8'h80 : 8'h10;  //4~283
                        end
                    end
                 end else begin
                    if (cols < 11'd287) begin
                        case (cols) 
                            284:data = 8'hff;                        //284
                            285:data = 8'h00;                        //285
                            286:data = 8'h00;                        //286
                        endcase
                    end else begin
                        if (cols==11'd287) begin
                            data = SAV(row);                         //287
                        end else begin
                            if ((row >= 22 && row <= 309) || (row >= 335 && row <= 622)) 
                                data = colorValue(cols);                //288~1727
                            else
                                data = (cols[0] == 0) ? 8'h80 : 8'h10;  //288~1727
                        end
                    end
                 end 
                 if (cols < 11'd1727) 
                    cols = cols + 1'b1;
                 else begin 
                    cols = 11'd0; 
                    hsvs = 0;
                    if (row < 10'd624) 
                        row = row + 1'b1;
                    else row = 10'd0;
                 end
         end 
    end    
assign en_d = data;
assign en_vs = hsvs;
assign en_hs = ~hsvs;
assign colp = cols;
assign rowp = row;
     endmodule

写在最后:
我在网上找了很多资料:

很难找ADV7391的Verilog源码,我将此篇贡献于此。

写一个ADV7391的Virelog调试过程相关推荐

  1. dotnet core 应用是如何跑起来的 通过自己写一个 dotnet host 理解运行过程

    在上一篇博客是使用官方提供的 AppHost 跑起来整个 dotnet 程序.本文告诉大家在 dotnet 程序运行到托管代码之前,所需要的 Native 部分的逻辑.包括如何寻找 dotnet 运行 ...

  2. 用.netcore写一个简单redis驱动,调试windows版本的redis

    1. 下载windows版本的redis 2.开发环境vs2017  新建一个 .net core控制台. private static Socket socket = new Socket(Addr ...

  3. linux下Qt编写串口调试助手,如何在linux下用QT写一个简单的串口调试助手

    如何在linux下用QT写一个简单的串口调试助手 QT5串口类 在QT5以前,编写串口一般使用的是qextserialport类,但在QT5之后有了QT自带的串口类SerialPort(串口基础类)和 ...

  4. VB.net写一个简易串口RS485调试助手

    最近在调试带rs485串口通讯的设备,项目上主要是用PLC和串口通讯,因为PLC有集成好的串口块,使用起来比较容易,为了方便测试,就想着用上位机写一个简易的串口通讯程序,用于调试. 在网上查找了一些资 ...

  5. 一个完整的gdb调试过程以及一些常用的命令

    1. 启动调试 <span style="color:#000000"><code>gcc -g test.c // 编译文件,生成可执行程序,并且给文件加 ...

  6. 单片机shell命令_单片机裸机下写一个自己的shell调试器

    result = paramBuffer[i] -'A'+10; } else { //出现范围之外的数据,返回1 return 1; } valueResult += (u32)(result*fa ...

  7. ChatGPT实现用C语言写一个扫雷小游戏

    前几天我们利用 ChatGPT实现用C语言写一个学生成绩管理系统 其过程用时不到30秒,速度惊人 今天又让ChatGPT用C语言写了一个扫雷小游戏,它的回答是:抱歉,我是AI语言模型,无法编写程序. ...

  8. 案例一: 使用IDA PRO+OllyDbg+PEview 追踪windows API 动态链接库函数的调用过程。 首先用文本编辑器写一个C++源程序名为StackFrame.cpp ,代码如下:

    案例一: 使用IDA PRO+OllyDbg+PEview 追踪windows API 动态链接库函数的调用过程. 首先用文本编辑器写一个C++源程序名为StackFrame.cpp ,代码如下: 1 ...

  9. 手把手教你写一个串口调试助手

    硬件攻城狮 2022-05-20 14:05 发表于广东 果果小师弟. 电子信息工程硕士在读,分享单片机.嵌入式linux.物联网等知识,致力于打造最硬核的嵌入式技术公众号. 摘要:前段时间发布了一个 ...

最新文章

  1. 天猫国际618一骑绝尘,占中国跨境进口电商总订单超七成
  2. 锐起无盘服务器安装教程,锐起无盘安装方法 图文教程
  3. AIgorand区块链中VRF随机函数的应用
  4. 强烈推荐 MicroSoft Office OneNote
  5. endpointimpl怎么填参数_App拉新:以老拉新活动怎么做?
  6. 智能手机RAM和ROM的区别以及SD卡的作用
  7. anaconda moviepy_Anaconda、Jupyter Notebook安装与使用
  8. 使用SoapUI生成wsdl文件客户端(二)
  9. iOS混排计算中英文个数,中午算一个字符,英文和符号算半个字符
  10. 关于Initializing Spring root WebApplicationContext解决方法
  11. HTML怎么引入字体包中的字体
  12. jclasslib 查看类信息
  13. 【黄啊码】关于vue的PC端和手机端框架
  14. AtCoder Grand Contest 007题解
  15. 我要用生锈的机关枪击穿现在
  16. oracle 查看用户配额,【Quota】获取及调整用户表空间配额方法
  17. 运维:你们 JAVA 服务怎么又又又又出问题了,内存降不下来
  18. 【Windows】【VS】error C2220: 以下警告被视为错误
  19. 两种批处理方式(操作系统)
  20. C语言利用瑞丽分布产生高斯白噪声

热门文章

  1. Java毕设项目家政服务公司管理信息计算机(附源码+系统+数据库+LW)
  2. 程序员版的“鱿鱼游戏”趣图来了!
  3. 《山东体育科技》是核心期刊吗?
  4. uniapp引入字体
  5. 陕西农民挖地基,竟然挖出2700年前的青铜家谱!专家:这是中国第一盘
  6. android 利用重力感应监听 来电时翻转手机后静音。
  7. gitlab 社区版 多人 review 实现
  8. linux sockaddr in,Linux C中sockaddr和sockaddr_in的区别
  9. QCharts - 5.示例-条形统计图
  10. AI导出图片分辨率增大问题