这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » sdjntl的进程贴

共16条 2/2 1 2 跳转至
专家
2012-12-28 13:37:10     打赏
11楼

 

 

10、 LCD24064的显示

 


 

1、      实验内容
LCD24064的显示

2、      实验代码
`define DEBUG

  `ifdef  DEBUG
  `define COUNT  17'd5
`else
  `define COUNT  17'd10000  
`endif

 

module lcd12864(
  CLK_50MHZ,
  RESET_N,
  LCD_RS,
  LCD_RW,
  LCD_E,
  LCD_D,
  RED
 ); 
output  RED;
input CLK_50MHZ;   //系统时钟
input  RESET_N;  //复位信号
output  [7:0] LCD_D;  //LCD数据总线
output  LCD_RS;    //1:数据模式;0:指令模式
output  LCD_RW;   //1:读操作;0:写操作,
output  LCD_E;    //使能信号,写操作时在下降沿将数据送出;读操作时保持高电平
//output rst;//lcd复位信号

//内部寄存器
reg  [7:0] LCD_D;
reg  LCD_RS;  

//状态定义
parameter  FUNCTION  = 4'h0;
parameter  DISPLAY  = 4'h1;
parameter  MODE   = 4'h2;
parameter  CLEAR  = 4'h3;
parameter  WRITERAM0 = 4'h4;
parameter  WRITERAM1 = 4'h5;
parameter  WRITERAM2 = 4'h6;
parameter  WRITERAM3 = 4'h7;
parameter  SETDDRAM0 = 4'h8;
parameter  SETDDRAM1 = 4'h9;
parameter  SETDDRAM2 = 4'ha;
parameter  SETDDRAM3 = 4'hb;
parameter  SHIFT  = 4'hc;


function [7:0] ddram;          
  input [5:0] n;
  begin
   case(n)
   //发送第1行数据
   6'b000_000:ddram = "W";
   6'b000_001:ddram = "e"; 
   6'b000_010:ddram = "l";
   6'b000_011:ddram = "c"; 
   6'b000_100:ddram = "o"; 
   6'b000_101:ddram = "m"; 
   6'b000_110:ddram = "e";     
   6'b000_111:ddram = " "; 
   6'b001_000:ddram = "F"; 
   6'b001_001:ddram = "P"; 
   6'b001_010:ddram = "G"; 
   6'b001_011:ddram = "A"; 
   6'b001_100:ddram = 8'D0; 
           //发送第2行数据
   6'b001_101:ddram = "s";
   6'b001_110:ddram = "d";
   6'b001_111:ddram = "j";
   6'b010_000:ddram = "n";
   6'b010_001:ddram = "t";
   6'b010_010:ddram = "l";
   6'b010_011:ddram = 8'D0; 
    //发送第3行数据
   6'b010_100:ddram = 8'hB5;  
   6'b010_101:ddram = 8'hE7;
   6'b010_110:ddram = 8'hD7; 
   6'b010_111:ddram = 8'hD3; 
   6'b011_000:ddram = 8'hB2; 
   6'b011_001:ddram = 8'hFA; 
   6'b011_010:ddram = 8'hC6;  
   6'b011_011:ddram = 8'hB7; 
   6'b011_100:ddram = 8'hCA; 
   6'b011_101:ddram = 8'hC0; 
   6'b011_110:ddram = 8'hBD;  
   6'b011_111:ddram = 8'hE7; 
   6'b100_000:ddram = 8'hB7; 
   6'b100_001:ddram = 8'D0; 
    //发送第4行数据
   6'b100_010:ddram = "w";  
   6'b100_011:ddram = "w";
   6'b100_100:ddram = "w"; 
   6'b100_101:ddram = "."; 
   6'b100_110:ddram = "e"; 
   6'b100_111:ddram = "e"; 
   6'b101_000:ddram = "p";  
   6'b101_001:ddram = "w"; 
   6'b101_010:ddram = "."; 
   6'b101_011:ddram = "c"; 
   6'b101_100:ddram = "o";  
   6'b101_101:ddram = "m";
   6'b101_110:ddram = "."; 
   6'b101_111:ddram = "c"; 
   6'b110_000:ddram = "n";  
   6'b110_001:ddram = 8'D0;       
   endcase
  end
 endfunction
//*************************代码开始******************************
//工作灯指示
reg  [25:0] led_cnt;
always @(posedge CLK_50MHZ or negedge RESET_N)        
begin
 if(!RESET_N)
  led_cnt <= 0; 
 else
  led_cnt <= led_cnt+1'b1;  
end

assign RED = led_cnt[25];

//时钟分频
wire clkr;
reg  [16:0] counter;
always @(posedge CLK_50MHZ or negedge RESET_N)        
begin
 if(!RESET_N)
  begin
   counter <= 17'd0; 
  end
 else if(counter == `COUNT)
  counter <= 17'd0;
 else
  counter <= counter+1'b1;  
end
assign clkr = (counter == `COUNT) ;

reg   e;
reg  [7:0] current = 0;
reg  [1:0] cnt;
reg     [5:0] address = 0;
always @(posedge clkr)
begin
  case(current)
    FUNCTION:   begin  LCD_RS <= 0; LCD_D <= 8'h30; current <= DISPLAY;   end  //初始化 --基本指令集
    DISPLAY:    begin  LCD_RS <= 0; LCD_D <= 8'h0c; current <= MODE;      end //开整体显示 游标关
    MODE:       begin  LCD_RS <= 0; LCD_D <= 8'h06; current <= CLEAR;     end //光标右移  DDRAM 地址计数加1 画面整体不移动
    CLEAR:      begin  LCD_RS <= 0; LCD_D <= 8'h01; current <= SETDDRAM0; end //清屏   
    SETDDRAM0:  begin  LCD_RS <= 0; LCD_D <= 8'h80; current <= WRITERAM0; end  //设置坐标位置 (地址设置为第1行)  设定DDRAM地址80  
    WRITERAM0:
  begin
   if(ddram(address))
    begin
        LCD_RS <= 1;
     LCD_D <= ddram(address);
     address <= address + 1'b1;
    end
   else
    begin
        LCD_RS <= 0;
        address <= address + 1'b1;
     current <= SETDDRAM1;
    end
  end 
     SETDDRAM1:   begin  LCD_RS <= 0; LCD_D <= 8'h90; current <= WRITERAM1; end  //address <= 0;设置坐标位置 (地址设置为第3行)
     WRITERAM1:
  begin
   if(ddram(address))
    begin
        LCD_RS <= 1;
     LCD_D <= ddram(address);
     address <= address + 1'b1;
    end
   else
    begin
        LCD_RS <= 0;
        address <= address + 1'b1;
     current <= SETDDRAM2;
    end
  end
      SETDDRAM2:   begin  LCD_RS<=0; LCD_D<=8'h88; current<=WRITERAM2; end  //设置坐标位置 (地址设置为第3行)
      WRITERAM2:
  begin   
   if(ddram(address))
    begin
        LCD_RS <= 1;
     LCD_D <= ddram(address);
     address <= address + 1'b1;
    end
   else
    begin
        LCD_RS <= 0;
        address <= address + 1'b1;
     current <= SETDDRAM3;
    end
  end
    SETDDRAM3:   begin  LCD_RS <= 0; LCD_D <= 8'h98; current <= WRITERAM3; end  //address <= 0;设置坐标位置 (地址设置为第3行)
    WRITERAM3:
  begin   
   if(ddram(address))
    begin
        LCD_RS <= 1;
     LCD_D <= ddram(address);
     address <= address + 1'b1;
    end
   else
    begin
        LCD_RS <= 0;
        address <= address + 1'b1;
     current <= SHIFT;
    end
  end
       SHIFT:   begin LCD_RS <= 0;  LCD_D <= 8'h00;                    //这段保证前段显示部分至少执行一遍
              address <= 0;                                   //然后把液晶的En脚拉高,完成一次读写过程
              if(cnt!=2'h2) 
                  begin 
                       e <= 0;
                       current <= FUNCTION;
                       cnt <= cnt+1; 
                  end 
                   else 
                     begin
                        current <= FUNCTION;
                        e <= 1;
                        cnt <= 0;
                    end   
              end
      default:   current <= SHIFT;
    endcase
end

assign LCD_E = clkr | e;//对LCD始终为写操作
 
assign LCD_RW = 0; //对LCD始终为写操作

//assign rst=RESET_N;

endmodule 

3、      测试仿真

     
// Verilog Test Bench template for design : lcd12864
//
// Simulation tool : ModelSim-Altera (Verilog)
//

`timescale 1 ps/ 1 ps
module lcd12864_vlg_tst();
// constants                                          
// general purpose registers
//reg eachvec;
// test vector input registers
reg CLK_50MHZ;
reg RESET_N;
// wires                                              
wire [7:0] LCD_D;
wire LCD_E;
wire LCD_RS;
wire LCD_RW;

// assign statements (if any)                         
lcd12864 i1 (
// port map - connection between master ports and signals/registers  
 .CLK_50MHZ(CLK_50MHZ),
 .LCD_D(LCD_D),
 .LCD_E(LCD_E),
 .LCD_RS(LCD_RS),
 .LCD_RW(LCD_RW),
 .RESET_N(RESET_N)
);
initial                                               
begin 
   CLK_50MHZ = 0;                                           
    RESET_N = 0;
    #20
     RESET_N = 1;                          
end 

initial                                               
begin                                                 
  forever
 #20
 CLK_50MHZ =~CLK_50MHZ; 
end  

                                                 
endmodule

 

4、      测试下载文件

lcd12864.rar

 

 


专家
2012-12-28 13:37:20     打赏
12楼

11、串口收发数据

1、      实验内容
   串口收发数据
2、      实验代码
`define DEBUG

`ifdef DEBUG
`define  BPS_PARA  12 //波特率为9600时的分频计数值
`define  BPS_PARA_2  6 //波特率为9600时的分频计数值的一半,用于数据采样ifdef DEBUG

`else
`define  BPS_PARA  5207 //波特率为9600时的分频计数值
`define  BPS_PARA_2  2603 //波特率为9600时的分频计数值的一半,用于数据采样
`endif


module uart(
    CLK_50MHZ,RESET_N,
    UART_RXD,UART_TXD,
    GREEN,RED,YELLOW
    );

/*
parameter   bps9600  = 5207, //波特率为9600bps
     bps19200  = 2603, //波特率为19200bps
    bps38400  = 1301, //波特率为38400bps
    bps57600  = 867, //波特率为57600bps
    bps115200 = 433; //波特率为115200bps

parameter   bps9600_2  = 2603,
    bps19200_2 = 1301,
    bps38400_2 = 650,
    bps57600_2 = 433,
    bps115200_2 = 216; 
*/

 //以下波特率分频计数值可参照上面的参数进行更改
//`define  BPS_PARA  5207 //波特率为9600时的分频计数值
//`define  BPS_PARA_2  2603 //波特率为9600时的分频计数值的一半,用于数据采样

 

input  CLK_50MHZ;  //50MHz主时钟
input  RESET_N;  //低电平复位信号
input UART_RXD;  //RS232接收数据信号
output UART_TXD;  //RS232发送数据信号
output GREEN,RED,YELLOW;

reg GREEN,RED;
wire bps_start1,bps_start2; //接收到数据后,波特率时钟启动信号置位
wire clk_bps1,clk_bps2;  // clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点
wire[7:0] rx_data;   //接收数据寄存器,保存直至下一个数据来到
reg rx_int;        //接收数据中断信号,接收到数据期间始终为高电平


//----------------------------------------------------/work led/----------------------------------------------------
reg [25:0]  led_cnt;
always @ (posedge CLK_50MHZ or negedge RESET_N) begin
 if(!RESET_N) led_cnt <= 26'd0;
    else      led_cnt <= led_cnt + 1'b1;   
 end
 assign YELLOW = led_cnt[25];
 
//----------------------------------------------------/bps/----------------------------------------------------

wire  bps_start; //接收到数据后,波特率时钟启动信号置位
reg[12:0] cnt;  //分频计数
always @ (posedge CLK_50MHZ or negedge RESET_N)
 if(!RESET_N) cnt <= 13'd0;
 else if((cnt == `BPS_PARA) || !bps_start) cnt <= 13'd0; //波特率计数清零  5207
 else cnt <= cnt+1'b1;   //波特率时钟计数启动
 
reg clk_bps_r;  //波特率时钟寄存器
always @ (posedge CLK_50MHZ or negedge RESET_N)
 if(!RESET_N) clk_bps_r <= 1'b0;
 else if(cnt == `BPS_PARA_2) clk_bps_r <= 1'b1;// clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点
 else clk_bps_r <= 1'b0;
 
wire clk_bps; // clk_bps的高电平为接收或者发送数据位的中间采样点
assign clk_bps = clk_bps_r;

//----------------------------------------------------------/txd/----------------------------------------------------------

reg rx_int0,rx_int1,rx_int2; //rx_int信号寄存器,捕捉下降沿滤波用
wire neg_rx_int;    // rx_int下降沿标志位
//---------------------------------------------------------
always @ (posedge CLK_50MHZ or negedge RESET_N) begin
 if(!RESET_N) begin
   rx_int0 <= 1'b0;
   rx_int1 <= 1'b0;
   rx_int2 <= 1'b0;
  end
 else begin
   rx_int0 <= rx_int;
   rx_int1 <= rx_int0;
   rx_int2 <= rx_int1;
  end
end
assign neg_rx_int =  ~rx_int1 & rx_int2; //捕捉到下降沿后,neg_rx_int拉高保持一个主时钟周期

//---------------------------------------------------------
reg[7:0] tx_data; //待发送数据的寄存器
reg bps_start_r;
reg tx_en; //发送数据使能信号,高有效
reg[3:0] count;
//---------------------------------------------------------
always @ (posedge CLK_50MHZ or negedge RESET_N) begin
 if(!RESET_N) begin
   bps_start_r <= 1'bz;
   tx_en <= 1'b0;
   tx_data <= 8'd0;
  end
 else if(neg_rx_int) begin //接收数据完毕,准备把接收到的数据发回去
   bps_start_r <= 1'b1;
   tx_data <= rx_data; //把接收到的数据存入发送数据寄存器
   tx_en <= 1'b1;  //进入发送数据状态中
  end
 else if(count==4'd11) begin //数据发送完成,复位
   bps_start_r <= 1'b0;
   tx_en <= 1'b0;
  end
end

//assign bps_start = bps_start_r;

//---------------------------------------------------------
reg rs232_tx_r;

always @ (posedge CLK_50MHZ or negedge RESET_N) begin
 if(!RESET_N) begin
   count <= 4'd0;
   rs232_tx_r <= 1'b1;
   GREEN <= 1'b1;
  end
 else if(tx_en) begin
   if(clk_bps) begin
     count <= count+1'b1;
     GREEN <= ~GREEN;
     case (count)
      4'd0: rs232_tx_r <= 1'b0;  //发送起始位
      4'd1: rs232_tx_r <= tx_data[0]; //发送bit0
      4'd2: rs232_tx_r <= tx_data[1]; //发送bit1
      4'd3: rs232_tx_r <= tx_data[2]; //发送bit2
      4'd4: rs232_tx_r <= tx_data[3]; //发送bit3
      4'd5: rs232_tx_r <= tx_data[4]; //发送bit4
      4'd6: rs232_tx_r <= tx_data[5]; //发送bit5
      4'd7: rs232_tx_r <= tx_data[6]; //发送bit6
      4'd8: rs232_tx_r <= tx_data[7]; //发送bit7
      4'd9: rs232_tx_r <= 1'b1; //发送结束位
      4'd10: GREEN <= 1'b1;
       default: rs232_tx_r <= 1'b1;
      endcase
    end
   else if(count==4'd11) count <= 4'd0; //复位
  end
end

assign UART_TXD = rs232_tx_r;

//----------------------------------------------------------/rxd/----------------------------------------------------------
//----------------------------------------------------------------
reg rs232_rx0,rs232_rx1,rs232_rx2,rs232_rx3; //接收数据寄存器,滤波用
wire neg_rs232_rx; //表示数据线接收到下降沿

always @ (posedge CLK_50MHZ or negedge RESET_N) begin
 if(!RESET_N) begin
   rs232_rx0 <= 1'b0;
   rs232_rx1 <= 1'b0;
   rs232_rx2 <= 1'b0;
   rs232_rx3 <= 1'b0;
  end
 else begin
   rs232_rx0 <= UART_RXD;
   rs232_rx1 <= rs232_rx0;
   rs232_rx2 <= rs232_rx1;
   rs232_rx3 <= rs232_rx2;
  end
end
 //下面的下降沿检测可以滤掉<20ns-40ns的毛刺(包括高脉冲和低脉冲毛刺),
 //这里就是用资源换稳定(前提是我们对时间要求不是那么苛刻,因为输入信号打了好几拍)
 //(当然我们的有效低脉冲信号肯定是远远大于40ns的)
assign neg_rs232_rx = rs232_rx3 & rs232_rx2 & ~rs232_rx1 & ~rs232_rx0; //接收到下降沿后neg_rs232_rx置高一个时钟周期

//----------------------------------------------------------------
reg bps_start_rx_r;
reg[3:0] num; //移位次数

always @ (posedge CLK_50MHZ or negedge RESET_N)
 if(!RESET_N) begin
   bps_start_rx_r <= 1'bz;
   rx_int <= 1'b0;
  end
 else if(neg_rs232_rx) begin  //接收到串口接收线rs232_rx的下降沿标志信号
   bps_start_rx_r <= 1'b1; //启动串口准备数据接收
   rx_int <= 1'b1;   //接收数据中断信号使能
  end
 else if(num==4'd12) begin  //接收完有用数据信息
   bps_start_rx_r <= 1'b0; //数据接收完毕,释放波特率启动信号
   rx_int <= 1'b0;   //接收数据中断信号关闭
  end

assign bps_start = bps_start_rx_r|bps_start_r;

//----------------------------------------------------------------
reg[7:0] rx_data_r;  //串口接收数据寄存器,保存直至下一个数据来到
reg[7:0] rx_temp_data; //当前接收数据寄存器

always @ (posedge CLK_50MHZ or negedge RESET_N)
 if(!RESET_N) begin
   rx_temp_data <= 8'd0;
   num <= 4'd0;
   rx_data_r <= 8'd0;
   RED <= 1'b1;
  end
 else if(rx_int) begin //接收数据处理
  if(clk_bps) begin //读取并保存数据,接收数据为一个起始位,8bit数据,1或2个结束位  
    num <= num+1'b1;
    RED <= ~RED;
    case (num)
      4'd1: rx_temp_data[0] <= UART_RXD; //锁存第0bit
      4'd2: rx_temp_data[1] <= UART_RXD; //锁存第1bit
      4'd3: rx_temp_data[2] <= UART_RXD; //锁存第2bit
      4'd4: rx_temp_data[3] <= UART_RXD; //锁存第3bit
      4'd5: rx_temp_data[4] <= UART_RXD; //锁存第4bit
      4'd6: rx_temp_data[5] <= UART_RXD; //锁存第5bit
      4'd7: rx_temp_data[6] <= UART_RXD; //锁存第6bit
      4'd8: rx_temp_data[7] <= UART_RXD; //锁存第7bit
      4'd9: RED <= 1'b1;
      default: ;
     endcase
   end
  else if(num == 4'd12) begin  //我们的标准接收模式下只有1+8+1(2)=11bit的有效数据
    num <= 4'd0;   //接收到STOP位后结束,num清零
    rx_data_r <= rx_temp_data; //把数据锁存到数据寄存器rx_data中
   end
  end

assign rx_data = rx_data_r; 

 

endmodule

3、      测试仿真


`timescale 1 ps/ 1 ps
module uart_vlg_tst();
// constants                                          
// general purpose registers
reg eachvec;
// test vector input registers
reg CLK_50MHZ;
reg RESET_N;
reg UART_RXD;
// wires                                              
wire GREEN;
wire RED;
wire UART_TXD;
wire YELLOW;

// assign statements (if any)                         
uart i1 (
// port map - connection between master ports and signals/registers  
 .CLK_50MHZ(CLK_50MHZ),
 .GREEN(GREEN),
 .RED(RED),
 .RESET_N(RESET_N),
 .UART_RXD(UART_RXD),
 .UART_TXD(UART_TXD),
 .YELLOW(YELLOW)
);
initial                                               
begin                                                 
  RESET_N = 0;
  CLK_50MHZ = 0;                  
   UART_RXD = 0;
   #20
   RESET_N = 1;  
   #20
   UART_RXD = 1;  
    #20
   UART_RXD = 0;
    #20
   UART_RXD = 1;
    #200
   UART_RXD = 1;
    #20
   UART_RXD = 0;
    #200
   UART_RXD = 1;
    #20
   UART_RXD = 1;
    #201
   UART_RXD = 0;
    #120
   UART_RXD = 1;
  
    #10
   UART_RXD = 0;
                
end                                                   
 
 
 initial                                               
begin       
  forever
   #20
   CLK_50MHZ = ~CLK_50MHZ ;               

              
end   
endmodule



4、      测试下载文件
uart.rar

 

 


专家
2012-12-28 13:37:34     打赏
13楼

12、       读取PS2接口
 

1、      实验内容
读取PS2键盘,显示到1602上。

2、      实验代码

module lcd1602ps2(
              
               CLK_50MHZ,
               RESET_N,
               LCD_D,
               LCD_E,
               LCD_RS,
               LCD_RW,
               LED,
               GREEN,
               YELLOW,
               MS_CLK,
               MS_DAT
 );

 input CLK_50MHZ;
 input RESET_N;
 output [7:0] LCD_D;
 output [7:0] LED;
 output LCD_E;
 output LCD_RS;
 output LCD_RW;
 output GREEN,YELLOW;
 inout MS_DAT,MS_CLK;
 
wire[7:0] ps2_byte; // 1byte键值
wire ps2_state;  //按键状态标志位 
assign LED[7:0] =ps2_byte ;
   lcd1602 XLXI_1 (              
      .clk(CLK_50MHZ),
      .rst_n(RESET_N),
      .ps2_state(ps2_state),
      .data_in(LED[7:0]),
      .lcd_d(LCD_D),
      .lcd_e(LCD_E),
      .lcd_rs(LCD_RS),
      .lcd_rw(LCD_RW),
      .led(GREEN),
      .yellow(YELLOW)
               );
              
       
ps2scan   ps2scan( .clk(CLK_50MHZ),      //按键扫描模块
        .rst_n(RESET_N),    
        .ps2k_clk(MS_CLK),
        .ps2k_data(MS_DAT),
        .ps2_byte(ps2_byte),
        .ps2_state(ps2_state)
        );       
       
       
   /*           
              
   ps2_keyboard XLXI_2 (
                                  .clk(CLK_50MHZ),
                                  .reset(RESET_N),
                                  .rx_read(),
                                  .tx_data(),
                                  .tx_write(),
                                  .rx_ascii(LED[7:0]),
                                  .rx_data_ready(),
                                  .rx_extended(),
                                  .rx_released( en ),//RESET_N 
                                  .rx_scan_code(),
                                  .rx_shift_key_on(),
                                  .tx_error_no_keyboard_ack(),
                                  .tx_write_ack_o(),
                                  .ps2_clk(MS_CLK),
                                  .ps2_data(MS_DAT)
        );*/

endmodule
module ps2scan(clk,rst_n,ps2k_clk,ps2k_data,ps2_byte,ps2_state);

input clk;     //50M时钟信号
input rst_n;    //复位信号
input ps2k_clk;    //PS2接口时钟信号
input ps2k_data;   //PS2接口数据信号
output[7:0] ps2_byte;  // 1byte键值,只做简单的按键扫描
output ps2_state;   //键盘当前状态,ps2_state=1表示有键被按下

//------------------------------------------
reg ps2k_clk_r0,ps2k_clk_r1,ps2k_clk_r2; //ps2k_clk状态寄存器

//wire pos_ps2k_clk;  // ps2k_clk上升沿标志位
wire neg_ps2k_clk; // ps2k_clk下降沿标志位

always @ (posedge clk or negedge rst_n) begin
 if(!rst_n) begin
   ps2k_clk_r0 <= 1'b0;
   ps2k_clk_r1 <= 1'b0;
   ps2k_clk_r2 <= 1'b0;
  end
 else begin        //锁存状态,进行滤波
   ps2k_clk_r0 <= ps2k_clk;
   ps2k_clk_r1 <= ps2k_clk_r0;
   ps2k_clk_r2 <= ps2k_clk_r1;
  end
end

assign neg_ps2k_clk = ~ps2k_clk_r1 & ps2k_clk_r2; //下降沿

//------------------------------------------
reg[7:0] ps2_byte_r;  //PC接收来自PS2的一个字节数据存储器
reg[7:0] temp_data;   //当前接收数据寄存器
reg[3:0] num;    //计数寄存器

always @ (posedge clk or negedge rst_n) begin
 if(!rst_n) begin
   num <= 4'd0;
   temp_data <= 8'd0;
  end
 else if(neg_ps2k_clk) begin //检测到ps2k_clk的下降沿
   case (num)
    4'd0: num <= num+1'b1;
    4'd1: begin
       num <= num+1'b1;
       temp_data[0] <= ps2k_data; //bit0
      end
    4'd2: begin
       num <= num+1'b1;
       temp_data[1] <= ps2k_data; //bit1
      end
    4'd3: begin
       num <= num+1'b1;
       temp_data[2] <= ps2k_data; //bit2
      end
    4'd4: begin
       num <= num+1'b1;
       temp_data[3] <= ps2k_data; //bit3
      end
    4'd5: begin
       num <= num+1'b1;
       temp_data[4] <= ps2k_data; //bit4
      end
    4'd6: begin
       num <= num+1'b1;
       temp_data[5] <= ps2k_data; //bit5
      end
    4'd7: begin
       num <= num+1'b1;
       temp_data[6] <= ps2k_data; //bit6
      end
    4'd8: begin
       num <= num+1'b1;
       temp_data[7] <= ps2k_data; //bit7
      end
    4'd9: begin
       num <= num+1'b1; //奇偶校验位,不做处理
      end
    4'd10: begin
       num <= 4'd0; // num清零
      end
    default: ;
    endcase
  end 
end

reg key_f0;  //松键标志位,置1表示接收到数据8'hf0,再接收到下一个数据后清零
reg ps2_state_r; //键盘当前状态,ps2_state_r=1表示有键被按下

always @ (posedge clk or negedge rst_n) begin //接收数据的相应处理,这里只对1byte的键值进行处理
 if(!rst_n) begin
   key_f0 <= 1'b0;
   ps2_state_r <= 1'b0;
  end
 else if(num==4'd10) begin //刚传送完一个字节数据
   if(temp_data == 8'hf0) key_f0 <= 1'b1;
   else begin
     if(!key_f0) begin //说明有键按下
       ps2_state_r <= 1'b1;
       ps2_byte_r <= temp_data; //锁存当前键值
      end
     else begin
       ps2_state_r <= 1'b0;
       key_f0 <= 1'b0;
      end
    end
  end
end

reg[7:0] ps2_asci; //接收数据的相应ASCII码

always @ (ps2_byte_r) begin
 case (ps2_byte_r)  //键值转换为ASCII码,这里做的比较简单,只处理字母
  8'h15: ps2_asci <= 8'h51; //Q
  8'h1d: ps2_asci <= 8'h57; //W
  8'h24: ps2_asci <= 8'h45; //E
  8'h2d: ps2_asci <= 8'h52; //R
  8'h2c: ps2_asci <= 8'h54; //T
  8'h35: ps2_asci <= 8'h59; //Y
  8'h3c: ps2_asci <= 8'h55; //U
  8'h43: ps2_asci <= 8'h49; //I
  8'h44: ps2_asci <= 8'h4f; //O
  8'h4d: ps2_asci <= 8'h50; //P       
  8'h1c: ps2_asci <= 8'h41; //A
  8'h1b: ps2_asci <= 8'h53; //S
  8'h23: ps2_asci <= 8'h44; //D
  8'h2b: ps2_asci <= 8'h46; //F
  8'h34: ps2_asci <= 8'h47; //G
  8'h33: ps2_asci <= 8'h48; //H
  8'h3b: ps2_asci <= 8'h4a; //J
  8'h42: ps2_asci <= 8'h4b; //K
  8'h4b: ps2_asci <= 8'h4c; //L
  8'h1a: ps2_asci <= 8'h5a; //Z
  8'h22: ps2_asci <= 8'h58; //X
  8'h21: ps2_asci <= 8'h43; //C
  8'h2a: ps2_asci <= 8'h56; //V
  8'h32: ps2_asci <= 8'h42; //B
  8'h31: ps2_asci <= 8'h4e; //N
  8'h3a: ps2_asci <= 8'h4d; //M
  default:; 
  endcase
end

assign ps2_byte = ps2_asci; 
assign ps2_state = ps2_state_r;

endmodule

3、      测试仿真
                                  
// *****************************************************************************
                                                                   
// Verilog Test Bench template for design : lcd1602ps2
//
// Simulation tool : ModelSim-Altera (Verilog)
//

`timescale 1 ns/ 1 ps
module lcd1602ps2_vlg_tst();
// constants                                          
// general purpose registers
reg eachvec;
// test vector input registers
reg CLK_50MHZ;
reg treg_MS_CLK;
reg treg_MS_DAT;
reg RESET_N;
// wires                                              
wire GREEN;
wire [7:0] LCD_D;
wire LCD_E;
wire LCD_RS;
wire LCD_RW;
wire [7:0] LED;
wire MS_CLK;
wire MS_DAT;
wire YELLOW;

// assign statements (if any)                         
assign MS_CLK = treg_MS_CLK;
assign MS_DAT = treg_MS_DAT;
lcd1602ps2 i1 (
// port map - connection between master ports and signals/registers  
 .CLK_50MHZ(CLK_50MHZ),
 .GREEN(GREEN),
 .LCD_D(LCD_D),
 .LCD_E(LCD_E),
 .LCD_RS(LCD_RS),
 .LCD_RW(LCD_RW),
 .LED(LED),
 .MS_CLK(MS_CLK),
 .MS_DAT(MS_DAT),
 .RESET_N(RESET_N),
 .YELLOW(YELLOW)
);

initial                                               
begin
 treg_MS_CLK = 1;                                                
 CLK_50MHZ = 0;
 RESET_N = 0;
 #2100
 RESET_N = 1;
 treg_MS_DAT = 0;
 #1300
 
 treg_MS_DAT = 1;
  #3020
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #2001
 treg_MS_DAT = 1;
   #2300
 treg_MS_DAT = 0;
  #3010
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #3040
 treg_MS_DAT = 1;
    #2300
 treg_MS_DAT = 0;
  #3201
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3080
 treg_MS_DAT = 1;
  #3500
 treg_MS_DAT = 1;
  #300
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #3020
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #3050
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3200
 treg_MS_DAT = 1;
  #3200
 treg_MS_DAT = 1;
  #2010
 treg_MS_DAT = 1;
  #1310
 treg_MS_DAT = 0;
  #300
 treg_MS_DAT = 1;
   #1200
 treg_MS_DAT = 0;
  #3010
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #2001
 treg_MS_DAT = 1;
   #310
 treg_MS_DAT = 0;
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #310
 treg_MS_DAT = 0;
  treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3060
 treg_MS_DAT = 1;
  #3020
 treg_MS_DAT = 1;
  #300
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #3030
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #300
 treg_MS_DAT = 1;
   #3020
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3100
 treg_MS_DAT = 1;
  #300
 treg_MS_DAT = 1;
  #3020
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #200
 treg_MS_DAT = 1;
   #2300
 treg_MS_DAT = 0;
  #3010
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3040
 treg_MS_DAT = 1;
    #2300
 treg_MS_DAT = 0;
  #3201
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3080
 treg_MS_DAT = 1;
  #3500
 treg_MS_DAT = 1;
  #300
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #3020
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #3050
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3200
 treg_MS_DAT = 1;
  #3200
 treg_MS_DAT = 1;
  #2010
 treg_MS_DAT = 1;
  #1310
 treg_MS_DAT = 0;
  #300
 treg_MS_DAT = 1;
   #1200
 treg_MS_DAT = 0;
  #3010
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #2001
 treg_MS_DAT = 1;
   #310
 treg_MS_DAT = 0;
  #3020
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #2001
 treg_MS_DAT = 1;
   #2300
 treg_MS_DAT = 0;
  #3010
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #3040
 treg_MS_DAT = 1;
    #2300
 treg_MS_DAT = 0;
  #3201
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3080
 treg_MS_DAT = 1;
  #3500
 treg_MS_DAT = 1;
  #300
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #3020
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #3050
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3200
 treg_MS_DAT = 1;
  #3200
 treg_MS_DAT = 1;
  #2010
 treg_MS_DAT = 1;
  #1310
 treg_MS_DAT = 0;
  #300
 treg_MS_DAT = 1;
   #1200
 treg_MS_DAT = 0;
  #3010
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #2001
 treg_MS_DAT = 1;
   #310
 treg_MS_DAT = 0;
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #310
 treg_MS_DAT = 0;
  treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3060
 treg_MS_DAT = 1;
  #3020
 treg_MS_DAT = 1;
  #300
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #3030
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #300
 treg_MS_DAT = 1;
   #3020
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3100
 treg_MS_DAT = 1;
  #300
 treg_MS_DAT = 1;
  #3020
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #200
 treg_MS_DAT = 1;
   #2300
 treg_MS_DAT = 0;
  #3010
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3040
 treg_MS_DAT = 1;
    #2300
 treg_MS_DAT = 0;
  #3201
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3080
 treg_MS_DAT = 1;
  #3500
 treg_MS_DAT = 1;
  #300
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #3020
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #3050
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3200
 treg_MS_DAT = 1;
  #3200
 treg_MS_DAT = 1;
  #2010
 treg_MS_DAT = 1;
  #1310
 treg_MS_DAT = 0;
  #300
 treg_MS_DAT = 1;
   #1200
 treg_MS_DAT = 0;
  #3010
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #2001
 treg_MS_DAT = 1;
   #310
 treg_MS_DAT = 0;
  #3020
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #2001
 treg_MS_DAT = 1;
   #2300
 treg_MS_DAT = 0;
  #3010
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #3040
 treg_MS_DAT = 1;
    #2300
 treg_MS_DAT = 0;
  #3201
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3080
 treg_MS_DAT = 1;
  #3500
 treg_MS_DAT = 1;
  #300
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #3020
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #3050
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3200
 treg_MS_DAT = 1;
  #3200
 treg_MS_DAT = 1;
  #2010
 treg_MS_DAT = 1;
  #1310
 treg_MS_DAT = 0;
  #300
 treg_MS_DAT = 1;
   #1200
 treg_MS_DAT = 0;
  #3010
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #2001
 treg_MS_DAT = 1;
   #310
 treg_MS_DAT = 0;
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #310
 treg_MS_DAT = 0;
  treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3060
 treg_MS_DAT = 1;
  #3020
 treg_MS_DAT = 1;
  #300
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #3030
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #300
 treg_MS_DAT = 1;
   #3020
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3100
 treg_MS_DAT = 1;
  #300
 treg_MS_DAT = 1;
  #3020
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #200
 treg_MS_DAT = 1;
   #2300
 treg_MS_DAT = 0;
  #3010
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3040
 treg_MS_DAT = 1;
    #2300
 treg_MS_DAT = 0;
  #3201
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3080
 treg_MS_DAT = 1;
  #3500
 treg_MS_DAT = 1;
  #300
 treg_MS_DAT = 1;
  #1300
 treg_MS_DAT = 0;
  #3020
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #3050
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3001
 treg_MS_DAT = 1;
   #300
 treg_MS_DAT = 0;
  #3200
 treg_MS_DAT = 1;
  #3200
 treg_MS_DAT = 1;
  #2010
 treg_MS_DAT = 1;
  #1310
 treg_MS_DAT = 0;
  #300
 treg_MS_DAT = 1;
   #1200
 treg_MS_DAT = 0;
  #3010
 treg_MS_DAT = 1;
   #1300
 treg_MS_DAT = 0;
  #2001
 treg_MS_DAT = 1;
   #310
 treg_MS_DAT = 0;
end

                                               
initial                                               
begin                                                 
   forever
     #10
      CLK_50MHZ = ~CLK_50MHZ;     
     
             
end

                                               
initial                                               
begin                                                 
    
    forever
     #100
      treg_MS_CLK = ~treg_MS_CLK;       
     
             
end                                                  
endmodule


4、      测试下载文件
lcd1602ps2.rar

 


院士
2012-12-28 14:47:08     打赏
14楼
楼主,这是什么意思?

高工
2012-12-28 15:18:43     打赏
15楼
写完一气发,给你惊喜啊

助工
2012-12-29 10:49:25     打赏
16楼
             不错 还有仿真验证呀!!1

共16条 2/2 1 2 跳转至

回复

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