FPGA project : uart232_ram_vga

重点学习:

本实验重点学习了双口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会报错。

FPGA project : uart232_ram_vga_第1张图片

 FPGA project : uart232_ram_vga_第2张图片FPGA project : uart232_ram_vga_第3张图片

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

 

FPGA project : uart232_ram_vga_第4张图片

你可能感兴趣的:(野火征途pro,fpga开发)