集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
楼主: lcytms

FPGA初级课程第十九讲 PS2

[复制链接]
 楼主| lcytms 发表于 2016-11-23 22:45:50 | 显示全部楼层
查看实际效果。
展示开发板和PS2键盘。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-23 22:49:28 | 显示全部楼层
使用SignalTap II逻辑分析仪查看PS2实际波形。
按下数字键1时,波形如下。
对应的8位二进制为8'h69,与波形一致。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-23 22:59:29 | 显示全部楼层
先从键盘矩阵模块ps2.v做起吧!
新建工程文件夹ps2。
新建ps2.v文件。
module ps2 (clk, rst_n, ps2_sclk, ps2_sda, key_value, flag);
       
        input clk, rst_n;
        input ps2_sclk;
        input ps2_sda;
       
        output reg [3:0] key_value;
        output reg flag;

       
        reg [7:0] ps2_data;
        reg valid;
       
       
        wire neg;
        reg ps2_sclk_r;
       
        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        ps2_sclk_r <= 0;
                                end
                        else
                                begin
                                        ps2_sclk_r <= ps2_sclk;
                                end
                end
       
        assign neg = ps2_sclk_r && (~ps2_sclk);
       
       
        reg [3:0] num;
        reg [15:0] watchdog;                // 1kHz
       
        //////// transfer serial to parallel

        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        num <= 0;
                                        valid <= 0;
                                        ps2_data <= 0;
                                        watchdog <= 0;
                                end
                        else
                                begin
                                        if (!neg)
                                                begin
                                                        if (watchdog < 999)
                                                                begin
                                                                        watchdog <= watchdog + 16'd1;
                                                                        valid <= 0;
                                                                end
                                                        else
                                                                begin
                                                                        watchdog <= 0;
                                                                        num <= 0;
                                                                end
                                                end
                                        else
                                                begin
                                                        watchdog <= 0;
                                               
                                                        case (num)
                                                        0        :        num <= num + 4'd1;
                                                       
                                                        1        :        begin
                                                                                num <= num + 4'd1;
                                                                                ps2_data[0] <= ps2_sda;
                                                                        end
                                                       
                                                        2        :        begin
                                                                                num <= num + 4'd1;
                                                                                ps2_data[1] <= ps2_sda;
                                                                        end
                                                       
                                                        3        :        begin
                                                                                num <= num + 4'd1;
                                                                                ps2_data[2] <= ps2_sda;
                                                                        end
                                                       
                                                        4        :        begin
                                                                                num <= num + 4'd1;
                                                                                ps2_data[3] <= ps2_sda;
                                                                        end
                                                       
                                                        5        :        begin
                                                                                num <= num + 4'd1;
                                                                                ps2_data[4] <= ps2_sda;
                                                                        end
                                                       
                                                        6        :        begin
                                                                                num <= num + 4'd1;
                                                                                ps2_data[5] <= ps2_sda;
                                                                        end
                                                       
                                                        7        :        begin
                                                                                num <= num + 4'd1;
                                                                                ps2_data[6] <= ps2_sda;
                                                                        end
                                                       
                                                        8        :        begin
                                                                                num <= num + 4'd1;
                                                                                ps2_data[7] <= ps2_sda;
                                                                        end
                                                       
                                                        9        :        begin
                                                                                num <= num + 4'd1;
                                                                                valid <= 1;
                                                                        end
                                                       
                                                        10        :        begin
                                                                                num <= 0;
                                                                        end
                                                       
                                                        default        :        num <= 0;
                                                       
                                                        endcase
                                                end
                                end
                end

        //////////// key value decoder
       
        reg [9:0] key_store;
        reg state;
       
               
        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        key_store <= 'b0;
                                        flag <= 0;
                                        key_value <= 4'h0;
                                        state <= 0;
                                end
                        else
                                begin
                                        if (!valid)
                                                flag <= 0;
                                        else
                                                begin
                                                        case (state)
                                                        0        :        begin                                                // key pressed
                                                                                case (ps2_data)
                                                                                8'h70        :        key_store[0] <= 1'b1;                // KP0={70,F0_70}
                                                                                8'h69        :        key_store[1] <= 1'b1;                // KP1={69,F0_69}
                                                                                8'h72        :        key_store[2] <= 1'b1;                // KP2={72,F0_72}
                                                                                8'h7A        :        key_store[3] <= 1'b1;                // KP3={7A,F0_7A}
                                                                                8'h6B        :        key_store[4] <= 1'b1;                // KP4={6B,F0_6B}
                                                                                8'h73        :        key_store[5] <= 1'b1;                // KP5={73,F0_73}
                                                                                8'h74        :        key_store[6] <= 1'b1;                // KP6={74,F0_74}
                                                                                8'h6C        :        key_store[7] <= 1'b1;                // KP7={6C,F0_6C}
                                                                                8'h75        :        key_store[8] <= 1'b1;                // KP8={75,F0_75}
                                                                                8'h7D        :        key_store[9] <= 1'b1;                // KP9={7D,F0_7D}
                                                                               
                                                                                8'hF0        :        state <= 1;
                                                                               
                                                                                default        :        key_store <= key_store;
                                                                               
                                                                                endcase
                                                                        end
                                                       
                                                        1        :        begin                                                // key released
                                                                                case (ps2_data)
                                                                                8'h70        :        begin                // KP0={70,F0_70}
                                                                                                                key_store[0] <= 1'b0;
                                                                                                                flag <= 1;
                                                                                                                key_value <= 4'h0;
                                                                                                                state <= 0;
                                                                                                        end
                                                                                                       
                                                                                8'h69        :        begin                // KP1={69,F0_69}
                                                                                                                key_store[1] <= 1'b0;
                                                                                                                flag <= 1;
                                                                                                                key_value <= 4'h1;
                                                                                                                state <= 0;
                                                                                                        end
                                                                                                       
                                                                                8'h72        :        begin                // KP2={72,F0_72}
                                                                                                                key_store[2] <= 1'b0;
                                                                                                                flag <= 1;
                                                                                                                key_value <= 4'h2;
                                                                                                                state <= 0;
                                                                                                        end
                                                                                                       
                                                                                8'h7A        :        begin        // KP3={7A,F0_7A}
                                                                                                                key_store[3] <= 1'b0;
                                                                                                                flag <= 1;
                                                                                                                key_value <= 4'h3;
                                                                                                                state <= 0;
                                                                                                        end
                                                                                                       
                                                                                8'h6B        :        begin        // KP4={6B,F0_6B}
                                                                                                                key_store[4] <= 1'b0;
                                                                                                                flag <= 1;
                                                                                                                key_value <= 4'h4;
                                                                                                                state <= 0;
                                                                                                        end
                                                                                                       
                                                                                8'h73        :        begin                // KP5={73,F0_73}
                                                                                                                key_store[5] <= 1'b0;
                                                                                                                flag <= 1;
                                                                                                                key_value <= 4'h5;
                                                                                                                state <= 0;
                                                                                                        end
                                                                                                       
                                                                                8'h74        :        begin                // KP6={74,F0_74}
                                                                                                                key_store[6] <= 1'b0;
                                                                                                                flag <= 1;
                                                                                                                key_value <= 4'h6;
                                                                                                                state <= 0;
                                                                                                        end
                                                                                                       
                                                                                8'h6C        :        begin                // KP7={6C,F0_6C}
                                                                                                                key_store[7] <= 1'b0;
                                                                                                                flag <= 1;
                                                                                                                key_value <= 4'h7;
                                                                                                                state <= 0;
                                                                                                        end
                                                                                                       
                                                                                8'h75        :        begin                // KP8={75,F0_75}
                                                                                                                key_store[8] <= 1'b0;
                                                                                                                flag <= 1;
                                                                                                                key_value <= 4'h8;
                                                                                                                state <= 0;
                                                                                                        end
                                                                                                       
                                                                                8'h7D        :        begin        // KP9={7D,F0_7D}
                                                                                                                key_store[9] <= 1'b0;
                                                                                                                flag <= 1;
                                                                                                                key_value <= 4'h9;
                                                                                                                state <= 0;
                                                                                                        end
                                                                                                       
                                                                                default        :        state <= 0;

                                                                                endcase
                                                                               
                                                                                state <= 0;
                                                                        end
                                                       
                                                        endcase
                                                end
                                end
                end
               
endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-23 23:03:22 | 显示全部楼层
进行分析综合检查。
编写Testbench。
新建ps2_tb.v文件。
`timescale 1ns/1ps

module ps2_tb;

        reg clk, rst_n;
        reg ps2_sclk;
        reg ps2_sda;
       
        wire [3:0] key_value;
        wire flag;
       
        ps2 dut (.clk(clk), .rst_n(rst_n), .ps2_sclk(ps2_sclk), .ps2_sda(ps2_sda), .key_value(key_value), .flag(flag));

        initial
                begin
                        clk = 1;
                        rst_n = 0;
                        ps2_sclk = 1;
                        ps2_sda = 1;
                        #200.1
                        rst_n = 1;
                       
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //start bit
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d0, d=8'h69, num=1
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d1
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d2
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d3
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d4
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d5
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d6
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d7
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //parity bit
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //stop bit
                        #2000
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //start bit
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d0, d=8'hF0, num=1
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d1
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d2
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d3
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d4
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d5
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d6
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d7
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //parity bit
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //stop bit
                        #2000
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //start bit
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d0, d=8'h69, num=1
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d1
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d2
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d3
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d4
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d5
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d6
                        #60        ps2_sda = 0;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //d7
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //parity bit
                        #60        ps2_sda = 1;        #60        ps2_sclk = 0;        #120        ps2_sclk = 1;                //stop bit
                       
                        #2000 $stop;
                end

        always #10 clk = ~clk;

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-23 23:04:47 | 显示全部楼层
进行分析综合检查。
进行仿真设置。
查看仿真结果。
每次按键按下之后,数据位key_value和标志位flag都有对应数字按键1的输出。
仿真功能正确。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-23 23:08:49 | 显示全部楼层
向工程文件夹添加第四讲的数码管模块seg7.v。
第十一讲 键盘矩阵也用到此模块。
module seg7 (clk, rst_n, data, sel, seg);

        input clk, rst_n;
        input [23:0] data;
       
        output reg [2:0] sel;
        output reg [7:0] seg;
       
        reg clk_1k;
       
        parameter T1ms = 25_000;                //half_width
        reg [19:0] count;
       
        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        count <= 0;
                                        clk_1k <= 1;
                                end
                        else
                                begin
                                        if (count < T1ms - 1)
                                                begin
                                                        count <= count + 20'b1;
                                                end
                                        else
                                                begin
                                                        count <= 0;
                                                        clk_1k <= ~clk_1k;
                                                end
                                end
                end
       
        reg [2:0] state;
        reg [3:0] data_temp;
       
        always @ (posedge clk_1k or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        sel <= 3'b000;
                                        state <= 0;
                                end
                        else
                                begin
                                        case (state)
                                        0        :        begin
                                                                sel <= 3'b000;
                                                                data_temp <= data[23:20];
                                                                state <= 1;
                                                        end
                                                       
                                        1        :        begin
                                                                sel <= 3'b001;
                                                                data_temp <= data[19:16];
                                                                state <= 2;
                                                        end
                                                       
                                        2        :        begin
                                                                sel <= 3'b010;
                                                                data_temp <= data[15:12];
                                                                state <= 3;
                                                        end
                                                       
                                        3        :        begin
                                                                sel <= 3'b011;
                                                                data_temp <= data[11:8];
                                                                state <= 4;
                                                        end
                                                       
                                        4        :        begin
                                                                sel <= 3'b100;
                                                                data_temp <= data[7:4];
                                                                state <= 5;
                                                        end
                                                       
                                        5        :        begin
                                                                sel <= 3'b101;
                                                                data_temp <= data[3:0];
                                                                state <= 0;
                                                        end
                                                       
                                        default        :        state <= 0;
                                       
                                        endcase
                                end
                end

        always @ (*)
                begin
                        if (!rst_n)
                                begin
                                        seg = 8'b1111_1111;                //null
                                end
                        else
                                begin
                                        case (data_temp)
                                        0        :        seg = 8'b1100_0000;                //d0
                                        1        :        seg = 8'b1111_1001;                //d1
                                        2        :        seg = 8'b1010_0100;                //d2
                                        3        :        seg = 8'b1011_0000;                //d3
                                        4        :        seg = 8'b1001_1001;                //d4
                                        5        :        seg = 8'b1001_0010;                //d5
                                        6        :        seg = 8'b1000_0010;                //d6
                                        7        :        seg = 8'b1111_1000;                //d7
                                        8        :        seg = 8'b1000_0000;                //d8
                                        9        :        seg = 8'b1001_0000;                //d9
                                        10        :        seg = 8'b1000_1000;                //dA
                                        11        :        seg = 8'b1000_0011;                //db
                                        12        :        seg = 8'b1100_0110;                //dC
                                        13        :        seg = 8'b1010_0001;                //dd
                                        14        :        seg = 8'b1000_0110;                //dE
                                        15        :        seg = 8'b1000_1110;                //dF
                                        default        :        seg = 8'b1111_1111;                //null
                                        endcase
                                end
                end

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-23 23:11:08 | 显示全部楼层
向工程添加第十一讲 键盘矩阵中的数码管数据预处理模块pre_seg7.v。
module pre_seg7 (clk, rst_n, data, flag, data6);

        input clk, rst_n;
        input [3:0] data;
        input flag;
       
        output reg [23:0] data6;

        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        data6 <= 24'h000000;
                                end
                        else
                                begin
                                        if (!flag)
                                                data6 <= data6;
                                        else
                                                data6 <= {data6[19:0], data};
                                        end
                end
       
endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-23 23:12:38 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-23 23:15 编辑

新建分频模块divider.v。
编写divider.v模块如下。
module divider (clk, rst_n, clk_1M);

        input clk,rst_n;
       
        output reg clk_1M;
        reg [7:0] count;
       
        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        clk_1M <= 0;
                                        count <= 0;
                                end
                        else
                                begin
                                        if (count <24)
                                                count <= count + 8'd1;
                                        else
                                                begin
                                                        count <= 0;
                                                        clk_1M <= ~clk_1M;
                                                end
                                end
                end

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-23 23:14:51 | 显示全部楼层
新建top.v顶层模块,将以上四个模块都加入到top.v顶层模块中进行例化。
将top.v模块设置为顶层模块。
编写top.v模块如下。
module top (clk, rst_n, ps2_sclk, ps2_sda, sel, seg);

        input clk, rst_n;
        input ps2_sclk, ps2_sda;
       
        output [2:0] sel;
        output [7:0] seg;
       
        wire clk_1M;
        wire [3:0] data;
        wire flag;
        wire [23:0] data6;
       
        divider divider (.clk(clk), .rst_n(rst_n), .clk_1M(clk_1M));
       
        ps2 ps2 (.clk(clk_1M), .rst_n(rst_n), .ps2_sclk(ps2_sclk), .ps2_sda(ps2_sda), .key_value(data), .flag(flag));
       
        pre_seg7 pre_seg7 (.clk(clk_1M), .rst_n(rst_n), .data(data), .flag(flag), .data6(data6));

        seg7 seg7 (.clk(clk), .rst_n(rst_n), .data(data6), .sel(sel), .seg(seg));

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-23 23:17:10 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-23 23:21 编辑

参照.tcl文件设置好FPGA管脚

参照EP4CE10F17C8Nzx_1.tcl文件内容,对FPGA芯片管脚进行设置。

EP4CE10F17C8Nzx_1.tcl文件相关内容如下所示。FPGA芯片配置结果如图所示。

        #set_global_assignment -name FAMILY "Cyclone IV"
        #set_global_assignment -name DEVICE ep4ce10f17c8n

set_location_assignment PIN_E1    -to    clk         

# PS2
set_location_assignment PIN_N8    -to    ps2_sclk         
set_location_assignment PIN_L8    -to    ps2_sda        
       
# KEY 轻触按键
set_location_assignment PIN_L3    -to   key[0]         

# SEG7 x 8 七段数码管
set_location_assignment PIN_L6    -to   sel[2]
set_location_assignment PIN_N6    -to   sel[1]
set_location_assignment PIN_M7    -to   sel[0]
set_location_assignment PIN_T11   -to   seg[0]     
set_location_assignment PIN_T10   -to   seg[1]   
set_location_assignment PIN_T9    -to   seg[2]     
set_location_assignment PIN_T8    -to   seg[3]     
set_location_assignment PIN_T7    -to   seg[4]     
set_location_assignment PIN_T6    -to   seg[5]     
set_location_assignment PIN_T5    -to   seg[6]     
set_location_assignment PIN_T4    -to   seg[7]
   

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|集成电路技术分享 ( 京ICP备20003123号-1 )

GMT+8, 2024-5-23 10:51 , Processed in 0.098258 second(s), 17 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表