这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » anmko的进程贴:综合实验-基于DS1302的万年历LCD1602显示(最终版

共76条 7/8 |‹ 3 4 5 6 7 8 跳转至
高工
2012-11-29 08:57:37     打赏
61楼

19:模块例化一:按键模块

       功能模块例化,在不同应用中可以直接的调用而不必重新的编写。




                                  封装好了的按键功能模块


verilog程序如下:
module key_interface
#(
 parameter KEY_WIDTH = 7   //按键个数
)

(
 input clk, //时钟输入50MHZ
 input rst, //复位
 input [KEY_WIDTH-1:0] key_trigger, //按键输入端口
 output key_flag, //按键标识
 output reg [KEY_WIDTH-1:0] key_value //按键数值输出
);

 wire cnt_flag;
 reg[19:0] key_cnt; //延时20ms
 reg[KEY_WIDTH-1:0] key_trigger_r; //按键输入端口缓存
 always @(posedge clk or negedge rst)
 begin
  if(!rst)
   begin
   key_trigger_r <= {KEY_WIDTH{1'b1}}; 
   key_cnt <= 20'b0; 
   end
  else
   begin
   key_trigger_r <= key_trigger; //端口赋值给缓存
   if((key_trigger == key_trigger_r) && (key_trigger != {KEY_WIDTH{1'b1}}))
   begin    //前后两次的值相等,而且不恒为高电平
    if(key_cnt < 20'hfffff)
     key_cnt <= key_cnt + 1'b1; //延迟20ms
    end
    else 
     key_cnt <= 20'b0;
   end
 end
 assign cnt_flag = (key_cnt == 20'hffffe) ? 1'b1 : 1'b0;
        
 reg key_flag_r;
 always @(posedge clk or negedge rst)
 begin
  if(!rst)
   begin
   key_flag_r <= 1'b0;
   key_value <= {KEY_WIDTH{1'b1}};
   end
  else if(cnt_flag)
   begin
   key_flag_r <= 1'b1;
   key_value <= key_trigger; //按键值输出(按下的为0,其余的为1)
   end
  else
   key_flag_r <= 1'b0;
 end
 
 reg key_flag_r0,key_flag_r1;
 always @(posedge clk or negedge rst)
 begin
  if(!rst)
   begin
   key_flag_r0 <= 1'b0;
   key_flag_r1 <= 1'b0;
   end
  else
   begin
   key_flag_r0 <= key_flag_r;
   key_flag_r1 <= key_flag_r0;
   end
 end
 assign key_flag = (!key_flag_r1)& key_flag_r0; //上升沿
 
endmodule


高工
2012-11-29 11:14:10     打赏
62楼

20:模块例化二:数码管显示模块



verilog程序:

module disp_interface
(

 input clk, //时钟输入50MHZ
 input rst, //复位
 input [39:0] disp_value, //数据输入端口

 output reg [7:0] disp_reg,
 output reg [7:0] disp_bit
); 

 reg[15:0] cnt_scan;
 always @(posedge clk or negedge rst) begin
  if (!rst)
   cnt_scan <=15'b0;
  else cnt_scan <= cnt_scan + 1'b1;
 end
     
 always @(cnt_scan) begin
  case (cnt_scan[15:13])
   3'b000:
    disp_bit <= 8'b1111_1110;
   3'b001:
    disp_bit <= 8'b1111_1101;
   3'b010:
    disp_bit <= 8'b1111_1011;
   3'b011:
    disp_bit <= 8'b1111_0111;
   3'b100:
    disp_bit <= 8'b1110_1111;
   3'b101:
    disp_bit <= 8'b1101_1111;
   3'b110:
    disp_bit <= 8'b1011_1111;
   3'b111:
    disp_bit <= 8'b0111_1111;
   default:
    disp_bit <= 8'b1111_1110;
  endcase
 end
 
 reg [4:0] disp_reg_r;
 always @(posedge clk) begin
  case (disp_bit)  
       
   8'b1111_1110:
    disp_reg_r <= disp_value[4:0]; //0
   8'b1111_1101:
    disp_reg_r <= disp_value[9:5]; //1
   8'b1111_1011:
    disp_reg_r <= disp_value[14:10]; //2
   8'b1111_0111:
    disp_reg_r <= disp_value[19:15]; //3
   8'b1110_1111:
    disp_reg_r <= disp_value[24:20]; //4
   8'b1101_1111:
    disp_reg_r <= disp_value[29:25]; //6
   8'b1011_1111:
    disp_reg_r <= disp_value[34:30]; //7
   8'b0111_1111:
    disp_reg_r <= disp_value[39:35]; //8
   default:
    disp_reg_r <= 5'h10;
  endcase
 end
 
 
 always @(disp_reg_r) begin
  case (disp_reg_r)  //0-c0,1-f9,2-a4,3-b0,4-99,5-92,6-82,7-f8,8-80,9-90,
       //a-88,b-83,c-c6,d-a1,e-86,f-8e,--bf,.-7f,
   5'h00:
    disp_reg <= 8'hc0; //0
   5'h01:
    disp_reg <= 8'hf9; //1
   5'h02:
    disp_reg <= 8'ha4; //2
   5'h03:
    disp_reg <= 8'hb0; //3
   5'h04:
    disp_reg <= 8'h99; //4
   5'h05:
    disp_reg <= 8'h92; //5
   5'h06:
    disp_reg <= 8'h82; //6
   5'h07:
    disp_reg <= 8'hf8; //7
   5'h08:
    disp_reg <= 8'h80; //8
   5'h09:
    disp_reg <= 8'h90; //9
   5'h0a:
    disp_reg <= 8'h88; //a
   5'h0b:
    disp_reg <= 8'h83; //b
   5'h0c:
    disp_reg <= 8'hc6; //c
   5'h0d:
    disp_reg <= 8'ha1; //d
   5'h0e:
    disp_reg <= 8'h86; //e
   5'h0f:
    disp_reg <= 8'h8e; //f
   5'h10:
    disp_reg <= 8'hbf; //-
   5'h11:
    disp_reg <= 8'h7f; //.
   default:
    disp_reg <= 8'hff; //不显示
  endcase
 end
 
endmodule


高工
2012-11-30 11:37:39     打赏
63楼

21、模块例化三:LCD1602模块——12.11.30
row1_val[127..0]:数据输入,16个字符;
chanle:0-第一行;1-第二行;
注意:这个模块值时候调用,不能单独建立工程,FPGA没那么多3.3V的IO口啊


verilog程序:

module lcd1602_interface
(
 input clk,
 input rst_n,
 input chanle,
 input[127:0] row1_val,
 output lcd_en,  // lcd enable
 output reg lcd_rs,  // record,statement
 output lcd_rw,
 output reg[7:0] lcd_data

);
// reg [127:0] row1_val="Hello!I'm Anmko.";
 
 assign lcd_rw = 1'b0;
                
 reg [15:0] cnt;
 always @ (posedge clk or negedge rst_n)
 begin
  if(!rst_n)
   cnt <= 0;
  else
   cnt <= cnt + 1'b1; 
 end
 assign lcd_en = cnt[15]; //lcd enable,keep same time; >1000ns                       
 
 parameter IDLE         = 8'h00;
 // Initialization. write instructions  
 parameter DISP_SET     = 8'h01;         // entry mode set
 parameter DISP_OFF     = 8'h03;         // display off
 parameter CLR_SCR      = 8'h02;         // clean display
 parameter CURSOR_SET1  = 8'h06;         // display shift set
 parameter CURSOR_SET2  = 8'h07;         // display on and cursor set
 // display the 1st row
 parameter ROW1_ADDR    = 8'h05;         // write the start address of the 1st row
 parameter ROW1_0       = 8'h04;
 parameter ROW1_1       = 8'h0C;
 parameter ROW1_2       = 8'h0D;
 parameter ROW1_3       = 8'h0F;
 parameter ROW1_4       = 8'h0E;
 parameter ROW1_5       = 8'h0A;
 parameter ROW1_6       = 8'h0B;
 parameter ROW1_7       = 8'h09;
 parameter ROW1_8       = 8'h08;
 parameter ROW1_9       = 8'h18;
 parameter ROW1_A       = 8'h19;
 parameter ROW1_B       = 8'h1B;
 parameter ROW1_C       = 8'h1A;
 parameter ROW1_D       = 8'h1E;
 parameter ROW1_E       = 8'h1F;
 parameter ROW1_F       = 8'h1D;
 // display the 2nd row
 parameter ROW2_ADDR    = 8'h1C;         // write the start address of the 2nd row
 parameter ROW2_0       = 8'h14;
 parameter ROW2_1       = 8'h15;
 parameter ROW2_2       = 8'h17;
 parameter ROW2_3       = 8'h16;
 parameter ROW2_4       = 8'h12;
 parameter ROW2_5       = 8'h13;
 parameter ROW2_6       = 8'h11;
 parameter ROW2_7       = 8'h10;
 parameter ROW2_8       = 8'h30;
 parameter ROW2_9       = 8'h31;
 parameter ROW2_A       = 8'h33;
 parameter ROW2_B       = 8'h32;
 parameter ROW2_C       = 8'h36;
 parameter ROW2_D       = 8'h37;
 parameter ROW2_E       = 8'h35;
 parameter ROW2_F       = 8'h34;

 reg [5:0] current_state, next_state;    // current state, next state

 // FSM: always1
 always @ (posedge lcd_en or negedge rst_n) begin
  if(!rst_n)  current_state <= IDLE;
  else        current_state <= next_state;
 end

 // FSM: always2
 always begin
  case(current_state)
   IDLE        : next_state = DISP_SET;
   // Initialization. write instructions  
   DISP_SET    : next_state = DISP_OFF;
   DISP_OFF    : next_state = CLR_SCR;
   CLR_SCR     : next_state = CURSOR_SET1;
   CURSOR_SET1 : next_state = CURSOR_SET2;
   CURSOR_SET2 : begin
         if(!chanle)
         next_state = ROW1_ADDR;
         else
         next_state = ROW2_ADDR;
          end
   // display the 1st row
   ROW1_ADDR   : next_state = ROW1_0;
   ROW1_0      : next_state = ROW1_1;
   ROW1_1      : next_state = ROW1_2;
   ROW1_2      : next_state = ROW1_3;
   ROW1_3      : next_state = ROW1_4;
   ROW1_4      : next_state = ROW1_5;
   ROW1_5      : next_state = ROW1_6;
   ROW1_6      : next_state = ROW1_7;
   ROW1_7      : next_state = ROW1_8;
   ROW1_8      : next_state = ROW1_9;
   ROW1_9      : next_state = ROW1_A;
   ROW1_A      : next_state = ROW1_B;
   ROW1_B      : next_state = ROW1_C;
   ROW1_C      : next_state = ROW1_D;
   ROW1_D      : next_state = ROW1_E;
   ROW1_E      : next_state = ROW1_F;
   ROW1_F      : begin
         if(!chanle)
         next_state = ROW1_ADDR;
         else
         next_state = ROW2_ADDR;
         end
   // display the 2nd row
   ROW2_ADDR   : next_state = ROW2_0;
   ROW2_0      : next_state = ROW2_1;
   ROW2_1      : next_state = ROW2_2;
   ROW2_2      : next_state = ROW2_3;
   ROW2_3      : next_state = ROW2_4;
   ROW2_4      : next_state = ROW2_5;
   ROW2_5      : next_state = ROW2_6;
   ROW2_6      : next_state = ROW2_7;
   ROW2_7      : next_state = ROW2_8;
   ROW2_8      : next_state = ROW2_9;
   ROW2_9      : next_state = ROW2_A;
   ROW2_A      : next_state = ROW2_B;
   ROW2_B      : next_state = ROW2_C;
   ROW2_C      : next_state = ROW2_D;
   ROW2_D      : next_state = ROW2_E;
   ROW2_E      : next_state = ROW2_F;
   ROW2_F      : begin
         if(!chanle)
         next_state = ROW1_ADDR;
         else
         next_state = ROW2_ADDR;
         end
   default     : next_state = IDLE ;
  endcase
 end

 // FSM: always3
 always @ (posedge lcd_en or negedge rst_n) begin
  if(!rst_n)
   begin
   lcd_rs   <= 0;
   lcd_data <= 8'hxx;
   end
  else
   begin
   // write lcd_rs
   case(next_state)     
    IDLE        : lcd_rs <= 0;
    // Initialization. write instructions
    DISP_SET    : lcd_rs <= 0;
    DISP_OFF    : lcd_rs <= 0;
    CLR_SCR     : lcd_rs <= 0;
    CURSOR_SET1 : lcd_rs <= 0;
    CURSOR_SET2 : lcd_rs <= 0;
    // write data and display the 1st row
    ROW1_ADDR   : lcd_rs <= 0;
    ROW1_0      : lcd_rs <= 1;
    ROW1_1      : lcd_rs <= 1;
    ROW1_2      : lcd_rs <= 1;
    ROW1_3      : lcd_rs <= 1;
    ROW1_4      : lcd_rs <= 1;
    ROW1_5      : lcd_rs <= 1;
    ROW1_6      : lcd_rs <= 1;
    ROW1_7      : lcd_rs <= 1;
    ROW1_8      : lcd_rs <= 1;
    ROW1_9      : lcd_rs <= 1;
    ROW1_A      : lcd_rs <= 1;
    ROW1_B      : lcd_rs <= 1;
    ROW1_C      : lcd_rs <= 1;
    ROW1_D      : lcd_rs <= 1;
    ROW1_E      : lcd_rs <= 1;
    ROW1_F      : lcd_rs <= 1;
    // write data, and display the 2nd row
    ROW2_ADDR   : lcd_rs <= 0;
    ROW2_0      : lcd_rs <= 1;
    ROW2_1      : lcd_rs <= 1;
    ROW2_2      : lcd_rs <= 1;
    ROW2_3      : lcd_rs <= 1;
    ROW2_4      : lcd_rs <= 1;
    ROW2_5      : lcd_rs <= 1;
    ROW2_6      : lcd_rs <= 1;
    ROW2_7      : lcd_rs <= 1;
    ROW2_8      : lcd_rs <= 1;
    ROW2_9      : lcd_rs <= 1;
    ROW2_A      : lcd_rs <= 1;
    ROW2_B      : lcd_rs <= 1;
    ROW2_C      : lcd_rs <= 1;
    ROW2_D      : lcd_rs <= 1;
    ROW2_E      : lcd_rs <= 1;
    ROW2_F      : lcd_rs <= 1;
   endcase   
  
   // write lcd_data
   case(next_state)
    IDLE        : lcd_data <= 8'hxx;
    // Initialization. write instructions
    DISP_SET    : lcd_data <= 8'h38;
    DISP_OFF    : lcd_data <= 8'h08;
    CLR_SCR     : lcd_data <= 8'h01;
    CURSOR_SET1 : lcd_data <= 8'h06;
    CURSOR_SET2 : lcd_data <= 8'h0C;
    // write date, and display the 1st row
    ROW1_ADDR   : lcd_data <= 8'h80;
    ROW1_0      : lcd_data <= row1_val[127:120];
    ROW1_1      : lcd_data <= row1_val[119:112];
    ROW1_2      : lcd_data <= row1_val[111:104];
    ROW1_3      : lcd_data <= row1_val[103: 96];
    ROW1_4      : lcd_data <= row1_val[ 95: 88];
    ROW1_5      : lcd_data <= row1_val[ 87: 80];
    ROW1_6      : lcd_data <= row1_val[ 79: 72];
    ROW1_7      : lcd_data <= row1_val[ 71: 64];
    ROW1_8      : lcd_data <= row1_val[ 63: 56];
    ROW1_9      : lcd_data <= row1_val[ 55: 48];
    ROW1_A      : lcd_data <= row1_val[ 47: 40];
    ROW1_B      : lcd_data <= row1_val[ 39: 32];
    ROW1_C      : lcd_data <= row1_val[ 31: 24];
    ROW1_D      : lcd_data <= row1_val[ 23: 16];
    ROW1_E      : lcd_data <= row1_val[ 15:  8];
    ROW1_F      : lcd_data <= row1_val[  7:  0];
    // write date, and display the 2nd row
    ROW2_ADDR   : lcd_data <= 8'hC0;
    ROW2_0      : lcd_data <= row1_val[127:120];
    ROW2_1      : lcd_data <= row1_val[119:112];
    ROW2_2      : lcd_data <= row1_val[111:104];
    ROW2_3      : lcd_data <= row1_val[103: 96];
    ROW2_4      : lcd_data <= row1_val[ 95: 88];
    ROW2_5      : lcd_data <= row1_val[ 87: 80];
    ROW2_6      : lcd_data <= row1_val[ 79: 72];
    ROW2_7      : lcd_data <= row1_val[ 71: 64];
    ROW2_8      : lcd_data <= row1_val[ 63: 56];
    ROW2_9      : lcd_data <= row1_val[ 55: 48];
    ROW2_A      : lcd_data <= row1_val[ 47: 40];
    ROW2_B      : lcd_data <= row1_val[ 39: 32];
    ROW2_C      : lcd_data <= row1_val[ 31: 24];
    ROW2_D      : lcd_data <= row1_val[ 23: 16];
    ROW2_E      : lcd_data <= row1_val[ 15:  8];
    ROW2_F      : lcd_data <= row1_val[  7:  0];
   endcase 
  end
 end
 
endmodule


高工
2012-12-04 17:19:22     打赏
64楼
22、逻辑分析仪一:VGA显示驱动

想捣鼓个逻辑分析仪,VGA做显示。。。。
VGA常见刷新时序表:


                                                                                    水平扫描时序

                                                                                   垂直扫描时序

根据上面的水平和垂直扫描时序可以分析800x600模式,DIY FPGA核心板上的有源晶振频率为50MHZ。为了显示器显示效果好,采用刷新频率为72Hz。

 

以下以系统时钟频率为50MHZ,显示器显示800x600模式为例分析水平扫描和垂直扫描时序:系统时钟周期为1/50MHz=20ns水平扫描Horizonal(Line)。




A:水平(行)周期为1040个像素(Pix),时间为1040x20ns=20.8us;

B:同步脉冲为120像素(Pix);

C:后沿为61个像素(Pix);

D:有效时间为806个像素(Pix);

E:前沿为53个像素。



O:水平(行)周期为666个像素(Pix);

P:同步脉冲为6像素(Pix);

Q:后沿为21个像素(Pix);

R:有效时间为604个像素(Pix);

S:前沿为35个像素。





//----------------水平扫描参数设置--------------------
 parameter LinePeriod = 12'd1040,
 parameter H_SyncPulse = 10'd120,
 parameter H_BackPorch = 10'd61,
 parameter H_ActivePix = 10'd806,
 
//----------------垂直扫描参数设置--------------------
 parameter FramePeriod = 12'd666,
 parameter V_SyncPulse = 10'd6,
 parameter V_BackPorch = 10'd21,
 parameter V_ActivePix = 10'd604,

//-----------------水平扫描计数-----------------
 reg[11:0] X_cnt;
 always @(posedge clk or negedge rst) begin
  if(!rst)
   X_cnt <= 12'b1;
  else if(X_cnt == LinePeriod) X_cnt <= 12'b1;
  else X_cnt <= X_cnt + 1'b1;
 end
 
//-------------水平扫描信号HSYNC计产生-------------
 reg H_Sync_r;
 always @(posedge clk or negedge rst) begin
  if(!rst) H_Sync_r <= 1'b1;
  else if(X_cnt == 12'b1) H_Sync_r <= 1'b0;
  else if(X_cnt >= H_SyncPulse) H_Sync_r <= 1'b1;
 end
 assign H_Sync = H_Sync_r;
 
//-----------------垂直扫描计数-----------------
 reg[11:0] Y_cnt;
 always @(posedge clk or negedge rst) begin
  if(!rst) Y_cnt <= 12'b1;
  else if(Y_cnt == FramePeriod) Y_cnt <= 12'b1;
  else if(X_cnt == LinePeriod) Y_cnt <= Y_cnt + 1'b1;
 end
//-------------垂直扫描信号VSYNC计产生-------------
 reg V_Sync_r;
 always @(posedge clk or negedge rst) begin
  if(!rst) V_Sync_r <= 1'b1;
  else if(Y_cnt == 12'b1) V_Sync_r <= 1'b0;
  else if(Y_cnt >= V_SyncPulse) V_Sync_r <= 1'b1;
 end
 assign V_Sync = V_Sync_r;
 
//----------------有效显示区标志-------------------
 wire valid;
 assign valid = (X_cnt>=(H_SyncPulse+H_BackPorch))&&
                           (X_cnt<(H_SyncPulse+H_BackPorch+H_ActivePix))&&
                           (Y_cnt>=(V_SyncPulse+V_BackPorch))&&
                           (Y_cnt<(V_SyncPulse+V_BackPorch+V_ActivePix));

//--------------------数据写入-----------------------
 wire[9:0] x_dis;
 wire[9:0] y_dis;
 assign x_dis = X_cnt - (H_SyncPulse + H_BackPorch + 1'b1);
 assign y_dis = Y_cnt - (V_SyncPulse + V_BackPorch + 1'b1);
 
 reg [7:0] vga_RGB;
 always @(posedge clk or negedge rst) begin
  if(!rst) vga_RGB <= 8'b0;
  else if(valid)
   begin
   case(x_dis)
    10'd0: begin
     if(y_dis >= 10'd0 && y_dis < 10'd60) vga_RGB <= 8'd0;
     else if(y_dis >= 10'd60 && y_dis < 10'd120) vga_RGB <= 8'd25;
     else if(y_dis >= 10'd120 && y_dis < 10'd180) vga_RGB <= 8'd50;
     else if(y_dis >= 10'd180 && y_dis < 10'd240) vga_RGB <= 8'd75;
     else if(y_dis >= 10'd240 && y_dis < 10'd300) vga_RGB <= 8'd100;
     else if(y_dis >= 10'd300 && y_dis < 10'd360) vga_RGB <= 8'd125;
     else if(y_dis >= 10'd360 && y_dis < 10'd420) vga_RGB <= 8'd150;
     else if(y_dis >= 10'd420 && y_dis < 10'd480) vga_RGB <= 8'd175;
     else if(y_dis >= 10'd480 && y_dis < 10'd540) vga_RGB <= 8'd200;
     else if(y_dis >= 10'd540 && y_dis < 10'd600) vga_RGB <= 8'd225;
     else vga_RGB <= 8'd240;
     end
    10'd80,10'd160,10'd240,10'd320,10'd400,10'd480,10'd560,10'd640,10'd720: vga_RGB <= vga_RGB+1'b1;
    default: ;
   endcase
  end
 end
 assign VGA_R = vga_RGB[7:5];
 assign VGA_G = vga_RGB[4:2];
 assign VGA_B = vga_RGB[1:0];


效果图:

高工
2012-12-05 21:46:37     打赏
65楼
23、VGA显示256色的图片
        本来是显示字符的:CHA(通道A)


        突然又觉得好歹也是VGA啊,你不能把这么个大液晶屏当12806使吧,,怎么着都得显示个图片出来吧~~~~说干就干

拿张PLMM的壁纸


        在网上下了个图片转MIF的软件,坑爹的,没有转256色格式的功能,只有256灰度的,好吧,黑白电视机的画面还是蛮怀念的,计算了一下,EP2C5有36(好像是36,反正不会多于36)个M4K,4*1024*36bit,真可怜,存储一个满屏的画面都不行,最后敲定128*100像素的照片,直接转成MIF,效果如下,,真坑爹,,,


金泫雅妹纸,,你怎么了,你百变大咖啊!你这让那个我情何以堪!!!哎~~~~~~~估计是现在的液晶显示器不只是灰度显示了,于是只好用其他的软件先把图片转换成.c,然后在把它编辑成.hex的,,于是真的就显示出来了。。。


实在是小,,,进一点


SOF,POF文件下载:
——回复可见内容——

verilog在楼下的楼下

高工
2012-12-06 09:54:03     打赏
66楼

verilog程序:
module vga
#(
//------------水平扫描常量--------------
 parameter LinePeriod = 12'd1040,
 parameter H_SyncPulse = 10'd120,
 parameter H_BackPorch = 10'd61,
 parameter H_ActivePix = 10'd806,
//------------垂直扫描常量-------------- 
 parameter FramePeriod = 12'd666,
 parameter V_SyncPulse = 10'd6,
 parameter V_BackPorch = 10'd21,
 parameter V_ActivePix = 10'd604
)

(
 input clk,
 input rst,
 output H_Sync,
 output V_Sync,
 output [2:0] VGA_R,
 output [2:0] VGA_G,
 output [1:0] VGA_B
);

//-----------------水平扫描计数-----------------
 reg[11:0] X_cnt;
 always @(posedge clk or negedge rst) begin
  if(!rst)
   X_cnt <= 12'b1;
  else if(X_cnt == LinePeriod) X_cnt <= 12'b1;
  else X_cnt <= X_cnt + 1'b1;
 end
 
//-------------水平扫描信号HSYNC计产生-------------
 reg H_Sync_r;
 always @(posedge clk or negedge rst) begin
  if(!rst) H_Sync_r <= 1'b1;
  else if(X_cnt == 12'b1) H_Sync_r <= 1'b0;
  else if(X_cnt >= H_SyncPulse) H_Sync_r <= 1'b1;
 end
 assign H_Sync = H_Sync_r;
 
//-----------------垂直扫描计数-----------------
 reg[11:0] Y_cnt;
 always @(posedge clk or negedge rst) begin
  if(!rst) Y_cnt <= 12'b1;
  else if(Y_cnt == FramePeriod) Y_cnt <= 12'b1;
  else if(X_cnt == LinePeriod) Y_cnt <= Y_cnt + 1'b1;  //水平扫描完后垂直
 end
//-------------垂直扫描信号VSYNC计产生-------------
 reg V_Sync_r;
 always @(posedge clk or negedge rst) begin
  if(!rst) V_Sync_r <= 1'b1;
  else if(Y_cnt == 12'b1) V_Sync_r <= 1'b0;
  else if(Y_cnt >= V_SyncPulse) V_Sync_r <= 1'b1;
 end
 assign V_Sync = V_Sync_r;
 
//----------------有效显示区标志-------------------
 wire valid;
 assign valid = (X_cnt>=(H_SyncPulse+H_BackPorch))&&(X_cnt<(H_SyncPulse+H_BackPorch+H_ActivePix))&&
      (Y_cnt>=(V_SyncPulse+V_BackPorch))&&(Y_cnt<(V_SyncPulse+V_BackPorch+V_ActivePix));

 wire[9:0] x_dis;
 wire[9:0] y_dis;
 assign x_dis = X_cnt - (H_SyncPulse + H_BackPorch );
 assign y_dis = Y_cnt - (V_SyncPulse + V_BackPorch );
 
/**************VGA色彩信号产生***************
 RGB = 000   黑色 RGB = 100 红色
  = 001   蓝色  = 101 紫色
  = 010 绿色  = 110 黄色
  = 011 青色  = 111 白色
*******************************************/ 
 
 reg[15:0] rom_addr;  //ROM地址
 wire[7:0] rom_data;  //ROM数据
 rom PIC_rom
 (
  .address(rom_addr),
  .clock(clk),
  .q(rom_data)
 );
 
 reg [7:0] vga_RGB;
 always @(posedge clk or negedge rst) begin
  if(!rst) 
   begin
   vga_RGB <= 8'b0;
   rom_addr <= 16'b0;
   end
  else if(valid)
   begin
   if((x_dis >= 10'd336 && x_dis < 10'd464) && (y_dis >= 10'd250 && y_dis < 10'd350))
    begin
    vga_RGB <= rom_data;
    rom_addr <= rom_addr + 1'b1;
    if(rom_addr == 12799) rom_addr <= 16'b0;    
    end
   else vga_RGB <= 8'b000_001_11;
   end
  else vga_RGB <= 8'b0;
 end

 assign VGA_R = vga_RGB[7:5];
 assign VGA_G = vga_RGB[4:2];
 assign VGA_B = vga_RGB[1:0];

endmodule

 


高工
2012-12-06 19:38:38     打赏
67楼
你用这个吧,这个是改进之后的http://forum.eepw.com.cn/thread/221172/11#110

高工
2012-12-13 16:23:03     打赏
68楼
24、IP核——PLL锁相环
(首先做这个实验你焊接的晶振应该是Y2)
        Cyclone II器件中最多有四个锁相环Cyclone II 的PLL功能强大,可以用作零延时缓存器、频率合成器、抖动衰减器、一个低斜扇出缓冲器,支持时钟转换、可编程切换、可编程占空比,减少时钟延时、时钟偏斜。
                                                     器件中的可用PLLs个数



                                                         Cyclone II器件中PLL的位置

        EP2C5和EP2C8只有8个全局时钟和两个PLL,如上图红色所标出的。

                                            PLL的参考时钟


       在Cyclone II器件中,多达四个管脚可以驱动PLL,PLL具有内部延时块可以补偿从输入到PLL的延时。每个PLL的输入可以由四个单端输入和两个差分输入时钟输入来供给。
下面是PLL核添加过程:














到这一步,PLL算是添加完了,c0输出50Mhz、c1输出100Mhz、c2输出150Mhz的时钟信号。接下来是调用了。

verilog程序:

module pll_led(clk,clk2, rst, led);

 input clk;
 input clk2;
 input rst;

 output [4:0] led;

 wire clkdiv0;
 wire clkdiv1;
 wire clkdiv2;
 pll_ctrl  PLL_DIV
 (
  .inclk0(clk),
  .c0(clkdiv0),
  .c1(clkdiv1),
  .c2(clkdiv2)
 );

 wire clkdiv3;
 wire clkdiv4;
 wire clkdiv5;
 pll_ctrl2  PLL_DIV2
 (
  .inclk0(clk2),
  .c0(clkdiv3),
  .c1(clkdiv4),
  .c2(clkdiv5)
 );
 
 reg [25:0] cnt0;
 reg led_r0;
 always @(posedge clk or negedge rst) begin
  if(!rst) cnt0 <= 26'b0;
  else if(cnt0 == 26'd25_000_000)
   begin
   led_r0 <= ~led_r0;
   cnt0 <= 26'b0;
   end
  else cnt0 <= cnt0 + 1'b1;
 end
 assign led[0] = led_r0;
 
 reg [25:0] cnt1;
 reg led_r1;
 always @(posedge clkdiv0 or negedge rst) begin
  if(!rst) cnt1 <= 26'b0;
  else if(cnt1 == 26'd25_000_000)
   begin
   led_r1 <= ~led_r1;
   cnt1 <= 26'b0;
   end
  else cnt1 <= cnt1 + 1'b1;
 end
 assign led[1] = led_r1;
 
 reg [25:0] cnt2;
 reg led_r2;
 always @(posedge clkdiv1 or negedge rst) begin
  if(!rst) cnt2 <= 26'b0;
  else if(cnt2 == 26'd25_000_000)
   begin
   led_r2 <= ~led_r2;
   cnt2 <= 26'b0;
   end
  else cnt2 <= cnt2 + 1'b1;
 end
 assign led[2] = led_r2;
 
 reg [25:0] cnt3;
 reg led_r3;
 always @(posedge clkdiv2 or negedge rst) begin
  if(!rst) cnt3 <= 26'b0;
  else if(cnt3 == 26'd25_000_000)
   begin
   led_r3 <= ~led_r3;
   cnt3 <= 26'b0;
   end
  else cnt3 <= cnt3 + 1'b1;
 end
 assign led[3] = led_r3;
 
 reg [25:0] cnt4;
 reg led_r4;
 always @(posedge clkdiv3 or negedge rst) begin
  if(!rst) cnt4 <= 26'b0;
  else if(cnt4 == 26'd25_000_000)
   begin
   led_r4 <= ~led_r4;
   cnt4 <= 26'b0;
   end
  else cnt4 <= cnt4 + 1'b1;
 end
 assign led[4] = led_r4;
endmodule


观察LED灯的闪烁频率。
说明:调用了两个PLL,我们的板子上的晶振输入FPGA的引脚是CLK2(Y2)和CLK7(Y1),是要中只有接入Y2晶振的PLL模块才有效。你可以分配引脚试试。

高工
2012-12-13 19:04:10     打赏
69楼
PLL有verilog的文本文件的啊,你可以看看那

高工
2012-12-14 08:45:46     打赏
70楼
25、IP核——ROM的使用
        51FPGA的教程中12864实验中使用到了rom,但没介绍怎么调用rom。我在VGA的图片的256色显示中也使用了rom,在这里给大伙介绍一下。


        使用IP核使用引导。


         有两块ROM,选择其一。如上图所示。



        注意红色标识处,在这里填好你的位宽和字数,一定要与你的.mif(.hex)文件的位宽和字数一致。单色显示的位宽应该是1,我256色的VGA,所以填的是8。图左下角是你能用的空间,M4K=1024*4bit,要确保你使用的空间不溢出,否则编译报错。如上图所示。



在这里添加已编译好的mif文件,51fpga介绍了hex的制作过程。如上图所示。


到这里就finish了,

在你的工程文件下会自动生成一个rom.v(名字你自己定义)的文件如下图所示



在top层中调用:

详细的见:VGA的256色显示的源代码http://forum.eepw.com.cn/thread/221172/16#155

共76条 7/8 |‹ 3 4 5 6 7 8 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]