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

共223条 15/23 |‹ 13 14 15 16 17 18 ›| 跳转至
助工
2012-11-11 19:43:47     打赏
141楼
高手!!!学习!!

助工
2012-11-25 21:55:14     打赏
142楼
回复看看好东西,谢谢楼主!

院士
2012-11-25 21:59:45     打赏
143楼
状态机啊~~
好高级啊~~

高工
2012-11-25 23:17:37     打赏
144楼

呵呵,,小见解。。。


高工
2012-11-25 23:18:11     打赏
145楼

加油,论坛靠你我他


高工
2012-11-29 08:57:37     打赏
146楼

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     打赏
147楼

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-29 14:15:20     打赏
148楼
顶一下。谢谢楼主

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

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     打赏
150楼
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];


效果图:

共223条 15/23 |‹ 13 14 15 16 17 18 ›| 跳转至

回复

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