FPGA project : ROM_VGA

在之前彩条显示工程中增添一个rom模块,在中心显示100 X 100 的一个图像。

主要考察rom的使用。读数据拉高,并输入地址。下个周期输出该地址对应的数据。

如果输出口不加reg寄存一下,数据只会滞后一个时钟周期输出(相对于读使能)。

加了 滞后两个。相当于打了一拍嘛。比较好理解。

在设计这个实验中,还重点考察了,坐标与数据,在时序上要对齐。

尤其输出信号用reg,对某个“数据输出信号”采样。虽然“数据输出信号”和坐标对齐了。

但是真正要输出的信号,还是滞后了一个时钟周期(相对于坐标)。

所以还要把“数据输出信号”提前一个时钟周期的同时,把输出信号的采样点也提前一个时钟周期,这样输出信号才能完全和坐标对齐。

仿真图上有直观的文字说明。

FPGA project : ROM_VGA_第1张图片

// #define   BLACK     0x0000       //   黑色    
// #define   NAVY      0x000F       //    深蓝色  
// #define   DGREEN    0x03E0       //  深绿色  
// #define   DCYAN     0x03EF       //   深青色  
// #define   MAROON    0x7800       //   深红色      
// #define   PURPLE    0x780F       //   紫色  
// #define   OLIVE     0x7BE0       //   橄榄绿      
// #define   LGRAY     0xC618       //  灰白色
// #define   DGRAY     0x7BEF       //  深灰色      
// #define   BLUE      0x001F       //  蓝色    
// #define   GREEN     0x07E0       //  绿色          
// #define   CYAN      0x07FF       //  青色  
// #define   RED       0xF800       //  红色       
// #define   MAGENTA   0xF81F       //  品红    
// #define   YELLOW    0xFFE0       //  黄色        
// #define   WHITE     0xFFFF       //  白色  
// rgb 565
module vga_pix (
    input           wire            vga_clk   ,
    input           wire            vga_rst_n ,
    input           wire    [9:0]   pix_x     ,
    input           wire    [9:0]   pix_y     ,

    output          reg     [15:0]  pix_data  
);

	reg 	[13:0]  address ; // 在读使能信号拉高,每个时钟周期自加一,0 ~ 9999
	reg 	        rden    ; // 读使能信号超前图像数据一个时钟周期。
	wire	[15:0]  q       ; // 从rom里读出的数据。
    wire    [13:0]  address_w ;
    wire            rden_w  ; 

    // parameter  
    parameter   H_VALID = 10'd640  ,
                V_VALID = 10'd480  ;
    parameter   RED     = 16'hF800 ,
                ORANGE  = 16'hFC00 ,
                YELLOW  = 16'hFFe0 ,
                GREEN   = 16'h07e0 ,
                QING    = 16'h07FF ,
                BLUE    = 16'h001F ,
                PURPLE  = 16'hF81F ,
                BLACK   = 16'h0000 ,
                WHITE   = 16'hFFFF ,
                GRAY    = 16'hD69A ;

    // output signal
    always @(posedge vga_clk or negedge vga_rst_n) begin
        if(~vga_rst_n) begin
            pix_data <= 10'h3ff ;
        end else begin // 有简便写法 ( H_VALID / 10 ) * n
            if((pix_y >= 190) && (pix_y <= 289) && (pix_x >= 269) && (pix_x <= 368))
                pix_data <= q ;
            else 
            if((pix_y >= 10'd0) && (pix_y <= V_VALID / 10 - 1'b1))
                pix_data <= RED ;
            else 
            if((pix_y >= V_VALID / 10) && (pix_y <= (V_VALID / 10) * 2 - 1'b1))
                pix_data <= ORANGE ;
            else
            if((pix_y >= (V_VALID / 10) * 2) && (pix_y <= (V_VALID / 10) * 3 - 1'b1))
                pix_data <= YELLOW ;
            else 
            if((pix_y >= (V_VALID / 10) * 3) && (pix_y <= (V_VALID / 10) * 4 - 1'b1))
                pix_data <= GREEN ;
            else 
            if((pix_y >= (V_VALID / 10) * 4) && (pix_y <= (V_VALID / 10) * 5 - 1'b1))
                pix_data <= QING ;
            else 
            if((pix_y >= (V_VALID / 10) * 5) && (pix_y <= (V_VALID / 10) * 6 - 1'b1))
                pix_data <= BLUE ;
            else 
            if((pix_y >= (V_VALID / 10) * 6) && (pix_y <= (V_VALID / 10) * 7 - 1'b1))
                pix_data <= PURPLE ;
            else 
            if((pix_y >= (V_VALID / 10) * 7) && (pix_y <= (V_VALID / 10) * 8 - 1'b1))
                pix_data <= BLACK ;
            else 
            if((pix_y >= (V_VALID / 10) * 8) && (pix_y <= (V_VALID / 10) * 9 - 1'b1))
                pix_data <= WHITE ;
            else 
            if((pix_y >= (V_VALID / 10) * 9) && (pix_y <= V_VALID - 1'b1) )
                pix_data <= GRAY ;
            else 
                pix_data <= BLACK ;
        end
    end
/****************新增代码*******************/
rom_pic rom_pic_insert(
	.address        ( address_w ),
	.clock          ( vga_clk   ),
	.rden           ( rden_w    ),
	.q              ( q         )
    );

	// reg 	[13:0]  address; // 在读使能信号拉高,每个时钟周期自加一,0 ~ 9999
    always @(posedge vga_clk or negedge vga_rst_n) begin
        if(~vga_rst_n) begin
            address <= 0 ;
        end else begin
            if(rden == 1'b1) begin
                if(address == 9999) begin
                    address <= 0 ;
                end else begin
                    address <= address + 1'b1 ;
                end
            end else begin
                address <= address ;
            end
        end
    end
    assign address_w = address ;
	// reg 	        rden; // 读使能信号超前图像数据一个时钟周期。..或者说rom读出的数据,滞后读使能信号一个时钟周期。这是输出端口没有加reg的情况。加了要滞后两个时钟周期。
    always @(posedge vga_clk or negedge vga_rst_n) begin // 这其实也说明了,时序逻辑会滞后条件一个时钟周期。说明输出是reg型。
        if(~vga_rst_n) begin
            rden <= 1'b0 ;
        end else begin
            if((pix_y >= 190) && (pix_y <= 289) && (pix_x >= 267) && (pix_x <= 366)) begin
                rden <= 1'b1 ;
            end else begin
                rden <= 1'b0 ;
            end
        end
    end
    assign rden_w = rden ;

endmodule 

 FPGA project : ROM_VGA_第2张图片

 FPGA project : ROM_VGA_第3张图片

 FPGA project : ROM_VGA_第4张图片

FPGA project : ROM_VGA_第5张图片 

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