chenhebing 发表于 2012-9-19 15:04:35

verilog编程问题

小弟刚学FPGA,最近看了一个16位的乘法器,例程中只给了我核心处理器模块,我想把按键和数码管显示全部做上去,可是出了问题,好几天了不知道怎么解决。代码如下,请大神指点。

module mux16(clk,rst_n,done,dig,seg,keyin,keyout);
input clk;                //芯片的时钟信号。
input rst_n;        //低电平复位、清零信号。定义为0表示芯片复位;定义为1表示复位信号无效。
//input start;         //芯片使能信号。定义为0表示信号无效;定义为1表示芯片读入输入管脚得乘数和被乘数,并将乘积复位清零。
//input ain;        //输入a(被乘数),其数据位宽为16bit.
//input bin;        //输入b(乘数),其数据位宽为16bit.
//output yout;        //乘积输出,其数据位宽为32bit.
input keyin;
output keyout;
output done;                //芯片输出标志信号。定义为1表示乘法运算完成.
output dig;
output seg;

reg areg;        //乘数a寄存器
reg breg;        //乘数b寄存器
reg yout_r;        //乘积寄存器
reg ain;
reg bin;
//reg ab_in;
reg done_r;
reg i;                //移位次数寄存器
reg start;
reg point;
reg yout_rr;


//reg keyval;

//reg start_r;
//reg point_r;

wire keyval;
wire yout;
wire int_r;

assign done = done_r;
assign yout = yout_rr;

key        key_u1(.clk(clk),.rst(rst_n),.int_r(int_r),.keyval(keyval),.keyin(keyin),.keyout(keyout));

dyn_seg seg_u1(.clk(clk),.d(yout),.dig(dig),.seg(seg));

always @ (posedge clk or negedge rst_n)
begin
        if(!rst_n)
        begin
                ain <= 16'd0;
                bin <= 16'd0;
                point <=1'b0;
        end
        else
        case(keyval)
                4'd10:
                begin
                        point <=1'b1;
        //                bin <=16'd0;
                        start <=1'b0;
                end
                4'd11:
                begin
                        start <=1'b1;
                end
                default:
                begin
                        if(int_r)
                        begin
                        if(!point)
                                ain <= {ain,keyval};
                        else
                                bin <= {bin,keyval};
                        end
                end
        endcase
end


always @ (posedge clk)
begin
        if(start)
                yout_rr <=yout_r;
        else
                if(!point)
                        yout_rr <=ain;
                else
                        yout_rr <=bin;
end

//数据位控制
always @(posedge clk or negedge rst_n)
        if(!rst_n)
                i <= 5'd0;
        else if(start && i < 5'd17) i <= i+1'b1;
        else if(!start) i <= 5'd0;

//乘法运算完成标志信号产生
always @(posedge clk or negedge rst_n)
        if(!rst_n) done_r <= 1'b0;
        else if(i == 5'd16) done_r <= 1'b1;                //乘法运算完成标志
        else if(i == 5'd17) done_r <= 1'b0;                //标志位撤销

//专用寄存器进行移位累加运算
always @(posedge clk or negedge rst_n)
begin
        if(!rst_n) begin
                        areg <= 16'h0000;
                        breg <= 16'h0000;
                        yout_r <= 32'h00000000;
                end
        else if(start) begin                //启动运算
                        if(i == 5'd0) begin        //锁存乘数、被乘数
                                        areg <= ain;
                                        breg <= bin;
                                end
                        else if(i > 5'd0 && i < 5'd16) begin
                                        if(areg) yout_r <= {1'b0,yout+breg,yout_r};        //累加并移位
                                        else yout_r <= yout_r>>1;        //移位不累加
                                end
                        else if(i == 5'd16 && areg) yout_r <= yout_r+breg;        //累加不移位
                end
end

endmodule

module key(clk,rst,int_r,keyval,keyin,keyout);       
inputclk;                                                //系统时钟
inputrst;                                                        //同步复位       
output int_r;       
input        keyin;                                //键盘接口输入
output keyout;                                //键盘接口输出
output keyval;                                //按键值

reg                keyval_r;
reg                keyout_r;
reg                dout1,dout2,dout3;                        //寄存
reg        keytmp1;
reg         keytmp2;
reg        clk_count;
reg                cnt4;
reg int_rr;

wire        nFlag;
wire        clk_en;
wire        clk4_en;
wire                key_done;                                //按键消抖输出

parametercmp_cnt = 100000;                         //消抖时钟分频系数=0.002*系统时钟频率

assign keyval=keyval_r;
assign keyout=keyout_r;

/*产生消抖时钟使能信号*/

always @ (posedge clk)                                               
begin
        if(!rst)
                clk_count <= 0;
        else
                if(clk_en)
                        clk_count <= 0;
                else
                        clk_count <= clk_count + 1'b1;
end

assign clk_en = (clk_count == cmp_cnt);        //Clock=50MHz时,ClkEN=2ms

/*产生键盘时钟使能信号*/
always @ (posedge clk)
begin
        if(!rst)
                cnt4 <= 2'd0;
        else
                if(clk_en)
                begin
                        if(clk4_en)
                                cnt4 <= 2'd0;
                        else
                                cnt4 <= cnt4 + 1'b1;
                end
end
assign clk4_en = (cnt4 == 2'b11) && clk_en;        //Clk4En=4*ClkEn

/*键盘消抖模块*/       
assign key_done = (dout1 | dout2 | dout3);       

always @ (posedge clk)
begin
        if(clk_en)                                                //消抖时钟使能信号
        begin
                dout1 <= keyin;
                dout2 <= dout1;
                dout3 <= dout2;
        end       
end


/*输出键盘行扫描信号*/
always @ (posedge clk)
begin
        if(!rst)
                keyout_r <= 3'b110;
        else if(clk4_en)
        begin
                if(keyout_r == 3'b011)
                        keyout_r <= 3'b110;
                else
                        keyout_r <= {keyout_r,1'b1};
        end       
end


/*读取键盘状态值*/
always @ (posedge clk)
begin
        if(!rst)
                keytmp1 <= 12'hfff;
        else
                if(clk4_en)
                begin
                        case(keyout_r)
                                3'b110 : keytmp1 <= key_done;       
                                3'b101 : keytmp1 <= key_done;       
                                3'b011 : keytmp1 <= key_done;               
                                default : keytmp1 <= 12'hfff;
                        endcase
                end
end

always @ (posedge clk)
begin
        keytmp2 <= keytmp1;       
end

assign nFlag = ~keytmp1 & keytmp2;
assign int_r =int_rr;
//assign int_r = nFlag;
always @ (posedge clk)
begin
        if(nFlag)
                int_rr <=1'b1;
        else
                int_rr <=1'b0;
end

/*输出键盘值*/
always @ (posedge clk)
begin
        if(!rst)
                keyval_r <= 4'd0;
        else
        begin
                if(nFlag)                        keyval_r <= 4'd1;
                else if(nFlag)                keyval_r <= 4'd4;
                else if(nFlag)                keyval_r <= 4'd7;
                else if(nFlag)                keyval_r <= 4'd10;
                else if(nFlag)                keyval_r <= 4'd2;
                else if(nFlag)                keyval_r <= 4'd5;
                else if(nFlag)                keyval_r <= 4'd8;
                else if(nFlag)                keyval_r <= 4'd0;
                else if(nFlag)         keyval_r <= 4'd3;
                else if(nFlag)                keyval_r <= 4'd6;
                else if(nFlag)        keyval_r <= 4'd9;
                else if(nFlag)        keyval_r <= 4'd11;
        end
end

endmodule


module dyn_seg(clk,d,dig,seg);
input clk;
input d;
output dig;
output seg;

reg clk_time;
reg dig_r;
reg seg_r;
reg count;
reg disp_dat;

assign dig=dig_r;
assign seg=seg_r;

always @ (posedge clk)
begin
        clk_time <= clk_time+1'b1;
        if(clk_time==17'd99999)
        begin
                count <= count+1'b1;
                clk_time <= 17'd0;
        end
end

always @ (posedge clk)
begin
        case(count)
                3'd0:        disp_dat=d;
                3'd1:        disp_dat=d;
                3'd2:        disp_dat=d;
                3'd3:        disp_dat=d;
                3'd4:        disp_dat=d;
                3'd5:        disp_dat=d;
                3'd6:        disp_dat=d;
                3'd7:        disp_dat=d;
        endcase
       
        case(count)
                3'd0:        dig_r=8'b01111111;
                3'd1:        dig_r=8'b10111111;
                3'd2:        dig_r=8'b11011111;
                3'd3:        dig_r=8'b11101111;
                3'd4:        dig_r=8'b11110111;
                3'd5:        dig_r=8'b11111011;
                3'd6:        dig_r=8'b11111101;
                3'd7:        dig_r=8'b11111110;
        endcase
end


always @ (disp_dat)
        begin
                case(disp_dat)
                        4'h0:        seg_r=8'h3f;
                        4'h1:        seg_r=8'h06;
                        4'h2:        seg_r=8'h5b;
                        4'h3:        seg_r=8'h4f;
                        4'h4:        seg_r=8'h66;
                        4'h5:        seg_r=8'h6d;
                        4'h6:        seg_r=8'h7d;
                        4'h7:        seg_r=8'h07;
                        4'h8:        seg_r=8'h7f;
                        4'h9:        seg_r=8'h6f;
                        4'ha:        seg_r=8'h77;
                        4'hb:        seg_r=8'h7c;
                        4'hc:        seg_r=8'h39;
                        4'hd: seg_r=8'h5e;
                        4'he:        seg_r=8'h79;
                        4'hf:        seg_r=8'h71;
                endcase
        end
endmodule

chenhebing 发表于 2012-9-19 15:06:25

4X3为12,但是3X4就成了8,不知道为什么,找不到出错的原因,求指点。谢谢了!
页: [1]
查看完整版本: verilog编程问题