学习FPGA过程中HDLBits刷题部分记录

2020/3/17在这里插入图片描述

module top_module( 
    input [2:0] a,
    input [2:0] b,
    output [2:0] out_or_bitwise,
    output out_or_logical,
    output [5:0] out_not
);
    assign out_or_bitwise=a|b;//按位或
    assign out_not={~b, ~a};
    assign out_or_logical=a||b; //逻辑或
endmodule

补充:^代表的是异或; 每一位进行
^~代表的是同或; 每一位进行
几个向量串联可以直接assign {w,x,y,z}={a,b,c,d,e,f,2’b11};
wxyz就可分到自己对应的值;
将较小的数拓展为较大的数时,assign out={{24{in[7]}},in};
一般都是将它的符号位保留,也就是最左边的那位;
复制时,需按照以下形式进行;
assign converge1={5{a,b,c,d,e}};
assign converge2={{5{a}},{5{b}},{5{c}},{5{d}},{5{e}}};
不能通过循环通过assign给变量赋值;
模块例化有两种方法;
在这里插入图片描述
实例化三个模块:
需创建中间变量,然后传值

	module top_module ( input clk, input d, output q );
    wire q1_d2;
    wire q2_d3;
    my_dff u_my_dff1(
        .clk	(clk),
        .d		(d),
        .q		(q1_d2)
    );  
    my_dff u_my_dff2(
        .clk	(clk),
        .d		(q1_d2),
        .q		(q2_d3)
    );
    my_dff u_my_dff3(
        .clk	(clk),
        .d		(q2_d3),
        .q		(q)
    );
endmodule

这个题我感觉有点难。。。。
在这里插入图片描述
2020/3/18
因为第三个的q没有直接和输出相连,所以需要创建一个中间变量储存,然后根据sel的值是多少,再赋值给一个暂时储存输出的中间变量,通过assign语句将值赋给q。(因为assign不能连续赋值,所以不能放在case里面,直接把值赋给q,所以需要建立一个储存输出值的中间变量);

module top_module ( 
    input clk, 
    input  [7:0] d, 
    input  [1:0] sel, 
    output [7:0] q 
);
    wire   [7:0] q1_d2;
    wire   [7:0] q2_d3;
    wire   [7:0] q3_data_tep;
    reg	   [7:0] data_tep;
    always@(*)begin
        case(sel)
            2'd0:begin
                 data_tep=d;
            end
            2'd1:begin
                data_tep=q1_d2;
            end
            2'd2:begin
                data_tep=q2_d3;
            end
            2'd3:begin
                data_tep=q3_data_tep;
            end
        endcase
    end
    assign q=data_tep;
	my_dff8 u_my_dff81( 
        .clk	(clk), 
        .d		(d),
        .q		(q1_d2)
);
    my_dff8 u_my_dff82( 
        .clk	(clk), 
        .d		(q1_d2),
        .q		(q2_d3)
);
    my_dff8 u_my_dff83( 
        .clk	(clk), 
        .d		(q2_d3),
        .q		(q3_data_tep) 
);
endmodule

这个最后开始没读懂题,以为要建16个add1和16个add2。。。。
在这里插入图片描述

module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);//
    wire cout1_cin2,cout;
    wire [15:0] sum1;
    wire [15:0] sum2;
    add16 add1(.a(a[15:0]), .b(b[15:0]), .cin(1'b0), .sum(sum1),.cout(cout1_cin2));
    add16 add2(.a(a[31:16]),.b(b[31:16]),.cin(cout1_cin2),.sum(sum2),.cout(cout));
    assign sum={sum2, sum1};
endmodule

module add1( input a, input b, input cin,   output sum, output cout );
	assign sum=a^b^cin;
    assign cout=(a&b)|(a&cin)|(b&cin);
endmodule

多位数据和少位数据异或时,少位数据要扩增复制;

2021/3/19
在这里插入图片描述

module top_module( 
    input  [99:0] a, b,
    input  cin,
    output [99:0] cout,
    output [99:0] sum 
);
    reg	   [99:0] sum_tmp;
    reg	   [99:0] cout_tmp;
    always@(*)begin
        sum_tmp[0]=a[0]^b[0]^cin;
        cout_tmp[0]=(a[0]&b[0])|(a[0]&cin)|(cin&b[0]);
        for(int i=1;i<=99;i++)begin
            sum_tmp[i]=a[i]^b[i]^cout_tmp[i-1];
            cout_tmp[i]=(a[i]&b[i])|(a[i]&cout_tmp[i-1])|(cout_tmp[i-1]&b[i]);
        end
    end
    assign sum=sum_tmp;
    assign cout=cout_tmp;
endmodule

generate知识
在这里插入图片描述

module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum 
);
    reg  [99:0] cout_temp;
    reg [399:0] sum_temp;
    assign sum=sum_temp;
    generate
        genvar i;
        assign cout_temp[0]=cin;
        for(i=0;i<=399;i=i+4)begin:bcdadd
            bcd_fadd u_bcd_fadd(
                .a		(a[i+3:i]),
                .b		(b[i+3:i]),
                .cin	(cout_temp[i/4]),
                .cout	((i==396)?cout:cout_temp[i/4+1]),
                .sum	(sum_temp[i+3:i])
            );
        end
    endgenerate
endmodule

OR或,AND与,XOR异或,NOR或非,NAND与非,XNOR异或非(同或)。

卡洛图化简
最后加就是或,乘在一起就是与。在这里插入图片描述
module top_module(
input x3,
input x2,
input x1, // three inputs
output f // one output
);
assign f=(x3&x1)|((~x3)&x2);
endmodule

2020/3/21
verilog不能使用out_tmp=in[(i3’d4+2’d3):(i3’d4)];这种形式,使用In[p:o]这种形式时,里面不能为变量。
在这里插入图片描述
可以用下面代替
assign out = {in[sel4+3], in[sel4+2], in[sel4+1], in[sel4+0]};

2020/3/22

我没有把补码弄清楚,导致一直判断出来是否溢出,区分出什么时候会一处溢出(原来的符号位和现在的不同即为溢出)。mei

 	assign s = a + b;
    assign overflow = (a[7] & b[7] & ~s[7]) | (~a[7] & ~b[7] & s[7]);

直接用a+b就能表达求和,再加上cin就能得出最后的进位。
在这里插入图片描述
assign {cout,sum}=a+b+cin;

卡洛图化简的两种形式
SOP form 即与或式,对应于卡诺图就是圈1即可
POS form 即或与式, 对应于卡诺图就是圈0后,整体取反. 不用管的打其他符号可以用作化简

这个最开始还是没读懂题,后面发现就是ab固定求cd不同值时 的输出,注意顺序zh

    assign mux_in[0]=c?1'b1:(d?1'b1:1'b0);
    assign mux_in[1]=1'b0;
    assign mux_in[2]=c?(d?1'b0:1'b1):(d?1'b0:1'b1);
    assign mux_in[3]=c?(d?1'b1:1'b0):1'b0;

同步
always@(posedge clk)begin
这里面出现reset时,它需要在clk的上升沿到来时,才会触发。
end

异步
always@(posedge clk,posedge reset)begin
这里面出现reset时,它能够在clk或reset的任意一个上升沿到来时,都会触发。
end

边沿触发器,置位信号和clk同步
在这里插入图片描述
这个题一开始也没有看懂zhege

module top_module (
	input clk,
	input L,
	input r_in,
	input q_in,
	output reg Q
);
    always@(posedge clk)begin
        if(L)
            Q<=r_in;
        else
            Q<=q_in;
    end
endmodule

没有弄懂,需要加深,我最开始加了个中间变量在里面,在always里先把值给中间变量然后在外面赋值给z,不对,这样的话使用的是上一次的值,因该是有变化输出马上就变.不要中间变量正确。m没

module top_module (
    input clk,
    input x,
    output z
); 
    reg q0,q1,q2;
    always@(posedge clk)begin
        q0<=x^q0;
        q1<=x&~q1;
    	q2<=x|~q2;
    end
    assign z=~(q0|q1|q2);
endmodule

2021/3/23
这个题也是一开始完全没看懂再说什么。。。
在这里插入图片描述

module top_module (
    input clk,
    input [7:0] in,
    output [7:0] pedge
);
    reg [7:0] pedge_1,pedge_2;
    assign pedge=pedge_1&~pedge_2;
    always@(posedge clk)begin
        pedge_1<=in;
        pedge_2<=pedge_1;
    end
endmodule

这个题太难了。。。。。。,捕获”意味着输出将保持1直到寄存器被重置(同步复位),应该就是指只要没有被清除就一直保持高电平,所以需要或。这里的复位不是清清除那两个寄存的高低电平,而是直接清除输出。

module top_module (
    input clk,
    input reset,
    input [31:0] in,
    output [31:0] out
);
    wire [31:0] nedge;
    reg [31:0] reg_in;
    always@(posedge clk)
        reg_in <= in;
    assign 	nedge = reg_in & ~in;//下降沿检测
    always@(posedge clk)begin
        if(reset)
                out<= 0;
        else if(nedge!=0)
                out<=nedge|out;
        else
                out<=out;  
    end
endmodule

这个题我想了好久还是不会。。。 它先将值储存再两个不同变量当中,然后根据clk的电平来赋值,我之前就是没想到用什么来判断。

在这里插入图片描述

module top_module (
    input clk,
    input d,
    output q
);
    reg co,coo;
    always@(posedge clk)begin
        co<=d;
    end
    always@(negedge clk)begin
		coo<=d;
    end
    assign q=clk?co:coo;
endmodule

这个题我一开始没有用bcd去做,导致c_enable没有用。
在这里插入图片描述

module top_module (
    input clk,
    input reset,
    output OneHertz,
    output [2:0] c_enable
); //
    reg [3:0] q0,q1,q2;
    assign OneHertz=(q0==4'd9&&q1==4'd9&&q2==4'd9);//计时0到999,全为9时说明到一个1hz周期
    assign c_enable={(q1==4'd9&&q0==4'd9),q0==4'd9,1'b1};//指明每一个bcd器开始工作的时间,借用的之前做过的bcd
    bcdcount ge  (clk, reset, c_enable[0], q0);
    bcdcount shi (clk, reset, c_enable[1], q1);
    bcdcount bai (clk, reset, c_enable[2], q2);
endmodule

2021/3/24
一直没弄懂那个时间是怎么跳的卡了几个小时。。。。后面才发现早上11点一过就算下午 ,12跳1,然后晚上11点一过,就是早上,12跳1
在这里插入图片描述

module top_module(
    input  		 clk,
    input  		 reset,
    input 		 ena,
    output 		 pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss
); 
   reg flag;
   always@(posedge clk)begin
        if(reset)begin
            hh[7:4]<=4'd1;
            hh[3:0]<=4'd2;
            mm[7:4]<=4'd0;
            mm[3:0]<=4'd0;
            ss[7:4]<=4'd0;
            ss[3:0]<=4'd0;
            pm<=1'b0;
            flag=1'b0;
        end
        else begin
            if(ena)begin
                if(ss[3:0]<4'd9)
                    ss[3:0]<=ss[3:0]+1'b1;
                else begin
                    ss[3:0]<=4'd0;
                    if(ss[7:4]<4'd5)
                        ss[7:4]<=ss[7:4]+1'b1;
                    else begin
                        ss[7:4]<=4'd0;
                        if(mm[3:0]<4'd9)
                            mm[3:0]<=mm[3:0]+1'b1;
                        else begin
                            mm[3:0]<=4'd0;
                            if(mm[7:4]<4'd5)
                                mm[7:4]<=mm[7:4]+1'b1;
                            else begin
                                mm[7:4]<=4'd0;
                                if(!pm)begin //白天
                                    if(hh[3:0]<4'd9)begin
                                        hh[3:0]<=hh[3:0]+1'b1;
                                        if((hh[3:0]==4'd1)&(hh[7:4]==4'd1))begin  //11
                                            pm<=~pm;
                                        end
                                        else if((hh[3:0]==4'd2)&(hh[7:4]==4'd1))begin
                                            hh[7:4]<=4'd0;
                                            hh[3:0]<=4'd1;
                                        end
                                    end
                                    else begin
                                        hh[7:4]<=hh[7:4]+1'b1;
                                        hh[3:0]<=4'd0;
                                    end
                                end
                                else begin
                                    if(hh[3:0]<4'd9)begin
                                        hh[3:0]<=hh[3:0]+1'b1;
                                        if(hh[7:4]==4'd1&(hh[3:0]==4'd2))begin
                                            hh[7:4]<=4'd0;
                                            hh[3:0]<=4'd1;
                                        end
                                        else if((hh[3:0]==4'd1)&(hh[7:4]==4'd1))begin  //11
                                            pm<=~pm;
                                        end
                                    end
                                    else begin
                                        hh[7:4]<=hh[7:4]+1'b1;
                                        hh[3:0]<=4'd0;
                                    end
                                end
                            end
                        end
                    end
                end
            end
            else begin
            	hh<=hh;
           		mm<=mm;
           		ss<=ss;
           		pm<=pm;
            end
        end
    end
endmodule

算数逻辑和移位逻辑的不同:算数右移时,符号位不变,以符号位为基准移动,例如1100 移动一位 1110
逻辑右移就是直接移动没有这些规则。

2021/3/28
计算某种条件的个数时,要注意是否有这个状态,例如

if(count==2'd2)
	count<=2'd0;

在这里面count有2’d2这个状态,但是每个周期的count0时才作为那个使用,因为一开始的时候count0就已经使用了,还有就是尽量少用两个计数去表示一个东西,我这样会经常出错。。。。。

要使几个时钟周期里面高电平为2时输出为1,可以采用延迟打拍
例如:出现2个高电平就是 110 101 011三种情况 当满足这三种中的一种时,就输出高电平。

            w_reg1 <= w;
            w_reg2 <= w_reg1;
            以上为打拍举例
 if(w&~w_reg1&w_reg2|w&w_reg1&~w_reg2|~w&w_reg1&w_reg2)begin
                z <= 1'b1;
            end

2021/3/30
verilog 中
initial:它只会执行一次;
forever:它会不停的重复执行里面的内容;
#5:代表延迟5个时间。

module top_module ( );
	reg clk;
    initial
        forever begin
            clk=1'b0;
        	#5 clk=1'b1;
        	#5 clk=1'b0;
        end

    dut u_dut(
        .clk	(clk) 
    ) ;
endmodule
    initial begin
        in[0]=1'b0;
        in[1]=1'b0;
        #10;
        in[0]=1'b1;
        in[1]=1'b0;
        #10;
        in[0]=1'b0;
        in[1]=1'b1;
        #10;
        in[0]=1'b1;
        in[1]=1'b1;
    end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

syf_wfl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值