打印
[FPGA]

FPGA抢答器

[复制链接]
1026|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
qq470373513|  楼主 | 2015-1-29 23:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在此先感谢各路大神的帮忙,谢谢!这几天每天都要做家教,好心酸,想着我的的知识还没学完我就特别着急,可是为了生活没有办法,只能挤一挤时间了。做了几天的抢答器,借鉴了很多资料,现在我把它晒在这里,希望能帮到需要帮助的人,也希望和大家一起学习一起探讨,有问题可以及时指出哦~~不慎感谢!!
//************************************
//TOP module of 5 roads of responder
//************************************
`define ud #1
module RESPONDER_5(      
                                        //input ports
                                          SYSCLK,
                                          RST_B,
                                          KEY,
                                        //output ports
                                          BUZZER,
                                          LED,
                                          SEG_SEL,
                                          SEG_OUT
                                          );

//input and output declaration
input                                  SYSCLK;
input                                  RST_B;
input                [4:0]     KEY;
output                                  BUZZER;
output      [3:0]          LED;
output                [1:0]     SEG_SEL;
output                [7:0]          SEG_OUT;

//reg and wire declaration
wire                                  SYSCLK;
wire                              RST_B;
wire                [4:0]     KEY;
wire                                  BUZZER;
wire                [3:0]     LED;
wire                [1:0]     SEG_SEL;
wire                [7:0]     SEG_OUT;
//reg and wire in the module
reg                        [5:0]     KEY_REG;
reg                        [5:0]     KEY_REG_N;
reg                        [3:0]     KEY_NUM;
reg                                          SEG_LOCK;
reg                                          SEG_LOCK_N;
reg                                          LED_BUZZER_EN;
reg                                          LED_BUZZER_EN_N;
reg                        [31:0]    LED_BUZZER_TIME_CNT;
reg                        [31:0]    LED_BUZZER_TIME_CNT_N;
reg                        [3:0]     SECOND_L_NUM;
reg                          [3:0]          SECOND_L_NUM_N;
reg                        [3:0]     SECOND_H_NUM;
reg                        [3:0]     SECOND_H_NUM_N;
wire                [3:0]     TIME_L_NUM;
wire                [3:0]     TIME_H_NUM;
wire                [3:0]     SECOND_L;
wire                [3:0]     SECOND_H;




//detect key action
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                KEY_REG <= `ud 5'b11111;
        else
                KEY_REG <= `ud KEY_REG_N;
end
always        @        (*)
begin                                                    //****************************************
        if(KEY_REG != 5'b11111)              //detect the first key value is useable
                KEY_REG_N = KEY_REG;     //make sure the key press after the first
        else if(KEY != 5'b11111)                //is invalid
                KEY_REG_N = KEY;              //****************************************
        else
                KEY_REG_N = KEY_REG;
end

//key pressed decoder
always        @        (*)
begin
        case(KEY_REG)
                5'b11110:                        KEY_NUM = 4'h1;
                5'b11101:                        KEY_NUM = 4'h2;
                5'b11011:                        KEY_NUM = 4'h3;
                5'b10111:                        KEY_NUM = 4'h4;
                5'b01111:                        KEY_NUM = 4'h5;
                default :                        KEY_NUM = 4'h0;
        endcase
end

//the number lock at 0 if nobody press the key
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                SEG_LOCK <= `ud 1'h0;
        else
                SEG_LOCK <= `ud SEG_LOCK_N;
end
always        @        (*)
begin
        if((KEY_REG == 5'b11111)&&(TIME_L_NUM == 4'h0)&&(TIME_H_NUM == 4'h0))
                SEG_LOCK_N = 1'h1;
        else
                SEG_LOCK_N = SEG_LOCK;
end

//LED and BUZZER light up time counter
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                LED_BUZZER_TIME_CNT <= `ud 32'h0;
        else
                LED_BUZZER_TIME_CNT <= `ud LED_BUZZER_TIME_CNT_N;
end
always        @        (*)
begin
        if(LED_BUZZER_TIME_CNT == 32'h17D_7840)
                LED_BUZZER_TIME_CNT_N = 32'h0;
        else if (LED_BUZZER_EN)
                LED_BUZZER_TIME_CNT_N = LED_BUZZER_TIME_CNT + 32'h1;
        else
                LED_BUZZER_TIME_CNT_N = LED_BUZZER_TIME_CNT;
end
//LED and BUZZER enable
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                LED_BUZZER_EN <= `ud 1'h1;        //when count down begin ,led twinkle and buzzer bell
        else
                LED_BUZZER_EN <= `ud LED_BUZZER_EN_N;
end
always        @        (*)
begin
        if(LED_BUZZER_TIME_CNT == 32'h17D_7840)     //1s      
                LED_BUZZER_EN_N = 1'h0;
        else if((SEG_LOCK)||(KEY_REG ==5'b11111)&&(KEY_REG_N != 5'b11111))
                LED_BUZZER_EN_N = 1'h1;
        else
                LED_BUZZER_EN_N = LED_BUZZER_EN;
end

//LED segment lower control
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                SECOND_L_NUM <= `ud 4'h0;
        else
                SECOND_L_NUM <= `ud SECOND_L_NUM_N;
end
always        @        (*)
begin
        if(SEG_LOCK)
                SECOND_L_NUM_N = 4'h0;
        else if(KEY_REG == 5'b11111)
                SECOND_L_NUM_N = TIME_L_NUM;
        else
                SECOND_L_NUM_N = KEY_NUM;
end
assign SECOND_L = SECOND_L_NUM;

//LED segment higher control
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                SECOND_H_NUM <= `ud 1'h0;
        else
                SECOND_H_NUM <= `ud SECOND_H_NUM_N;
end
always        @        (*)
begin
        if(SEG_LOCK)
                SECOND_H_NUM_N = 4'h0;
        else if(KEY_REG == 5'b11111)
                SECOND_H_NUM_N = TIME_H_NUM;
        else
                SECOND_H_NUM_N = 4'h0;
end
assign SECOND_H = SECOND_H_NUM;

//instance
//buzzer
BUZZER i1(
                        .SYSCLK(SYSCLK),
                        .RST_B(RST_B),
                        .BUZZER_EN(LED_BUZZER_EN),
                        .BUZZER(BUZZER)
                        );

//led
LED i2(
                        .SYSCLK(SYSCLK),
                        .RST_B(RST_B),
                        .LED_EN(LED_BUZZER_EN),
                        .LED(LED)
                        );

//led segment
SEGMENT i3(
                        .SYSCLK(SYSCLK),
                        .RST_B(RST_B),
                        .SEG_SCAN_TIME(32'h3D090),
                        .SECOND_L_NUM(SECOND_L),
                        .SECOND_H_NUM(SECOND_H),
                        .SEG_SEL(SEG_SEL),
                        .SEG_OUT(SEG_OUT)
                        );
//the lower second
COUNTER i4(
                        .SYSCLK(SYSCLK),
                        .RST_B(RST_B),
                        .NUM_UP_LIM(4'h9),
                        .CLK_DIV_NUM(32'h17D_783F),
                        .NUM_OUT(TIME_L_NUM)
                        );
                       
//the higher second
COUNTER i5(
                        .SYSCLK(SYSCLK),
                        .RST_B(RST_B),
                        .NUM_UP_LIM(4'h1),
                        .CLK_DIV_NUM(32'hEE6_B280),
                        .NUM_OUT(TIME_H_NUM)
                        );
                       
endmodule

//**********************************
//BUZZER module
//**********************************
`define ud #1
module BUZZER(
                                //input ports
                                  SYSCLK,
                                  RST_B,
                                  BUZZER_EN,
                                //output ports
                                  BUZZER
                                  );
                                 
//input and output declaration
input                          SYSCLK;
input                          RST_B;
input                          BUZZER_EN;
output                          BUZZER;

//reg and wire declaration
wire                          SYSCLK;
wire                          RST_B;
wire                          BUZZER_EN;
reg                                  BUZZER;
reg                                  BUZZER_N;

//reg and wire in the module
reg                  [31:0]  CLK_DIV_CNT;
reg                  [31:0]  CLK_DIV_CNT_N;

//clock division for ring
always        @        (posedge SYSCLK or negedge RST_B)
begin      
        if(!RST_B)
                CLK_DIV_CNT <= `ud 32'h0;
        else
                CLK_DIV_CNT <= `ud CLK_DIV_CNT_N;
end
always @        (*)
begin
        if(CLK_DIV_CNT == 32'hFF80)
                CLK_DIV_CNT_N = 32'h0;
        else
                CLK_DIV_CNT_N = CLK_DIV_CNT + 32'h1;
end

//buzzer control
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                BUZZER <= `ud 1'h0;
        else
                BUZZER <= `ud BUZZER_N;
end
always        @        (*)
begin
        if((BUZZER_EN)&&(CLK_DIV_CNT == 32'hFF80))
                BUZZER_N = ~BUZZER;
        else
                BUZZER_N = BUZZER;
end
endmodule

//****************************
//LED module
//****************************
`define ud #1
module LED(
                                //input ports
                                  SYSCLK,
                                  RST_B,
                                  LED_EN,
                                //output ports
                                  LED
                                  );

//input and output declaration
input                          SYSCLK;
input                          RST_B;
input                          LED_EN;
output        [3:0]    LED;

//reg and wire declaration
wire                          SYSCLK;
wire                          RST_B;
wire                          LED_EN;
reg                [3:0]    LED;
//reg and wire in the module
reg                [31:0]   CLK_DIV_CNT;
reg                [31:0]   CLK_DIV_CNT_N;
reg                [3:0]          LED_N;

//clock division for twinkle
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                CLK_DIV_CNT <= `ud 32'h0;
        else
                CLK_DIV_CNT <= `ud CLK_DIV_CNT_N;
end
always        @        (*)
begin
        if(CLK_DIV_CNT == 32'h26_25A0)
                CLK_DIV_CNT_N = 32'h0;
        else
                CLK_DIV_CNT_N = CLK_DIV_CNT + 32'h1;
end

//led control
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                LED <= `ud 4'hf;
        else
                LED <= `ud LED_N;
end
always        @        (*)
begin
        if((LED_EN)&&(CLK_DIV_CNT == 32'h26_25A0))
                LED_N = ~LED;
        else if (LED_EN)
                LED_N = LED;
        else
                LED_N = 4'hF;
end
endmodule

//***********************************
//LED segment module
//***********************************
`define ud #1
module SEGMENT(
                                        //input ports
                                          SYSCLK,
                                          RST_B,
                                          SEG_SCAN_TIME,       //LED scan time   ,10ms
                                          SECOND_L_NUM,       //value in the lower second
                                          SECOND_H_NUM,                  //value in the higher second
                                        //output ports
                                          SEG_SEL,
                                          SEG_OUT
                                          );

//input and output declaration
input                                  SYSCLK;
input                                  RST_B;
input        [31:0]                  SEG_SCAN_TIME;
input        [3:0]                   SECOND_L_NUM;
input        [3:0]              SECOND_H_NUM;
output        [1:0]                   SEG_SEL;
output        [7:0]        SEG_OUT;

//reg and wire declaration
wire                                  SYSCLK;
wire                                  RST_B;
wire        [31:0]                  SEG_SCAN_TIME;
wire        [3:0]                  SECOND_L_NUM;
wire        [3:0]            SECOND_H_NUM;
reg                [1:0]                  SEG_SEL;
reg                [7:0]                   SEG_OUT;
//reg and wire in the module
reg                [31:0]           SEG_SCAN_DIV_CNT;
reg                [31:0]              SEG_SCAN_DIV_CNT_N;
reg             [1:0]                  SEG_SEL_NUM;
reg                [1:0]                  SEG_SEL_NUM_N;
reg                [3:0]                  SEG_OUT_NUM;



//LED segment scan frequency
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                SEG_SCAN_DIV_CNT <= `ud 32'h0;
        else
                SEG_SCAN_DIV_CNT <= `ud SEG_SCAN_DIV_CNT_N;
end
always        @        (*)
begin
        if(SEG_SCAN_DIV_CNT == SEG_SCAN_TIME)
                SEG_SCAN_DIV_CNT_N = 32'h0;
        else
                SEG_SCAN_DIV_CNT_N = SEG_SCAN_DIV_CNT + 32'h1;
end

//LED segment select control
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                SEG_SEL_NUM <= `ud 2'h0;
        else
                SEG_SEL_NUM <= `ud SEG_SEL_NUM_N;
end
always        @        (*)
begin
        if(SEG_SCAN_DIV_CNT == SEG_SCAN_TIME)
                SEG_SEL_NUM_N = SEG_SEL_NUM + 2'h1;
        else
                SEG_SEL_NUM_N = SEG_SEL_NUM;
end

//LED segment select decoder
always        @        (*)
begin
        case(SEG_SEL_NUM)      
                2'h0:                        SEG_SEL = 2'b10;
                2'h1:                        SEG_SEL = 2'b01;
                default:                SEG_SEL = 2'b11;
        endcase
end

//numbers in the segment load
always        @        (*)
begin
        case(SEG_SEL_NUM)
                2'b00:                        SEG_OUT_NUM = SECOND_L_NUM;
                2'b01:                        SEG_OUT_NUM = SECOND_H_NUM;
                default:                SEG_OUT_NUM = 4'h0;
        endcase
end

//LED segment numbers decoder
always        @        (*)
begin
        case(SEG_OUT_NUM)
                4'h0        :                SEG_OUT = 8'b0000_0011;
                4'h1        :                SEG_OUT = 8'b1001_1111;
                4'h2        :                SEG_OUT = 8'b0010_0101;
                4'h3        :                SEG_OUT = 8'b0000_1101;
                4'h4        :                SEG_OUT = 8'b1001_1001;
                4'h5        :                SEG_OUT = 8'b0100_1001;
                4'h6        :                SEG_OUT = 8'b0100_0001;
                4'h7        :                SEG_OUT = 8'b0001_1111;
                4'h8        :                SEG_OUT = 8'b0000_0001;
                4'h9        :                SEG_OUT = 8'b0000_1001;
                default :                    SEG_OUT = 8'b1111_1111;
        endcase
end
endmodule      


//****************************************************
//counter module ,pretended at produce segment number
//****************************************************
`define ud #1
module COUNTER(
                                        //input ports
                                          SYSCLK,
                                          RST_B,
                                          NUM_UP_LIM,
                                          CLK_DIV_NUM,
                                        //output ports
                                          NUM_OUT
                                          );

//input and output declaration
input                                SYSCLK;
input                                RST_B;
input                 [3:0]          NUM_UP_LIM;
input                 [31:0]         CLK_DIV_NUM;
output                [3:0]          NUM_OUT;

//reg and wire declaration
wire                                 SYSCLK;
wire                                 RST_B;
wire                       [3:0]     NUM_UP_LIM;
wire                       [31:0]    CLK_DIV_NUM;
reg                        [3:0]     NUM_OUT;
//reg and wire in the module
reg                        [31:0]    TIME_DIV_CNT;
reg                        [31:0]    TIME_DIV_CNT_N;
reg                                  CLK;
reg                                  CLK_N;
reg                        [3:0]     NUM_OUT_N;




//clock divided to adaptable frequency
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                TIME_DIV_CNT <= `ud 32'h0;
        else
                TIME_DIV_CNT <= `ud TIME_DIV_CNT_N;
end
always        @        (*)
begin
        if(TIME_DIV_CNT == CLK_DIV_NUM)
                TIME_DIV_CNT_N = 32'h0;
        else
                TIME_DIV_CNT_N = TIME_DIV_CNT + 32'h1;
end

//adaptable clock signal
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                CLK <= `ud 1'h0;
        else
                CLK <= `ud CLK_N;
end
always        @        (*)
begin
        if(TIME_DIV_CNT == CLK_DIV_NUM)
                CLK_N = ~CLK;
        else
                CLK_N = CLK;
end

//number output control
always        @        (posedge SYSCLK or negedge RST_B)
begin
        if(!RST_B)
                NUM_OUT <= `ud NUM_UP_LIM;
        else
                NUM_OUT <= `ud NUM_OUT_N;
end
always        @        (*)
begin
        if((NUM_OUT == 4'h0)&&(CLK == 1'h1)&&(CLK_N == 1'h0))
                NUM_OUT_N = NUM_UP_LIM;
        else if((CLK == 1'h1)&&(CLK_N == 1'h0))
                NUM_OUT_N = NUM_OUT - 4'h1;
        else
                NUM_OUT_N = NUM_OUT;
end
endmodule

相关帖子

沙发
t546505| | 2015-3-9 17:25 | 只看该作者
感觉这东西要写的代码好多啊!!!

使用特权

评论回复
板凳
风魔小象| | 2015-3-9 19:26 | 只看该作者
精神可慰

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

19

帖子

0

粉丝