FPGA project : uart232_ram_vga

news/2024/7/3 0:46:33

重点学习:

本实验重点学习了双口ram解决多bit跨时钟域同步处理的问题。

其实signal port ram,它的输入口和输出口分别用不同的时钟,也可以解决这个问题。

让我意识到的比较重要的事情:

1,代码设计中,一些大于10的数字,尽量用parameter设定一些可以重传的参数来代替。因为这样方便仿真修改。我就是之前写uart_rx模块,数字啥的没用参数替代。这个实验中仿真时需要修改参数,然后重新修改了uart_rx代码。使得仿真时间大大缩短,很方便。

2,在vga_pic模块中模拟产生的ram,读完数据后,ram里面的数据并没有消失,还在。

写数据:在时钟上升沿,写使能拉高,与此同时要有对应的地址与数据。然后数据就写进对应的地址里面了。

读数据:在时钟上升沿,读使能拉高,与此同时给出地址,然后数据就都出来了。值得一提的是,数据会滞后一个时钟周期(相对于读使能与地址),说明ram内部用的时序逻辑嘛。

3, task input ...如果写在task内部了。那么在task name 后面就不要加括号了。否则modulism会报错。

 

module vga_pic (
    input       wire            clk_25  , // ram 的输出时钟,也是vga图像的时钟。
    input       wire            clk_50  , // ram 的输入时钟
    input       wire            rst_n   , // 经过系统复位和pll的locked相与后的复位。
    input       wire    [9:0]   pix_x   ,
    input       wire    [9:0]   pix_y   ,
    input       wire    [7:0]   po_data , // 写入的数据的数据
    input       wire            po_flag , // 用作ram的读使能。

    output      wire    [7:0]   pix_data
);
    // parameter 
    parameter   H_VALID = 10'd640    ,
                V_VALID = 10'd480    ;

    parameter   PIC_SIZE= 14'd1_0000 ,
                H_PIC   = 10'd100    ,
                V_PIC   = 10'd100    ;

    parameter   RED     = 8'b1110_0000 ,
                GREEN   = 8'b0001_1100 ,
                BLUE    = 8'b0000_0011 ,
                WHITE   = 8'b1111_1111 ,
                BLACK   = 8'b0000_0000 ;

    // reg signal define
    reg     [13:0]  wr_addr  ;  // ram 的写地址。
    reg     [ 7:0]  data_pix ;  // 彩条像素
    reg             pic_valid; // 图片有效
    wire    [ 7:0]  pic_data ; // 图片像素
    reg             rd_en    ; // ram读使能
    reg     [13:0]  rd_addr  ;

/************************************************************************/
    // reg     [13:0]  wr_addr  ;  // ram 的写地址。    
    always @(posedge clk_50 or negedge rst_n) begin
        if(~rst_n) begin
            wr_addr <= 14'd0 ;
        end else begin
            if(po_flag) begin
                if(wr_addr == 9999) begin // 记到最大的地址后归零。
                    wr_addr <= 14'd0 ;
                end else begin
                    wr_addr <= wr_addr + 1'b1 ;
                end
            end else begin
                wr_addr <= wr_addr ;
            end
        end
    end

    // reg     [ 7:0]  data_pix ;  // 彩条像素
    always @(posedge clk_25 or negedge rst_n) begin 
        if(~rst_n) begin
            data_pix <= BLACK ;
        end else begin
            if(pix_y >= 0 && pix_y <= (V_VALID / 5 - 1))
                data_pix <= RED ;
            else if((pix_y >= V_VALID / 5) && pix_y <= ((V_VALID / 5 ) * 2) - 1)
                data_pix <= GREEN ;
            else if((pix_y >= (V_VALID / 5) * 2) && pix_y <= ((V_VALID / 5 ) * 3) - 1)
                data_pix <= BLUE ;
            else if((pix_y >= (V_VALID / 5) * 3) && pix_y <= ((V_VALID / 5 ) * 4) - 1)
                data_pix <= WHITE ;
            else if((pix_y >= (V_VALID / 5) * 4) && pix_y <= (V_VALID  - 1))
                data_pix <= BLACK ;
            else 
                data_pix <= BLACK ;
        end // 先不写else 一会看编译是否会通过。
    end
    // reg             pic_valid; // 图片有效
    always @(posedge clk_25 or negedge rst_n) begin
        if(~rst_n) begin
            pic_valid <= 1'b0 ;
        end else begin
            if(pix_x >= 269 && pix_x <= 368 && pix_y >= 190 && pix_y <= 289) begin
                pic_valid <= 1'b1 ;
            end else begin
                pic_valid <= 1'b0 ;
            end
        end
    end
    // wire    [ 7:0]  pic_data ; // 图片像素
    // 图片像素存在了ram中,所以只需要取出来就是图片像素了。
    // reg             rd_en    ; // ram读使能
    always @(posedge clk_25 or negedge rst_n) begin
        if(~rst_n) begin
            rd_en <= 1'b0 ;
        end else begin
            if(pix_x >= 268 && pix_x <= 367 && pix_y >= 190 && pix_y <= 289) begin
                rd_en <= 1'b1 ;
            end else begin
                rd_en <= 1'b0 ;
            end
        end
    end
    // reg     [13:0]  rd_addr  ;
    always @(posedge clk_25 or negedge rst_n) begin
        if(~rst_n) begin
            rd_addr <= 14'd0 ;
        end else begin
            if(rd_en) begin
                if(rd_addr == 9999) begin
                    rd_addr <= 14'd0 ;
                end else begin
                    rd_addr <= rd_addr + 1'b1 ;
                end
            end else begin
                rd_addr <= rd_addr ;
            end
        end
    end

/**********************output signal define**************************************/
    // wire    [7:0]   pix_data ;
    assign pix_data = (pic_valid == 1'b1) ? pic_data : data_pix ;
/******************例化双口ram*******************/
ram_10000_double ram_10000_double_insert(
	.data                   ( po_data ) ,
	.inclock                ( clk_50  ) ,
	.outclock               ( clk_25  ) ,
	.rdaddress              ( rd_addr ) ,
	.wraddress              ( wr_addr ) ,
	.wren                   ( po_flag ) ,
	.q                      ( pic_data)
);

endmodule

 

module top(
    input       wire            sys_clk     ,
    input       wire            sys_rst_n   ,
    input       wire            rx          ,

    output      wire    [7:0]   rgb         ,
    output      wire            hsync       ,
    output      wire            vsync   
);

    // 例化间连线
    wire            rst_n       ;
    wire    [7:0]   po_data     ;
    wire            po_flag     ;
    wire    [7:0]   pix_data    ;
    wire    [9:0]   pix_x       ;
    wire    [9:0]   pix_y       ;
    wire            clk_25      ;
    wire            clk_50      ;

pll	pll_inst (
    .sys_rst_n              ( sys_rst_n     ) ,
	.areset                 ( ~sys_rst_n    ) ,
	.inclk0                 ( sys_clk       ) ,
	.c0                     ( clk_25        ) ,
	.c1                     ( clk_50        ) ,
	.locked                 ( rst_n         )
);

uart_rx uart_rx_inst(
    .sys_clk                ( clk_50        ) ,
    .sys_rst_n              ( rst_n         ) ,
    .rx                     ( rx            ) ,

    .po_data                ( po_data       ) ,
    .po_flag                ( po_flag       ) 
);

vga_ctrl vga_ctrl_inst(
    .vga_clk                ( clk_25        ) ,
    .vga_rst_n              ( rst_n         ) ,
    .pix_data               ( pix_data      ) ,

    .hsync                  ( hsync         ) ,
    .vsync                  ( vsync         ) ,
    .pix_x                  ( pix_x         ) ,
    .pix_y                  ( pix_y         ) ,
    .rgb                    ( rgb           )         
);

vga_pic vga_pic_inst(
    .clk_25                 ( clk_25        ) ,
    .clk_50                 ( clk_50        ) ,
    .rst_n                  ( rst_n         ) ,
    .pix_x                  ( pix_x         ) ,
    .pix_y                  ( pix_y         ) ,
    .po_data                ( po_data       ) ,
    .po_flag                ( po_flag       ) ,

    .pix_data               ( pix_data      )
);


endmodule
`timescale 1ns/1ns
module test_top();
    reg             sys_clk     ;
    reg             sys_rst_n   ;
    reg             rx          ;

    wire    [7:0]   rgb         ;
    wire            hsync       ;
    wire            vsync       ;

    reg     [7:0]   data_mem    [9999:0];


top top_insert(
    .sys_clk                ( sys_clk    ) ,
    .sys_rst_n              ( sys_rst_n  ) ,
    .rx                     ( rx         ) ,

    .rgb                    ( rgb        ) ,
    .hsync                  ( hsync      ) ,
    .vsync                  ( vsync      )   
);

    defparam    top_insert.uart_rx_inst.CLK_FREQ = 5 ;
    defparam    top_insert.uart_rx_inst.UART_BPS = 1  ;
    parameter   CYCLE = 20 ;
    initial begin
        sys_clk     = 1'b1 ;
        sys_rst_n   <=1'b0 ;
        #(CYCLE)           ;
        sys_rst_n   <=1'b1 ; 
    end
    always #(CYCLE / 2) sys_clk = ~sys_clk ;

    initial begin
        $readmemh ("D:/intel_FPGA/VScodedocument/EmbedFire/31 rs232_vga/matlab/data_test.txt",data_mem);
    end

    initial begin
        rx <= 1'b1 ;
        #(CYCLE * 10) ;
        rx_byte ;
    end

    task    rx_byte;
    integer j ; // j 是存储器的地址。
    for (j = 0;j < 10000 ;j = j + 1 ) begin
        rx_bit(data_mem[j]) ; // 没有输入端口,自然不需要输入参数。
    end
    endtask

    task    rx_bit;
    input [7:0]data ;
    integer i ;
    for (i = 0;i < 10 ;i = i + 1 ) begin
        case (i)
        0:rx    <= 1'b0;
        1:rx    <= data[0];
        2:rx    <= data[1];
        3:rx    <= data[2];
        4:rx    <= data[3];
        5:rx    <= data[4];
        6:rx    <= data[5];
        7:rx    <= data[6];
        8:rx    <= data[7];
        9:rx    <= 1'b1;
        default: rx    <= 1'b1;
        endcase
        #(5 * CYCLE) ;
    end
    endtask
endmodule

 


http://lihuaxi.xjx100.cn/news/1576391.html

相关文章

电子电路学习笔记之NCV6324BMTAATBG——同步降压转换器

关于同步降压转换器&#xff1f; 是一种广泛应用于各种电子产品中的转换器。它具有输入范围宽、转换效率高、输出电流大等优点。在同步降压型转换器的驱动电路中&#xff0c;一般包括电平移位电路、死区时间控制电路以及过零检测电路等。 电平移位电路用于将固定电平Vcc和GND…

Linux 磁盘扩容glusterfs节点容量过程

resize2fs 命令 使用 resize2fs 命令扩展文件系统时&#xff0c;可以通过指定新的大小来设置扩容量。有几种指定方式&#xff1a; 扩展到指定的绝对大小&#xff08;如 10GB&#xff09;&#xff1a; sudo resize2fs /dev/<partition> 10G其中&#xff0c; 是要扩展的…

两种fifo实现方式的差异

减少数据通路翻转来降低功耗&#xff1a; 以FIFO &#xff08;当容量较小而使用寄存器作为存储部分&#xff09;设计为例&#xff0c;虽然理论上可以使用比较简单的数据表项逐次移位的方式&#xff0c;实现FIFO 的先入先出功能&#xff0c;但是却应该使用维护读写指针的方式&am…

LCR 012.寻找数组的中心下标

​​题目来源&#xff1a; leetcode题目&#xff0c;网址&#xff1a;LCR 012. 寻找数组的中心下标 - 力扣&#xff08;LeetCode&#xff09; 解题思路&#xff1a; 获取第一个元素左边的元素 leftSum 和 右边的元素和 rightSum&#xff0c;按序遍历数组的同时不断更新 leftSu…

Selenium —— 网页frame与多窗口处理!

一、多窗口处理. 1.1、多窗口简介 点击某些链接&#xff0c;会重新打开⼀个窗⼜&#xff0c;对于这种情况&#xff0c;想在新页⾯上操作&#xff0c;就 得先切换窗⼜了。 获取窗⼜的唯⼀标识⽤句柄表⽰&#xff0c;所以只需要切换句柄&#xff0c;就可以在多个页⾯灵 活操作了…

机器学习---冷启动(Cold Start)、热启动(Warm Start)问题

在机器学习和推荐系统领域&#xff0c;“冷启动”&#xff08;Cold Start&#xff09;和"热启动"&#xff08;Warm Start&#xff09;是两个常用的概念&#xff0c;它们用来描述不同阶段或情境下的推荐问题。 冷启动&#xff08;Cold Start&#xff09;&#xff1a; …

【文献】TOF标定 Time-of-Flight Sensor Calibration for a Color and Depth Camera Pair

文章目录 Article info.Introduction处理TOF误差Take home messagesResourcesIDEAS Article info. Time-of-Flight Sensor Calibration for a Color and Depth Camera Pair IEEE TRANSACTIONS ON PATTERN ANALYSIS AND MACHINE INTELLIGENCE, VOL. 37, NO. 7, JULY 2015 Intr…

线性代数+分治:446E

https://codeforces.com/problemset/problem/446/E 把官方题解翻译了一遍 考虑暴力&#xff0c;肯定想到dp&#xff0c;然后变成矩阵。设用代替 &#xff08;这样子数之间的差值不会变化&#xff0c;但对于问题的处理能方便很多&#xff09; 我们先令&#xff08;也就是初始…