【FPGA】双线性差值实现图像缩放,使用modelsim和matlab仿真验真

双线性差值实现图像缩放,使用modelsim和matlab仿真验真

  • 一、概述
  • 二、源代码
  • 三、modelsim仿真程序
  • 四、matlab验证

一、概述

双线性插值,又称为双线性内插。在数学上,双线性插值是有两个变量的插值函数的线性插值扩展,其核心思想是在两个方向分别进行一次线性插值。
双线性插值作为数值分析中的一种插值算法,广泛应用在信号处理,数字图像和视频处理等方面。
网上理论知识一大把,反正不喜欢看费脑。
这里简单说就是附近四个点求出中间点主要分享代码

【FPGA】双线性差值实现图像缩放,使用modelsim和matlab仿真验真_第1张图片

二、源代码

整个代码中的除法器是使用易灵思平台,如是其它平台要将代替掉。

// An highlighted block
//wiret the code go go Interest trumps all ^_^
//设计放大外面使用两个ram
//缩小使用4个ram
//先乘再除
`define IP_UUID _24f688124f6f47f2a9a7e78597ca4ca8
`define IP_NAME_CONCAT(a,b) a``b
`define IP_MODULE_NAME(name) `IP_NAME_CONCAT(name,`IP_UUID)
module zoom #(
    parameter ORG_WIDTH             = 640                                   ,        //放大前数据宽
    parameter ORG_HEIGHT            = 512                                   ,        //放大前数据高
    parameter TAR_WIDTH             = 2560                                  ,        //放大后目标数据宽
    parameter TAR_HEIGHT            = 2048                                  ,        //放大后目标数据高
    parameter ORG_WIDTH_W           = 10                                    ,        //放大前数据宽         org的位宽一致
    parameter ORG_HEIGHT_H          = 10                                    ,        //放大前数据高
    parameter TAR_WIDTH_W           = 12                                    ,        //放大后目标数据宽      tar的位宽一致
    parameter TAR_HEIGHT_H          = 12                                    ,        //放大后目标数据高
    parameter RAM_ADDR_START1       = 0                                     ,      
    parameter RAM_ADDR_START2       = 640                                   ,    
    parameter RAM_ADDR_START3       = 1280                                  ,   
    parameter RAM_ADDR_WIDTH        = 12                                    ,
    //---------------------Non-user-definable parameters----------------------------
    parameter WMULT                 = ORG_WIDTH_W + TAR_WIDTH_W             ,
    parameter HMULT                 = ORG_HEIGHT_H + TAR_HEIGHT_H           ,
    parameter WZOOM                 = ORG_WIDTH_W + 10                      ,
    parameter HZOOM                 = ORG_HEIGHT_H +10                      ,
    parameter NX0                   = WZOOM+4                               ,
    parameter NY0                   = HZOOM+4                               ,  
    parameter NX1                   = NX0 -10                               ,
    parameter NY1                   = NY0 -10                               ,  
    parameter DLY                   = WMULT                               ,
    parameter DLY1                  = WMULT+3                               ,    
    parameter NZOOM                 = 11'd1024                              ,
    parameter nZoomFPNZOOMFPN       = 8'd16
)
(
    input                                   i_clk                       ,
    input                                   i_rst_n                     ,
    input                                   i_zoom_ctrl                 ,               //1:大 0:小        //放大外置RAM只需要两个RAM
    input                                   i_ram_sel                   ,
    input                                   i_hsync                     ,
    input                                   i_hsync_pre                 ,
    input                                   i_vsync                     ,
    input                                   i_fsync                     ,
    input           [7:0]                   i_data11                    ,                   
    input           [7:0]                   i_data12                    ,               
    input           [7:0]                   i_data21                    ,
    input           [7:0]                   i_data22                    ,   
    output reg      [RAM_ADDR_WIDTH - 1:0]  o_addr1                     ,
    output reg      [RAM_ADDR_WIDTH - 1:0]  o_addr2                     ,
    output reg      [RAM_ADDR_WIDTH - 1:0]  o_addr3                     ,
    output reg      [RAM_ADDR_WIDTH - 1:0]  o_addr4                     ,
    output          [7:0]                   o_data                      ,
    output reg                              o_hsync                     ,
    output reg                              o_hsync_pre                 ,
    output reg                              o_vsync                     ,
    output reg                              o_fsync                     ,
    output          [ORG_HEIGHT_H - 1:0]    o_vcnt                      ,
    output                                  o_updata_ram

);

reg                                                         flag                            ;
reg         [3:0]                                           cnt                             ;
reg         [DLY1-1:0]                                      hsync_dly                       ; 
reg         [DLY1-1:0]                                      hsync_pre_dly                   ; 
reg         [DLY1-1:0]                                      vsync_dly                       ; 
reg         [DLY1-1:0]                                      fsync_dly                       ; 
reg                                                         hsync                           ;
reg                                                         hsync_pre                       ;
reg                                                         vsync                           ;
reg                                                         fsync                           ;

reg         [TAR_WIDTH_W - 1:0]                             hcnt_tar                        ;
wire                                                        add_hcnt_tar                    ;
wire                                                        end_hcnt_tar                    ;

reg         [TAR_HEIGHT_H -1:0]                             vcnt_tar                        ;
wire                                                        add_vcnt_tar                    ;
wire                                                        end_vcnt_tar                    ;

reg         [TAR_HEIGHT_H -1:0]                             vcnt_pre                        ;
wire                                                        add_vcnt_pre                    ;
wire                                                        end_vcnt_pre                    ;

wire        [WMULT -1:0]                                    w_mult                          ;
wire        [WMULT -1:0]                                    w_div_q                         ;
wire        [TAR_WIDTH_W-1:0]                               w_div_r                         ;
wire        [HMULT -1:0]                                    h_mult                          ;
wire        [HMULT -1:0]                                    h_div_q                         ;
wire        [TAR_HEIGHT_H-1:0]                              h_div_r                         ;   

wire        [WZOOM-1:0]                                     zoom_w                          ;
wire        [HZOOM-1:0]                                     zoom_h                          ;

wire        [WZOOM-1:0]                                     rsz_multiple_w                  ;
wire        [HZOOM-1:0]                                     rsz_multiple_h                  ;

reg         [NX0-1:0]                                       n_x0                            ;
reg         [NY0-1:0]                                       n_y0                            ;
reg         [NX0-1:0]                                       n_wx0                           ;
reg         [NY0-1:0]                                       n_wy0                           ;
reg         [NX1-1:0]                                       n_wx1                           ;
reg         [NY1-1:0]                                       n_wy1                           ;
wire        [7:0]                                           n_wx2                           ;    
wire        [7:0]                                           n_wy2                           ;   

reg         [(DLY*8)-1:0]                                   n_wx1_dly                       ;         
reg         [(DLY*8)-1:0]                                   n_wy1_dly                       ;         
reg         [(DLY*8)-1:0]                                   n_wx2_dly                       ;         
reg         [(DLY*8)-1:0]                                   n_wy2_dly                       ;     

reg         [15:0]                                          data_buff1                      ;
reg         [15:0]                                          data_buff2                      ;
reg         [15:0]                                          data_buff                       ;

reg         [7:0]                                           data11_pre                      ; 
reg         [7:0]                                           data21_pre                      ; 
reg         [7:0]                                           n_wx1_pre,n_wx1_pre1            ;         
reg         [7:0]                                           n_wy1_pre,n_wy1_pre1            ;
reg         [7:0]                                           n_wx2_pre,n_wx2_pre1            ;
reg         [7:0]                                           n_wy2_pre,n_wy2_pre1            ; 
reg         [RAM_ADDR_WIDTH-1:0]                            addr_buf                        ;    
reg                                                         save_data                       ;    




wire          [30:0]   q =  ORG_WIDTH        ;
wire          [30:0]   w =  ORG_HEIGHT       ;
wire          [30:0]   e =  TAR_WIDTH        ;
wire          [30:0]   r =  TAR_HEIGHT       ;
wire          [30:0]   t =  ORG_WIDTH_W      ;
wire          [30:0]   y =  ORG_HEIGHT_H     ;
wire          [30:0]   u =  TAR_WIDTH_W      ;
wire          [30:0]   i =  TAR_HEIGHT_H     ;
wire          [30:0]   o =  RAM_ADDR_START1  ;
wire          [30:0]   p = RAM_ADDR_START2   ;
wire          [30:0]   a =  RAM_ADDR_START3  ;
wire          [30:0]   s =  RAM_ADDR_WIDTH   ;

wire          [30:0]   f =  NZOOM            ;
wire          [30:0]   g =  nZoomFPNZOOMFPN  ;

wire          [30:0]   q1 =WMULT ;
wire          [30:0]   q2 =HMULT ;


//打拍 跨时钟域

always @(posedge i_clk or negedge i_rst_n)begin 
    if(!i_rst_n)begin
        data11_pre <= 8'd0;
        data21_pre <= 8'd0;
        n_wx2_pre  <= 8'd0;
        n_wy2_pre  <= 8'd0;
        n_wx1_pre  <= 8'd0;
        n_wy1_pre  <= 8'd0;
        n_wx1_pre1 <= 8'd0;
        n_wy1_pre1 <= 8'd0;
        n_wx2_pre1 <= 8'd0;
        n_wy2_pre1 <= 8'd0;
    end 
    else if(i_zoom_ctrl == 1'b1)begin 
        if(save_data)begin          //WMULT+3
        data11_pre <= i_data11;
        data21_pre <= i_data21;
        end
        else begin
       data11_pre <= data11_pre;
       data21_pre <= data21_pre;    
        end
        n_wx2_pre  <= n_wx2_dly[(8*DLY)-1:(8*DLY)-8];
        n_wy2_pre  <= n_wy2_dly[(8*DLY)-1:(8*DLY)-8];
        n_wx1_pre  <= n_wx1_dly[(8*DLY)-1:(8*DLY)-8];
        n_wy1_pre  <= n_wy1_dly[(8*DLY)-1:(8*DLY)-8];
        n_wx1_pre1 <= n_wx1_pre;
        n_wy1_pre1 <= n_wy1_pre;
        n_wx2_pre1 <= n_wx2_pre;
        n_wy2_pre1 <= n_wy2_pre;
    end 
    else begin 
       data11_pre <= data11_pre;
       data21_pre <= data21_pre;
       n_wx2_pre  <= n_wx2_dly[(8*DLY)-1:(8*DLY)-8];
       n_wy2_pre  <= n_wy2_dly[(8*DLY)-1:(8*DLY)-8];
       n_wx1_pre  <= n_wx1_dly[(8*DLY)-1:(8*DLY)-8];
       n_wy1_pre  <= n_wy1_dly[(8*DLY)-1:(8*DLY)-8];
       n_wx1_pre1 <= n_wx1_pre;
       n_wy1_pre1 <= n_wy1_pre;
       n_wx2_pre1 <= n_wx2_pre;
       n_wy2_pre1 <= n_wy2_pre;
    end 
end

always @(posedge i_clk or negedge i_rst_n)begin  //1
    if(!i_rst_n)begin
        hsync     <=1'b0;
        hsync_pre <=1'b0;
        vsync     <=1'b0;
        fsync     <=1'b0;
    end 
    else begin 
        hsync     <= i_hsync    ;
        hsync_pre <= i_hsync_pre;
        vsync     <= i_vsync    ;
        fsync     <= i_fsync    ;        
    end 
end

always @(posedge i_clk or negedge i_rst_n)begin  //1
    if(!i_rst_n)begin
        hsync_dly       <={(DLY1){1'b0}};
        hsync_pre_dly   <={(DLY1){1'b0}};
        vsync_dly       <={(DLY1){1'b0}};
        fsync_dly       <={(DLY1){1'b0}};
    end 
    else begin 
        hsync_dly     <= {hsync_dly[DLY1-2:0],    hsync    };
        hsync_pre_dly <= {hsync_pre_dly[DLY1-2:0],hsync_pre};
        vsync_dly     <= {vsync_dly[DLY1-2:0],    vsync    };
        fsync_dly     <= {fsync_dly[DLY1-2:0],    fsync    };        
    end 
end  

always @(posedge i_clk or negedge i_rst_n)begin 
    if(!i_rst_n)begin
        o_hsync     <=1'b0;
        o_hsync_pre <=1'b0;
        o_vsync     <=1'b0;
        o_fsync     <=1'b0;
    end 
    else if(i_zoom_ctrl == 1'b1)begin 
        o_hsync     <= hsync_dly[DLY1-1]    ;
        o_hsync_pre <= hsync_pre_dly[DLY1-1];
        o_vsync     <= vsync_dly[DLY1-1]    ;
        o_fsync     <= fsync_dly[DLY1-1]    ;
    end 
    else begin 
        o_hsync     <= hsync_dly[DLY1-1]    ;
        o_hsync_pre <= hsync_pre_dly[DLY1-1];
        o_vsync     <= vsync_dly[DLY1-1]    ;
        o_fsync     <= fsync_dly[DLY1-1]    ;
    end 
end





always @(posedge i_clk or negedge i_rst_n)begin 
    if(!i_rst_n)begin
         n_wx1_dly <={(8*DLY){1'b0}};
         n_wy1_dly <={(8*DLY){1'b0}};
         n_wx2_dly <={(8*DLY){1'b0}};
         n_wy2_dly <={(8*DLY){1'b0}};
    end 
    else begin 
         n_wx1_dly <={n_wx1_dly[(8*(DLY-1))-1:0],n_wx1[7:0]};
         n_wy1_dly <={n_wy1_dly[(8*(DLY-1))-1:0],n_wy1[7:0]};
         n_wx2_dly <={n_wx2_dly[(8*(DLY-1))-1:0],n_wx2};
         n_wy2_dly <={n_wy2_dly[(8*(DLY-1))-1:0],n_wy2};
    end 
end


always @(posedge i_clk or negedge i_rst_n)begin //WMULT+2
    if(!i_rst_n)begin
        data_buff1 <= 16'd0;
        data_buff2 <= 16'd0;
    end 
    else if(i_zoom_ctrl == 1'b1)begin           //WMULT+4
        data_buff1 <= n_wy2_dly[(8*DLY)-1:(8*DLY)-8]*(n_wx2_dly[(8*DLY)-1:(8*DLY)-8]*data11_pre+n_wx1_dly[(8*DLY)-1:(8*DLY)-8]*i_data11);
        data_buff2 <= n_wy1_dly[(8*DLY)-1:(8*DLY)-8]*(n_wx2_dly[(8*DLY)-1:(8*DLY)-8]*data21_pre+n_wx1_dly[(8*DLY)-1:(8*DLY)-8]*i_data12);
    end
    else begin 
        data_buff1 <= n_wy2_dly[(8*DLY)-1:(8*DLY)-8]*(n_wx2_dly[(8*DLY)-1:(8*DLY)-8]*i_data11+n_wx1_dly[(8*DLY)-1:(8*DLY)-8]*i_data12);
        data_buff2 <= n_wy1_dly[(8*DLY)-1:(8*DLY)-8]*(n_wx2_dly[(8*DLY)-1:(8*DLY)-8]*i_data21+n_wx1_dly[(8*DLY)-1:(8*DLY)-8]*i_data22);
    end 
end

always @(posedge i_clk or negedge i_rst_n)begin //+WMULT+3
    if(!i_rst_n)begin
        data_buff <= 16'd0;
    end 
    else begin 
        data_buff <= data_buff2 +data_buff1;
    end 
end

assign o_data = data_buff[15:8];



//计数器
always @(posedge i_clk or negedge i_rst_n)begin //1
   if(!i_rst_n)begin
        hcnt_tar <= {(TAR_WIDTH_W){1'b0}};
    end 
    else if(fsync)begin
        hcnt_tar <= {(TAR_WIDTH_W){1'b0}};
    end
    else if(add_hcnt_tar)begin 
            if(end_hcnt_tar)begin 
                hcnt_tar <= {(TAR_WIDTH_W){1'b0}};
            end
            else begin 
                hcnt_tar <= hcnt_tar + {{(TAR_WIDTH_W-1){1'b0}},1'b1} ;
            end 
    end
   else  begin
       hcnt_tar <= hcnt_tar;
    end
end 

assign add_hcnt_tar = vsync && hsync;
assign end_hcnt_tar = add_hcnt_tar && hcnt_tar == TAR_WIDTH -{{(TAR_WIDTH_W-1){1'b0}},1'b1} ;

always @(posedge i_clk or negedge i_rst_n)begin  //1
   if(!i_rst_n)begin
        vcnt_tar <= {(TAR_HEIGHT_H){1'd0}};
    end 
    else if(fsync)begin
       vcnt_tar <= {(TAR_HEIGHT_H){1'd0}}; 
    end
    else if(add_vcnt_tar)begin 
            if(end_vcnt_tar)begin 
                vcnt_tar <= {(TAR_HEIGHT_H){1'd0}};
            end
            else begin 
                vcnt_tar <= vcnt_tar + {{(TAR_HEIGHT_H-1){1'd0}},1'b1};
            end 
    end
   else  begin
       vcnt_tar <= vcnt_tar;
    end
end 

assign add_vcnt_tar = end_hcnt_tar;
assign end_vcnt_tar = add_vcnt_tar && vcnt_tar == TAR_HEIGHT -{{(TAR_HEIGHT_H-1){1'd0}},1'b1};

always @(posedge i_clk or negedge i_rst_n)begin 
   if(!i_rst_n)begin
        vcnt_pre <= {(TAR_HEIGHT_H){1'd0}};
    end 
    else if(fsync)begin
       vcnt_pre <= {(TAR_HEIGHT_H){1'd0}}; 
    end
    else if(add_vcnt_pre)begin 
            if(end_vcnt_pre)begin 
                vcnt_pre <= {(TAR_HEIGHT_H){1'd0}};
            end
            else begin 
                vcnt_pre <= vcnt_pre + {{(TAR_HEIGHT_H-1){1'd0}},1'b1};
            end 
    end
   else  begin
       vcnt_pre <= vcnt_pre;
    end
end 

assign add_vcnt_pre = i_hsync_pre == 1'b1 && hsync_pre == 1'b0;         //上升沿
assign end_vcnt_pre = add_vcnt_pre && vcnt_pre ==  TAR_HEIGHT -{{(TAR_HEIGHT_H-1){1'd0}},1'b1};

assign o_updata_ram =  i_hsync_pre == 1'b1 && hsync_pre == 1'b0;  //更新地址信号
assign o_vcnt =h_div_q[ORG_HEIGHT_H - 1:0];

always @(posedge i_clk or negedge i_rst_n)begin 
    if(!i_rst_n)begin
        cnt <= 4'd0;
    end 
    else if(fsync)begin
        cnt <= 4'd0;
    end
    else if(i_hsync == 1'b1 && hsync == 1'd0)begin 
        if(cnt >= 4'd2)begin
            cnt <= 4'd0;
        end
        else begin
            cnt <= 4'd1 +cnt;
        end
    end 
    else begin 
        cnt <= cnt;
    end 
end

always @(posedge i_clk or negedge i_rst_n)begin 
    if(!i_rst_n)begin
        flag <= 1'd0;
    end 
    else if(fsync)begin 
       flag <= 1'd0; 
    end 
    else if(i_hsync == 1'b1 && hsync == 1'd0)begin
        flag <= ~flag;
    end
    else begin 
      flag <= flag;  
    end 
end
//更新横向第二个地址    //WMULT+1
always @(posedge i_clk or negedge i_rst_n)begin 
    if(!i_rst_n)begin
         addr_buf <= {(RAM_ADDR_WIDTH){1'b0}};
    end 
    else if(hsync_dly[WMULT-2] == 1'b1 && hsync_dly[WMULT-1] ==1'b0)begin
        addr_buf <= {(RAM_ADDR_WIDTH){1'b0}};
    end
    else if((addr_buf + {{(RAM_ADDR_WIDTH-1){1'b0}},1'b1} >= (ORG_WIDTH-{{(ORG_WIDTH_W-1){1'b0}},1'b1} ))&& addr_buf == w_div_q[ORG_WIDTH_W-1:0])begin
        addr_buf <= (ORG_WIDTH-{{(ORG_WIDTH_W-1){1'b0}},1'b1});
    end
    else if(addr_buf == w_div_q[ORG_WIDTH_W-1:0])begin
        addr_buf <= addr_buf + {{(RAM_ADDR_WIDTH-1){1'b0}},1'b1};
    end
    else begin 
         addr_buf <= addr_buf;
    end 
end

//保存前两个数据
always @(posedge i_clk or negedge i_rst_n)begin 
    if(!i_rst_n)begin
        save_data <= 1'b0;
    end 
    else if(addr_buf == w_div_q[ORG_WIDTH_W-1:0])begin 
        save_data <= 1'b1;
    end 
    else begin 
        save_data <= 1'b0;
    end 
end

always @(posedge i_clk or negedge i_rst_n)begin            //ram 1
    if(!i_rst_n)begin
        o_addr2 <={(RAM_ADDR_WIDTH){1'b0}};
        o_addr4 <={(RAM_ADDR_WIDTH){1'b0}};
        o_addr1 <={(RAM_ADDR_WIDTH){1'b0}};
        o_addr3 <={(RAM_ADDR_WIDTH){1'b0}}; 
    end
    else if(i_ram_sel == 1'b1)begin
        case (flag)
            1'b1:  begin
                if(i_zoom_ctrl == 1'b1)begin    //WMULT+2
                     o_addr2 <= RAM_ADDR_START1 + addr_buf;
                     o_addr4 <= RAM_ADDR_START1 + addr_buf;
                     o_addr1 <= RAM_ADDR_START1 + addr_buf;
                     o_addr3 <= RAM_ADDR_START1 + addr_buf;
                end
                else begin
                if(w_div_q[ORG_WIDTH_W-1:0] >= (ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1}))begin //WMULT+1
                    o_addr2 <= RAM_ADDR_START1+ (ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
                    o_addr4 <= RAM_ADDR_START1+ (ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
                    o_addr1 <= RAM_ADDR_START1+ (ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
                    o_addr3 <= RAM_ADDR_START1+ (ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
                end
                else begin
                o_addr2 <= RAM_ADDR_START1+w_div_q[ORG_WIDTH_W-1:0] +1'b1;
                o_addr4 <= RAM_ADDR_START1+w_div_q[ORG_WIDTH_W-1:0] +1'b1; 
                o_addr1 <= RAM_ADDR_START1+w_div_q[ORG_WIDTH_W-1:0];
                o_addr3 <= RAM_ADDR_START1+w_div_q[ORG_WIDTH_W-1:0];   
                end
                end
            end
            1'b0: begin
                if(i_zoom_ctrl == 1'b1)begin
                    o_addr2 <= RAM_ADDR_START2 + addr_buf;
                    o_addr4 <= RAM_ADDR_START2 + addr_buf;
                    o_addr1 <= RAM_ADDR_START2 + addr_buf;
                    o_addr3 <= RAM_ADDR_START2 + addr_buf;
                end 
                else begin
                 if(w_div_q[ORG_WIDTH_W-1:0] >= (ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1}))begin
                o_addr1 <= RAM_ADDR_START2+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
                o_addr2 <= RAM_ADDR_START2+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
                o_addr3 <= RAM_ADDR_START2+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
                o_addr4 <= RAM_ADDR_START2+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
                end
                else begin
                o_addr1 <= RAM_ADDR_START2+w_div_q[ORG_WIDTH_W-1:0];
                o_addr2 <= RAM_ADDR_START2+w_div_q[ORG_WIDTH_W-1:0]+1'b1;
                o_addr3 <= RAM_ADDR_START2+w_div_q[ORG_WIDTH_W-1:0];
                o_addr4 <= RAM_ADDR_START2+w_div_q[ORG_WIDTH_W-1:0]+1'b1;
                end
                end
            end
            default: o_addr1<= o_addr1;
        endcase
     end 
     else begin 
       case (cnt)
        4'd0:begin
            if(i_zoom_ctrl == 1'b1)begin
                    o_addr2 <= RAM_ADDR_START3 + addr_buf;
                    o_addr4 <= RAM_ADDR_START3 + addr_buf;
                    o_addr1 <= RAM_ADDR_START3 + addr_buf;
                    o_addr3 <= RAM_ADDR_START3 + addr_buf;
                end
            else begin
             if(w_div_q[ORG_WIDTH_W-1:0] >= (ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1}))begin
                    o_addr1 <= RAM_ADDR_START3+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
                    o_addr2 <= RAM_ADDR_START3+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
                    o_addr3 <= RAM_ADDR_START3+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
                    o_addr4 <= RAM_ADDR_START3+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
            end
            else begin
                    o_addr1 <= RAM_ADDR_START3+w_div_q[ORG_WIDTH_W-1:0];
                    o_addr2 <= RAM_ADDR_START3+w_div_q[ORG_WIDTH_W-1:0]+1'b1;
                    o_addr3 <= RAM_ADDR_START3+w_div_q[ORG_WIDTH_W-1:0];
                    o_addr4 <= RAM_ADDR_START3+w_div_q[ORG_WIDTH_W-1:0]+1'b1; 
            end
            end
        end
        4'd1:begin
            if(i_zoom_ctrl == 1'b1)begin
                    o_addr2 <= RAM_ADDR_START1 + addr_buf;
                    o_addr4 <= RAM_ADDR_START1 + addr_buf;
                    o_addr1 <= RAM_ADDR_START1 + addr_buf;
                    o_addr3 <= RAM_ADDR_START1 + addr_buf;
                end
            else 
            begin if(w_div_q[ORG_WIDTH_W-1:0] >= (ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1}))begin
            o_addr1 <= RAM_ADDR_START1+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
            o_addr2 <= RAM_ADDR_START1+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
            o_addr3 <= RAM_ADDR_START1+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
            o_addr4 <= RAM_ADDR_START1+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
            end
            else begin
            o_addr1 <= RAM_ADDR_START1+w_div_q[ORG_WIDTH_W-1:0];
            o_addr2 <= RAM_ADDR_START1+w_div_q[ORG_WIDTH_W-1:0]+1'b1;
            o_addr3 <= RAM_ADDR_START1+w_div_q[ORG_WIDTH_W-1:0];
            o_addr4 <= RAM_ADDR_START1+w_div_q[ORG_WIDTH_W-1:0]+1'b1;
            end
            end
        end
        4'd2:begin
            if(i_zoom_ctrl == 1'b1)begin
                    o_addr2 <= RAM_ADDR_START2 + addr_buf;
                    o_addr4 <= RAM_ADDR_START2 + addr_buf;
                    o_addr1 <= RAM_ADDR_START2 + addr_buf;
                    o_addr3 <= RAM_ADDR_START2 + addr_buf; 
                end
            else 
            begin if(w_div_q[ORG_WIDTH_W-1:0] >= (ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1}))begin
            o_addr1 <= RAM_ADDR_START2+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
            o_addr2 <= RAM_ADDR_START2+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
            o_addr3 <= RAM_ADDR_START2+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
            o_addr4 <= RAM_ADDR_START2+(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1});
            end
            else begin
            o_addr1 <= RAM_ADDR_START2+w_div_q[ORG_WIDTH_W-1:0];
            o_addr2 <= RAM_ADDR_START2+w_div_q[ORG_WIDTH_W-1:0]+1'b1;
            o_addr3 <= RAM_ADDR_START2+w_div_q[ORG_WIDTH_W-1:0];
            o_addr4 <= RAM_ADDR_START2+w_div_q[ORG_WIDTH_W-1:0]+1'b1;
            end
            end
        end
        default: o_addr4 <= o_addr4;
       endcase
     end 
end

//权重
assign zoom_w = {(ORG_WIDTH -{{(ORG_WIDTH_W -1){1'b0}},1'b1}),10'd0};
assign zoom_h = {(ORG_HEIGHT-{{(ORG_HEIGHT_H-1){1'b0}},1'b1}),10'd0};

`IP_MODULE_NAME(divider) #(
.WIDTHN             (WZOOM                  ),
.WIDTHD             (TAR_WIDTH_W            ),
.NREPRESENTATION    ("UNSIGNED"             ),
.DREPRESENTATION    ("UNSIGNED"             ),
.LATENCY            (TAR_WIDTH_W            ),
.PIPELINE           (1                      )
) 
u_divider_wzoom
(
.numer              ( zoom_w                                            ),
.denom              ( TAR_WIDTH-{{(TAR_WIDTH_W-1){1'b0}},1'b1}          ),
.clken              ( 1'b1                                              ),
.clk                ( i_clk                                             ),
.reset              ( !i_rst_n                                          ),
.quotient           ( rsz_multiple_w                                    ),
.remain             (                                                   )  
);


`IP_MODULE_NAME(divider) #(
.WIDTHN             (HZOOM                  ),
.WIDTHD             (TAR_HEIGHT_H           ),
.NREPRESENTATION    ("UNSIGNED"             ),
.DREPRESENTATION    ("UNSIGNED"             ),
.LATENCY            (TAR_HEIGHT_H           ),
.PIPELINE           (1                      )
) 
u_divider_hzoom
(
.numer              ( zoom_h                                            ),
.denom              ( TAR_HEIGHT-{{(TAR_HEIGHT_H-1){1'b0}},1'b1}        ),
.clken              ( 1'b1                                              ),
.clk                ( i_clk                                             ),
.reset              ( !i_rst_n                                          ),
.quotient           ( rsz_multiple_h                                    ),
.remain             (                                                   )  
);


always @(posedge i_clk or negedge i_rst_n)begin             //1
    if(!i_rst_n)begin
         n_x0 <={(NX0){1'b0}};
         n_y0 <={(NY0){1'b0}};
    end 
    else begin 
         n_x0 <=rsz_multiple_w*{hcnt_tar,4'd0};
         n_y0 <=rsz_multiple_h*{vcnt_tar,4'd0};
    end 
end


always @(posedge i_clk or negedge i_rst_n)begin             //2
    if(!i_rst_n)begin
            n_wx0 <={(NX0){1'b0}};
            n_wy0 <={(NY0){1'b0}};
    end 
    else begin 
        n_wx0 <=(hcnt_tar*rsz_multiple_w)>>10;
        n_wy0 <=(vcnt_tar*rsz_multiple_h)>>10;
    end 
end

always @(posedge i_clk or negedge i_rst_n)begin             //3
    if(!i_rst_n)begin
         n_wx1 <= {(NX1){1'b0}};
         n_wy1 <= {(NY1){1'b0}};
    end 
    else begin 
        n_wx1 <=  n_x0[NX0-1:10]-{n_wx0,4'd0};
        n_wy1 <=  n_y0[NY0-1:10]-{n_wy0,4'd0};
    end 
end


assign n_wx2 = nZoomFPNZOOMFPN - n_wx1[7:0];
assign n_wy2 = nZoomFPNZOOMFPN - n_wy1[7:0];

//例化模块
//W
//n_rsz_multiple_w = (float)n_width / n_rsz_wid * nZoom;
// parallel_ppl_mult
// #(
//     .MUL1_WIDTH (ORG_WIDTH_W    )           ,//Multiplier1 width
//     .MUL2_WIDTH (TAR_WIDTH_W    )           ,//multiplier2 width
//     .PPL_LEVEL  (5              )           //pipeline levels

// )
// parallel_ppl_mult_w 
// (
//     .clk    (i_clk                  ),
//     .rst_n  (i_rst_n                ),
//     .mul1   (ORG_WIDTH              ),
//     .mul2   (hcnt_tar               ),
//     .prod   (w_mult              )
// );

assign w_mult = (ORG_WIDTH-1'b1)*hcnt_tar; //WMULT
`IP_MODULE_NAME(divider) #(
.WIDTHN             (WMULT                  ),
.WIDTHD             (TAR_WIDTH_W            ),
.NREPRESENTATION    ("UNSIGNED"             ),
.DREPRESENTATION    ("UNSIGNED"             ),
.LATENCY            (WMULT                  ),
.PIPELINE           (1                      )
) 
u_divider_w
(
.numer              ( w_mult                                            ),
.denom              ( TAR_WIDTH-{{(TAR_WIDTH_W-1){1'b0}},1'b1}          ),
.clken              ( 1'b1                                              ),
.clk                ( i_clk                                             ),
.reset              ( !i_rst_n                                          ),
.quotient           ( w_div_q                                           ),
.remain             ( w_div_r                                           )  
);

//n_rsz_multiple_h = (float)n_height / n_rsz_hei * nZoom;
//H
// parallel_ppl_mult
// #(
//     .MUL1_WIDTH (ORG_HEIGHT_H   )           ,//Multiplier1 width
//     .MUL2_WIDTH (TAR_HEIGHT_H   )           ,//multiplier2 width
//     .PPL_LEVEL  (5              )           //pipeline levels

// )
// parallel_ppl_mult_h_pre 
// (
//     .clk    (i_clk                  ),
//     .rst_n  (i_rst_n                ),
//     .mul1   (ORG_HEIGHT              ),
//     .mul2   (vcnt_pre               ),
//     .prod   (h_mult                 )
// );

assign h_mult =(ORG_HEIGHT -1'b1)*vcnt_pre;                 //TAR_HEIGHT_H
`IP_MODULE_NAME(divider) #(
.WIDTHN             (HMULT                  ),
.WIDTHD             (TAR_HEIGHT_H           ),
.NREPRESENTATION    ("UNSIGNED"             ),
.DREPRESENTATION    ("UNSIGNED"             ),
.LATENCY            (HMULT                  ),
.PIPELINE           (1                      )
) 
u_divider_h
(
.numer              ( h_mult                                                ),
.denom              ( TAR_HEIGHT-{{(TAR_HEIGHT_H-1){1'b0}},1'b1}              ),
.clken              ( 1'b1                                                  ),
.clk                ( i_clk                                                 ),
.reset              ( !i_rst_n                                              ),
.quotient           ( h_div_q                                               ),
.remain             ( h_div_r                                               )  
);

endmodule

端口名称 端口命名 方向 位宽 说明
时钟 i_clk IN 1
复位 i_rst_n IN 1
行有效输入 i_hsync IN 1
提前行有效输入 i_hsync_pre IN 1
场有效输入 i_vsync IN 1
帧有效输入 i_fsync IN 1
RAM更新数据信号 o_updata_ram OUT 1
RAM个数选择 i_ram_sel IN 1 1:2个 0:4个
RAM数据更新地址 o_vcnt OUT ORG_HEIGHT_H
RAM1读取地址 o_addr1 OUT RAM_ADDR_WIDTH
RAM2读取地址 o_addr1 OUT RAM_ADDR_WIDTH
RAM3读取地址 o_addr1 OUT RAM_ADDR_WIDTH
RAM4读取地址 o_addr1 OUT RAM_ADDR_WIDTH
RAM1读取数据 i_data11 IN 8
RAM2读取数据 i_data12 IN 8
RAM3读取数据 i_data21 IN 8
RAM4读取数据 i_data22 IN 8
RAM缓存几行数据 i_ram_sel IN 1 1:2行 0:3行
行有效输出 o_hsync OUT 1
提前行有效输出 o_hsync_pre OUT 1
场有效输出 o_vsync OUT 1
帧有效输出 o_fsync OUT 1
缩放数据输出 o_data OUT 8
放大前图像宽 ORG_WIDTH
放大前图像高 ORG_HEIGHT
放大后图像宽 TAR_WIDTH
放大后图像高 TAR_HEIGHT
ORG_WIDTH位宽 ORG_WIDTH_W
ORG_HEIGHT位宽 ORG_HEIGHT_H
TAR_WIDTH位宽 TAR_WIDTH_W
TAR_HEIGHT位宽 TAR_HEIGHT_H
RAM第一行开始位置 RAM_ADDR_START1
RAM第二行开始位置 RAM_ADDR_START2
RAM第三行开始位置 RAM_ADDR_START3
RAM地址深度 RAM_ADDR_WIDTH
注意: ORG_WIDTH_W、ORG_HEIGHT_H长度一样;
TAR_WIDTH_W、TAR_HEIGHT_H长度一样;
参数例化不能给位宽;
缩小必须四个RAM;

三、modelsim仿真程序


`timescale 1ps/1ps
module zoom_tb();								 

    wire            clk_50m     ;
    wire            clk_8x      ;
    wire            rst_n       ;

    wire            hsync           ;
    wire            hsync_pre       ;
    wire            vsync           ;
    wire            fsync           ;
    wire   [7:0]    data11          ;
    wire   [7:0]    data12          ;
    wire   [7:0]    data21          ;
    wire   [7:0]    data22          ;
    wire   [7:0]    data            ;
    wire            data_vld        ;
    wire   [12:0]   addr1           ;
    wire   [12:0]   addr2           ;
    wire   [12:0]   addr3           ;
    wire   [12:0]   addr4           ;
    wire            updata_ram      ;
    wire   [11:0]   vcnt            ;

    reg    [7:0]    data11_buf      ;
    reg    [7:0]    data12_buf      ;
    reg    [7:0]    data21_buf      ;
    reg    [7:0]    data22_buf      ;

    wire    [20:0]  add_r1          ;
    wire    [20:0]  add_r2          ;

    reg             flag            ;
    reg     [11:0]  cnt             ;
    reg     [2:0]   shift           ;


//get clk and reset
clk_rst_gen clk_rst_gen_inst
(   
                //INPUTS
                //OUTPUTS
               .clk_50m  (clk_50m   ),
               .clk_8x   (clk_8x    ),
               .rst_n    (rst_n     )
			 );


reg signed   [7:0]    SRC_RAM11[5760:0];
reg signed   [7:0]    SRC_RAM12[5760:0];
reg signed   [7:0]    SRC_RAM21[5760:0];
reg signed   [7:0]    SRC_RAM22[5760:0];

reg                     updata_ram_dly  ;    

reg signed   [7:0]    SRC_RAM1[2073600:0];


always @(posedge clk_8x or negedge rst_n)begin 
    if(!rst_n)begin
        updata_ram_dly <= 1'b0;
    end  
    else begin 
        updata_ram_dly <= updata_ram;
    end 
end

always @(posedge clk_50m or negedge rst_n)begin 
    if(!rst_n)begin
        data11_buf <=8'd0;
        data12_buf <=8'd0;
        data21_buf <=8'd0;
        data22_buf <=8'd0;
    end 
    else begin 
        data11_buf <=SRC_RAM11[addr1];
        data12_buf <=SRC_RAM12[addr2];
        data21_buf <=SRC_RAM21[addr3];
        data22_buf <=SRC_RAM22[addr4];
    end 
end

always @(posedge clk_8x or negedge rst_n)begin 
    if(!rst_n)begin
        flag <= 1'b0;
    end
    else if(cnt == 1919)begin
        flag <= 1'b0;
    end 
    else if(updata_ram_dly == 1'b0 && updata_ram == 1'b1)begin 
        flag <= 1'b1;
    end 
    else begin 
        flag <= flag;
    end 
end

always @(posedge clk_8x or negedge rst_n)begin 
    if(!rst_n)begin
        shift <= 3'b100;
    end
    else if(fsync) begin
        shift <= 3'b100;
    end
    else if(updata_ram_dly == 1'b0 && updata_ram == 1'b1)begin 
        shift <= {shift[1:0],shift[2]};
    end 
    else begin 
        shift <= shift;
    end 
end



always @(posedge clk_8x or negedge rst_n)begin 
    if(!rst_n)begin
        cnt <= 12'd0;
    end 
    else if(flag == 1'b1)begin
    if(cnt == 12'd1919)begin 
        cnt <= 12'd0;
    end 
    else begin
        cnt <= cnt +12'd1;
    end
    end
    else begin 
       cnt <= cnt; 
    end 
end


reg [7:0]     ram11;
reg [7:0]     ram12;
always @(posedge clk_8x or negedge rst_n)begin 
    if(!rst_n)begin
        ram11 <= 8'd0;
        ram12 <= 8'd0;
    end 
    else begin 
        ram11 <= SRC_RAM1[add_r1 +cnt];
        ram12 <= SRC_RAM1[add_r1 +cnt]; 
    end 
end


reg   [12:0]       addr_ram;

always @(*)begin 
     if(shift[0])begin
       addr_ram<= cnt;
     end 
     else if(shift[1])begin 
        addr_ram<= 11'd1920 +cnt;
     end
     else if(shift[2]) begin
      addr_ram <=  13'd3840+cnt;
     end
     else begin 
        addr_ram<=addr_ram;
     end 
end

//assign addr_ram = shift[0] ==1'b1?cnt:(shift[1] ==1'b1?(11'd1920 +cnt):(shift[2] ==1'b1?(12'd3840+cnt):addr_ram));



always @(posedge clk_8x or negedge rst_n)begin 
    if(!rst_n)begin
        SRC_RAM11[addr_ram] <= 8'd0;
        SRC_RAM12[addr_ram] <= 8'd0;
        SRC_RAM21[addr_ram] <= 8'd0;
        SRC_RAM22[addr_ram] <= 8'd0;
    end 
    // else if(shift[0])begin 
        // SRC_RAM11[addr_ram] <= SRC_RAM1[add_r1 +cnt];
        // SRC_RAM12[addr_ram] <= SRC_RAM1[add_r1 +cnt];
        // SRC_RAM21[addr_ram] <= SRC_RAM1[add_r2 +cnt];
        // SRC_RAM22[addr_ram] <= SRC_RAM1[add_r2 +cnt];
    // end 
    // else if(shift[1])begin
        // SRC_RAM11[addr_ram] <= SRC_RAM1[add_r1 +cnt];
        // SRC_RAM12[addr_ram] <= SRC_RAM1[add_r1 +cnt];
        // SRC_RAM21[addr_ram] <= SRC_RAM1[add_r2 +cnt];
        // SRC_RAM22[addr_ram] <= SRC_RAM1[add_r2 +cnt];
    // end
    // else if(shift[2])begin
        // SRC_RAM11[addr_ram] <= SRC_RAM1[add_r1 +cnt];
        // SRC_RAM12[addr_ram] <= SRC_RAM1[add_r1 +cnt];
        // SRC_RAM21[addr_ram] <= SRC_RAM1[add_r2 +cnt];
        // SRC_RAM22[addr_ram] <= SRC_RAM1[add_r2 +cnt];
    // end
    else begin 
        SRC_RAM11[addr_ram] <=SRC_RAM1[add_r1 +cnt];
        SRC_RAM12[addr_ram] <=SRC_RAM1[add_r1 +cnt]; 
        SRC_RAM21[addr_ram] <=SRC_RAM1[add_r2 +cnt];
        SRC_RAM22[addr_ram] <=SRC_RAM1[add_r2 +cnt];
    end 
end

// wire  [21:0]  addr_buf1;
// wire  [21:0]  addr_buf2;
// assign addr_buf1 = vcnt * 10'd640;
// assign addr_buf2 = (vcnt + 1'b1) *10'd640;

wire [23:0] add_r3;
wire [23:0] add_r4;

assign  add_r3 = ((updata_ram_dly == 1'b0 && updata_ram == 1'b1) ? vcnt * 12'd1920           : add_r3) ;//+cnt;
assign  add_r4 = ((updata_ram_dly == 1'b0 && updata_ram == 1'b1 ) ? (vcnt >= 12'd1079)? (12'd1079 * 12'd1920) : (vcnt + 1'b1) *12'd1920  : add_r4);// +cnt;
assign  add_r1 = add_r3[20:0]; 
assign  add_r2 = add_r4[20:0];

integer fid;
integer i;
integer s;

initial
begin
   fid = $fopen("../src/test_1080p.txt","r");
 
   for(i=0;i<2073600;i=i+1)  //460*512
       begin
        s= $fscanf(fid,"%d",SRC_RAM1[i]);
       end
    $fclose(fid);

end


//这里替换掉是个灰阶
// reg     flag11          ;  
// reg     [3:0]       cnt8;     
// reg     [7:0]        ram1_buff;
// reg     [20:0]        cnt20  ;
// reg     [7:0]           cnt88;


// always @(posedge clk_8x or negedge rst_n)begin 
//     if(!rst_n)begin
//         flag11 <= 1'b1;
//     end 
//     else if(cnt20 == 21'd2073600)begin 
//         flag11 <= 1'b0;
//     end 
//     else begin 
//         flag11 <=flag11;
//     end 
// end

// always @(posedge clk_8x or negedge rst_n)begin 
//     if(!rst_n)begin
//         cnt8 <= 4'd1;
//     end 
//     else if(flag11 == 1'b1)begin 
//         if(cnt8 == 8'd8)begin
//             cnt8 <= 4'd1;
//         end
//         else begin
//             cnt8 <= 4'd1 +cnt8;
//         end
//     end 
//     else begin 
//         cnt8 <= cnt8;
//     end 
// end

// always @(posedge clk_8x or negedge rst_n)begin 
//     if(!rst_n)begin
//         cnt20 <= 21'd0;
//     end 
//     else if(flag11 == 1'b1 )begin 
//         cnt20 <= cnt20 +21'd1;
//     end 
//     else begin 
//         cnt20 <=cnt20;
//     end 
// end


// always @(posedge clk_8x or negedge rst_n)begin 
//     if(!rst_n)begin
//         cnt88 <= 8'd0;
//     end 
//     else if(flag11 == 1'b1 && cnt8 == 4'd8)begin 
//         if(cnt88 == 8'd239)begin
//              cnt88 <= 8'd0;
//         end
//         else begin
//         cnt88 <= 8'd1 +cnt88;
//         end
//     end 
//     else begin 
//         cnt88 <= cnt88;
//     end 
// end
// always @(posedge clk_8x or negedge rst_n)begin 
//     if(!rst_n)begin
//         SRC_RAM1[cnt20] <= 8'd0;
//         ram1_buff <=8'd0;
//     end 
//     else  if(flag11 == 1'b1)begin 
//         SRC_RAM1[cnt20] <= cnt88;
//         ram1_buff <=cnt88;
//     end 
//     else begin
//         ram1_buff <= ram1_buff;          
//     end
// end




dv_timing dv_timing_inst( 
    .clk		     (clk_50m       ),
    .rst_n	         (rst_n         ),
    .hsync           (hsync         ),
    .hsync_pre       (hsync_pre     ),
    .vsync           (vsync         ),
    .vsync_pre       (              ),
    .fsync           (fsync         )

);	

assign data11 = data11_buf;
assign data12 = data12_buf;
assign data21 = data21_buf;
assign data22 = data22_buf;


					 



zoom #(
    .ORG_WIDTH            (1920      )                  ,        //放大前数据宽
    .ORG_HEIGHT           (1080      )                  ,        //放大前数据高
    .TAR_WIDTH            (800       )                   ,        //放大后目标数据宽
    .TAR_HEIGHT           (600       )                   ,        //放大后目标数据高
    .ORG_WIDTH_W          (12        )                  ,        //放大前数据宽
    .ORG_HEIGHT_H         (12        )                  ,        //放大前数据高
    .TAR_WIDTH_W          (10        )                  ,        //放大后目标数据宽
    .TAR_HEIGHT_H         (10        )                  ,        //放大后目标数据高
    .RAM_ADDR_START1      (0         )                  ,      
    .RAM_ADDR_START2      (1920      )                  ,    
    .RAM_ADDR_START3      (3840      )                  ,   
    .RAM_ADDR_WIDTH       (13        )                  ,
    .NZOOM                (1024      )                  ,
    .nZoomFPNZOOMFPN      (16        )

)
zoom_inst
(
    .i_clk                       (clk_50m                   ),
    .i_rst_n                     (rst_n                     ),
    .i_zoom_ctrl                 (1'b1),               //1:大 0:小
    .i_ram_sel                   (1'b0),
    .i_hsync                     (hsync        ),
    .i_hsync_pre                 (hsync_pre    ),
    .i_vsync                     (vsync        ),
    .i_fsync                     (fsync        ),
    .i_data11                    (data11       ),                   
    .i_data12                    (data12       ),               
    .i_data21                    (data21       ),
    .i_data22                    (data22       ),   
    .o_addr1                     (addr1        ),
    .o_addr2                     (addr2        ),
    .o_addr3                     (addr3        ),
    .o_addr4                     (addr4        ),
    .o_data                      (data         ),
    .o_hsync                     (data_vld),
    .o_hsync_pre                 (),
    .o_vsync                     (),
    .o_fsync                     (),
    .o_vcnt                      (vcnt),
    .o_updata_ram                (updata_ram)

);


reg       [3:0]  cnt22;
reg         wr_en;
always @(posedge clk_50m or negedge rst_n)begin 
    if(!rst_n)begin
        cnt22 <= 4'd0;
    end 
    else if(fsync)begin 
       cnt22 <= cnt22 +4'd1; 
    end 
    else begin 
        cnt22 <= cnt22;
    end 
end

integer fid2;
    
initial
begin
   #1000000
   fid2 = $fopen("C:/Users/li_thers/Desktop/zoom/src/test_800_600.txt","w");
  wr_en=1'b1;
   #24200000
   wr_en=1'b0;
//   $fclose(fid2) ;
end

always@(posedge clk_50m)
begin
   if(data_vld && cnt22 == 4'd1)
    begin
        $fwrite(fid2,"%d\n",$unsigned(data));
    end 
end
                        
endmodule

其它辅助模块
仿真产生时钟
下面展示一些 内联代码片


//============================================================

`timescale 1ps/1ps

//============================================================
// module name defination
module clk_rst_gen (   
                //INPUTS
                //OUTPUTS
               clk_50m,
               clk_8x,
               rst_n
			 );

//INPUTS

//OUTPUTS
output          clk_50m;
output          clk_8x;
output          rst_n;

reg             clk_50m;  // 100Mhz
reg             clk_8x;   //8倍
reg             rst_n;
	       
initial
begin
   clk_50m         = 1'b0;
   clk_8x          = 1'b0;
   rst_n           = 1'b1;
end

always #10000  clk_50m   = ~clk_50m;            
always #1250   clk_8x    = ~clk_8x;

initial
begin
   #10000 rst_n=0;
   #10000 rst_n=1;
end

endmodule


//1080p时序无有效数据
module dv_timing( 
    input				clk		        ,
    input				rst_n	        ,
    output              hsync           ,
    output              hsync_pre       ,
    output              vsync           ,
    output              vsync_pre       ,
    output              fsync           

);								 
    //参数定义			 
    parameter   HMUN = 12'd900,   // 2560
                VMUN = 12'd700;   // 2048           
    //中间信号定义		 

reg         [11:0]  vcnt;
reg         [11:0]  hcnt;
  
assign hsync     = vsync && (hcnt >12'd20) && (hcnt <=12'd820); 
assign hsync_pre = vsync_pre && (hcnt >12'd20) && (hcnt <=12'd820); 
assign vsync     = vcnt >12'd10 && vcnt <=12'd610; 
assign vsync_pre = vcnt >12'd9 && vcnt <=12'd609; 
assign fsync     = vcnt == 12'd2  && hcnt == 12'd1;

always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        hcnt <= 12'd1;
    end 
    else if(hcnt == HMUN)begin 
        hcnt <= 12'd1;
    end 
    else begin 
        hcnt <= 12'd1 + hcnt;
    end 
end

always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        vcnt <= 12'd1;
    end 
    else if(hcnt == HMUN)begin 
        if(vcnt == VMUN)begin
            vcnt <= 12'd1;
        end
        else begin
            vcnt <= 12'd1 + vcnt;
        end
    end 
    else begin  //hold 
        vcnt <= vcnt;
    end 
end





endmodule

do文件


vlib work 
vlog ../src/dv_timing/dv_timing_copy.v
vlog ../src/clk_rst_gen/clk_rst_gen.v
vlog ../src/dis_play/zoom/*.v
vlog ../tb/zoom_tb.v

vsim -novopt work.zoom_tb


add wave sim:/zoom_tb/clk_rst_gen_inst/*
add wave sim:/zoom_tb/zoom_inst/*


#radix -dec
run 2700 us 
#run 180 us 

四、matlab验证


clear all

  
data1 = load('data_640_512.txt');
img1 = reshape(data1,640,512);

img1=flipud(img1');

figure(1);
surf(img1);                        
shading interp;                    
axis image;                        
view(2);                           
colormap(gray);                    

data2 = load('test_1920_1080x.txt');
img2 = reshape(data2,1920,1080);

img2=flipud(img2');



figure(2);
surf(img2);                     
shading interp;                 
axis image;                     
view(2);                        
colormap(gray);                 

data3 = load('test_1920_1080x1.txt');
img3 = reshape(data3,1920,1080);

img2=flipud(img3');

figure(3);
surf(img2);                     
shading interp;                 
axis image;                     
view(2);                        
colormap(gray);                 

结果
【FPGA】双线性差值实现图像缩放,使用modelsim和matlab仿真验真_第2张图片
整个模块延时就ORG_WIDTH_W+TAR_WIDTH_W+4个clk

你可能感兴趣的:(FPGA,fpga开发,matlab,开发语言)