FPGA刷题P3: 4位数值比较器电路、4bit超前进位加法器电路、优先编码器电路、 优先编码器

目前牛客网上面“基础语法”部分都已经完成了, 都是已经验证通过了的,代码链接如下:

FPGA刷题P1:4选1多路选择器、异步复位的串联T触发器、奇偶校验、移位拼接乘法_居安士的博客-CSDN博客

FPGA刷题P2:多功能数据处理器、求两个数的差值、使用generate...for语句简化代码、使用子模块实现三输入数的大小比较、使用函数实现数据大小端转化_居安士的博客-CSDN博客

个人的感觉,就算不是为了find work,用这些题目练习一下编程思维也是不错的 !下面就书接上文,开始“组合逻辑”的部分~~


目录

 4位数值比较器电路

4bit超前进位加法器电路

 优先编码器电路

用优先编码器实现键盘编码电路

 优先编码器


 4位数值比较器电路

 根据真值表output部分,给Y2=1和Y1=1时input要满足的条件,就可以实现了,这里没有Y0,我们可以理解为Y0是非Y1非Y2,需要注意的是,对于这种多个条件与或非,最好乖乖加括号,不然就需要特别熟悉符合的优先级,代码如下:

module comparator_4(
	input		[3:0]       A   	,
	input	   [3:0]		B   	,
 
 	output	 wire		Y2    , //A>B
	output   wire        Y1    , //A=B
    output   wire        Y0      //A<B
);

    assign Y2=(A[3]>B[3]) || ((A[3]==B[3])&&(A[2]>B[2]))||((A[3]==B[3])&&(A[2]==B[2])&&(A[1]>B[1])||(A[3]==B[3])&&(A[2]==B[2])&&(A[1]==B[1])&&(A[0]>B[0]));
    assign Y1=((A[3]==B[3])&&(A[2]==B[2])&&(A[1]==B[1])&&(A[0]==B[0]));
    assign Y0=(~Y1)&&(~Y2);
    
endmodule

4bit超前进位加法器电路

 这一题给出来了逻辑表达式,叫用Verilog语言去描述:

是同或运算符~^是异或运算符^&&是乘法,||是加法

公式里面的 i 指的是每一位

module lca_4(
	input		[3:0]       A_in  ,
	input	    [3:0]		B_in  ,
    input                   C_1   ,
 
 	output	 wire			CO    ,
	output   wire [3:0]	    S
);
    
    wire [3:0] G;
    wire [3:0] P;
    wire [3:0] C;
    
    assign G[0]=A_in[0] && B_in[0];//乘是与
    assign G[1]=A_in[1] && B_in[1];
    assign G[2]=A_in[2] && B_in[2];
    assign G[3]=A_in[3] && B_in[3];
    
    assign P[0]=A_in[0] ^ B_in[0];//圆圈加号是异或
    assign P[1]=A_in[1] ^ B_in[1];
    assign P[2]=A_in[2] ^ B_in[2];
    assign P[3]=A_in[3] ^ B_in[3];
    
    assign C[0]=G[0]|| P[0]&&C_1;//视为-1
    assign C[1]=G[1]|| P[1]&&C[0];//加号是或
    assign C[2]=G[2]|| P[2]&&C[1];
    assign C[3]=G[3]|| P[3]&&C[2];
    
    assign S[0]=P[0] ^ C_1;//视为-1
    assign S[1]=P[1] ^ C[0];
    assign S[2]=P[2] ^ C[1];
    assign S[3]=P[3] ^ C[2];
    
    assign CO=C[3];//输出C的高位作为进位
    
endmodule

 优先编码器电路

 真值表中x代表不知道是0还是1,就需要用到casex语句

casex语句可以识别出x和z的情况,使用方法和case没有区别,只是多加了x

casex(条件):

条件值:语句;

endcase

module encoder_0(
   input      [8:0]         I_n   ,
   
   output reg [3:0]         Y_n   
);

    always@(*)begin
        casex(I_n)
             9'b111111111:Y_n=4'b1111;
             9'b0xxxxxxxx:Y_n=4'b0110;
             9'b10xxxxxxx:Y_n=4'b0111;
             9'b110xxxxxx:Y_n=4'b1000;
             9'b1110xxxxx:Y_n=4'b1001;
             9'b11110xxxx:Y_n=4'b1010;
             9'b111110xxx:Y_n=4'b1011;
             9'b1111110xx:Y_n=4'b1100;
             9'b11111110x:Y_n=4'b1101;
             9'b111111110:Y_n=4'b1110;
            default: Y_n=4'b1111;
        endcase
    end
    
endmodule

用优先编码器实现键盘编码电路

这一题是在上一题的基础之上,真值表和上一题相同

 这个题要求按键输出为8421BCD码,根据目前真值表的输出Y,不难发现非Y就是8421BCD码的0~9

(8421BCD码:是指从高到低的4位分别为 8 4 2 1,用着4位数可以表示十进制的0~9,例如5的8421BCD码就是 0101)

此外,还要求有工作状态标志位,没有按键按下,Y输出为1111;按键0对应输入的0位,按下是低电平,因此只有按键0按下,0位=0

module encoder_0(
   input      [8:0]         I_n   ,
   
   output reg [3:0]         Y_n   
);

always @(*)begin
   casex(I_n)
      9'b111111111 : Y_n = 4'b1111;
      9'b0xxxxxxxx : Y_n = 4'b0110;
      9'b10xxxxxxx : Y_n = 4'b0111;
      9'b110xxxxxx : Y_n = 4'b1000;
      9'b1110xxxxx : Y_n = 4'b1001;
      9'b11110xxxx : Y_n = 4'b1010;
      9'b111110xxx : Y_n = 4'b1011;
      9'b1111110xx : Y_n = 4'b1100;
      9'b11111110x : Y_n = 4'b1101;
      9'b111111110 : Y_n = 4'b1110;
      default      : Y_n = 4'b1111;
   endcase    
end 
     
endmodule

module key_encoder(
    input      [9:0]         S_n   ,    //输入按键  I_n   
 
    output wire[3:0]         L     ,//按键输出Y_n
    output wire              GS //是否有按键按下
);    
    //例化  
    wire [3:0] L1;
    encoder_0 inst_encoder_0(
        .I_n   (S_n[9:1]),
        .Y_n   (L1)
     );
    
    assign L=~L1;//8421BCD码恰好是Y_n的非
    assign GS=((L1==4'b1111) && (S_n[0]==1))? 0:1; //没有按键按下=0,按键0没按下=1
    
endmodule

 优先编码器

 表格非常长!给了一个巨长的真值表要求实现

和以往不同的是,这次的输入相当于给了一个复位信号E

module encoder_83(
   input      [7:0]       I   ,
   input                  EI  ,
   
   output wire [2:0]      Y   ,
   output wire            GS  ,
   output wire            EO    
);
    reg [2:0] y;
    reg gs;
    reg eo;
    
    always@(*)begin
        if(~EI)begin
            y  =3'b0;
           gs  =1'b0;
           eo  =1'b0;
        end
        else begin
             casex(I)
        8'b00000000 : begin
            y = 3'b000;
            gs = 1'b0;
            eo = 1'b1;
        end
        8'b1xxxxxxx : begin
            y = 3'b111;
            gs = 1'b1;
            eo = 1'b0;
        end
        8'b01xxxxxx : begin
            y = 3'b110;
            gs = 1'b1;
            eo = 1'b0;
        end
        8'b001xxxxx : begin
            y = 3'b101;
            gs = 1'b1;
            eo = 1'b0;
        end
        8'b0001xxxx : begin
            y = 3'b100;
            gs = 1'b1;
            eo = 1'b0;
        end
        8'b00001xxx : begin
            y = 3'b011;
            gs = 1'b1;
            eo = 1'b0;
        end
        8'b000001xx : begin
            y = 3'b010;
            gs = 1'b1;
            eo = 1'b0;
        end
        8'b0000001x : begin
            y = 3'b001;
            gs = 1'b1;
            eo = 1'b0;
        end
        8'b00000001 : begin
            y = 3'b000;
            gs = 1'b1;
            eo = 1'b0;
        end
        default    : begin
            y = 3'b000;
            gs = 1'b0;
            eo = 1'b0;
        end
    endcase
        end
    end

assign Y = y;
assign GS = gs;
assign EO = eo;
    
endmodule

猜你喜欢

转载自blog.csdn.net/weixin_46188211/article/details/125780339