verilog版的1602+ps2

该代码为本人课设时所写,参考网上各个信息加本人修改所作,可以直接使用

// ps2scan.v
module ps2scan(clk,rst_n,ps2k_clk,ps2k_data,ps2_byte,ps2_state);
 
 input clk; //20M时钟信号
 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 <= "q"; //Q
		 8'h1d: ps2_asci <= "w"; //W
		 8'h24: ps2_asci <= "e"; //E
		 8'h2d: ps2_asci <= "r"; //R
		 8'h2c: ps2_asci <= "t"; //T
		 8'h35: ps2_asci <= "y"; //Y
		 8'h3c: ps2_asci <= "u"; //U
		 8'h43: ps2_asci <= "i"; //I
		 8'h44: ps2_asci <= "o"; //O
		 8'h4d: ps2_asci <= "p"; //P 
		 8'h1c: ps2_asci <= "a"; //A
		 8'h1b: ps2_asci <= "s"; //S
		 8'h23: ps2_asci <= "d"; //D
		 8'h2b: ps2_asci <= "f"; //F
		 8'h34: ps2_asci <= "g"; //G
		 8'h33: ps2_asci <= "h"; //H
		 8'h3b: ps2_asci <= "j"; //J
		 8'h42: ps2_asci <= "k"; //K
		 8'h4b: ps2_asci <= "l"; //L
		 8'h1a: ps2_asci <= "z"; //Z
		 8'h22: ps2_asci <= "x"; //X
		 8'h21: ps2_asci <= "c"; //C
		 8'h2a: ps2_asci <= "v"; //V
		 8'h32: ps2_asci <= "b"; //B
		 8'h31: ps2_asci <= "n"; //N
		 8'h3a: ps2_asci <= "m"; //M
		 8'h45: ps2_asci <= "0"; //0
		 8'h16: ps2_asci <= "1"; //1
		 8'h1e: ps2_asci <= "2"; //2
		 8'h26: ps2_asci <= "3"; //3
		 8'h25: ps2_asci <= "4"; //4
		 8'h2e: ps2_asci <= "5"; //5
		 8'h36: ps2_asci <= "6"; //6
		 8'h3d: ps2_asci <= "7"; //7
		 8'h3e: ps2_asci <= "8"; //8
		 8'h46: ps2_asci <= "9"; //9
		 default: ;
    endcase
  end
  
 assign ps2_byte = ps2_asci; 
 assign ps2_state = ps2_state_r;
 
 endmodule
// lcd1602.v
`include "ps2scan.v"
`define LINE_1 16
`define LINE_2 32

module lcd1602(clk20m,CLK,DATA,reset,LCD_DATA,LCD_RW,LCD_EN,LCD_RS);
input clk20m,CLK,DATA,reset;
output [7:0] LCD_DATA;
output LCD_RW,LCD_EN,LCD_RS;

wire[7:0] ps2_byte;
wire ps2_state;
reg[7:0] ps2_data[31:0];
reg[5:0] i;
ps2scan ReadByte(.clk(clk20m),.rst_n(reset),.ps2k_clk(CLK),
        .ps2k_data(DATA),.ps2_byte(ps2_byte),.ps2_state(ps2_state)); 
  
always @(negedge ps2_state or negedge reset) 
  begin  
   if(!reset)
      i<=0;
   else if(i<=6'd31)
      begin
       ps2_data[i]<=ps2_byte;
       i<=i+1'b1;
      end
    else
      begin
       i<=6'd1;;
       ps2_data[0]<=ps2_byte;
      end
  end 
			
reg LCD_RS;
reg [7:0] LCD_DATA;
reg LCD_CLOCK;
reg[21:0] count;
reg [9:0] state;
reg [5:0] char_count=0;
reg [7:0] data_display;

parameter     IDLE=10'b00_0000_0000;
parameter    CLEAR=10'b00_0000_0001;
parameter   RETURN=10'b00_0000_0010;
parameter     MODE=10'b00_0000_0100;
parameter  DISPLAY=10'b00_0000_1000;
parameter    SHIFT=10'b00_0001_0000;
parameter FUNCTION=10'b00_0010_0000;
parameter    CGRAM=10'b00_0100_0000;
parameter    DDRAM=10'b00_1000_0000;
parameter    WRITE=10'b01_0000_0000;
parameter     STOP=10'b10_0000_0000;

assign LCD_RW=1'b0;
assign LCD_EN=LCD_CLOCK;

always @(posedge clk20m or negedge reset)
begin 
 if(!reset)
   begin
   count <= 22'b0;
   LCD_CLOCK <= 1'b0;
   end
 else if(count==39999)//4ms zhouqi
   begin
   count <= 22'b0;
   LCD_CLOCK <= ~LCD_CLOCK;
   end
 else
   count <= count + 1'b1;
end


always @(posedge LCD_CLOCK or negedge reset)
begin 
 if(!reset)
   LCD_RS <= 1'b0;
 else if(state==WRITE)
   LCD_RS <= 1'b1;
 else
   LCD_RS <= 1'b0;
end
   
always @(posedge LCD_CLOCK or negedge reset)
begin
             
  if(!reset)
   begin
   state <= IDLE;
   LCD_DATA <= 8'bzzzz_zzzz;
   char_count<=6'd0;
   end
 else 
   begin
     case(state)
           IDLE:begin
               state <= CLEAR;
               LCD_DATA <= 8'bzzzz_zzzz;
               end
          CLEAR:begin
                state <= RETURN;
                LCD_DATA <= 8'b0000_0001;
                end 
         RETURN:begin
                state <= MODE;
                LCD_DATA <= 8'b0000_0010;
                end    
           MODE:begin
                state <= DISPLAY;
                LCD_DATA <= 8'b0000_0110;
                end    
        DISPLAY:begin
                state <= SHIFT;
                LCD_DATA <= 8'b0000_1100;
                end    
          SHIFT:begin
                state <= FUNCTION;
                LCD_DATA <= 8'b0001_0100;
                end    
       FUNCTION:begin
                state <= DDRAM;
                LCD_DATA <= 8'b0011_1000;
                end    
          DDRAM:begin
                if(i==0)
                    begin
                    state <= DDRAM;
                    LCD_DATA <= 8'b1000_0000;
                    end 
                else if((char_count==`LINE_1)&&(char_count!=i))
				    begin
                      state <= WRITE;
					  LCD_DATA <= 8'b1100_0000;				  
                    end
                else
					begin
					  state <= WRITE;
					  LCD_DATA <= 8'b1000_0000;
					  char_count <=0;
					end    
                end    
          WRITE:begin
                if((char_count+1'b1==`LINE_1)||(char_count+1'b1==`LINE_2)||(char_count+1'b1==i))
                    state <= DDRAM;
                else                
                    state <= WRITE;
                   
                char_count <= char_count +1'b1;
                LCD_DATA <= ps2_data[char_count];
                
                end 
        //STOP: state <=STOP;
        default:state <= IDLE;     
     endcase   
    end
end
endmodule
    

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值