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

  • Post author:
  • Post category:其他


牛客网上面有FPGA的刷题平台,打算暑假把上面的题刷了,代码思路给大家分享



目录


4选1多路选择器


异步复位的串联T触发器


奇偶校验


移位拼接乘法


位拆分与运算


4选1多路选择器

这道题用组合逻辑,sel选择信号的状态已经给出,可以通过case语法,sel为不同值的时候,输出选择不同,代码如下:

`timescale 1ns/1ns
module mux4_1(
input [1:0]d1,d2,d3,d0,
input [1:0]sel,
output[1:0]mux_out
);
//*************code***********//
    reg [1:0] mux_out_reg;//定义一个寄存器用来放输入
    always@(*)
        begin
            case(sel)
                2'b10:mux_out_reg=d1;
                2'b01:mux_out_reg=d2;
                2'b00:mux_out_reg=d3;
                2'b11:mux_out_reg=d0;
                default:mux_out_reg=d0;
            endcase
        end
    assign mux_out=mux_out_reg;
    
//*************code***********//
endmodule

异步复位的串联T触发器

这个题首先需要明确

T触发器的特点

,就是输出为输入的翻转(关于各种触发器可以看着这篇:

(1条消息) (数电)各种触发器汇总——FPGA八股文(1)_居安士的博客-CSDN博客

题目中所谓“串联”,就是把第一个T触发器的输出作为下一个触发器的输入,具体代码如下:

`timescale 1ns/1ns
module Tff_2 (
input wire data, clk, rst,
output reg q  
);
//*************code***********//
    reg q0;//定义中间变量q0
    
    always@(posedge clk or negedge rst)
        begin
            if(!rst)begin//rst低电平复位
                q0<=1'd0;
            end
            else if(data)begin//T触发器即为翻转触发器
                q0<=~q0;
            end
            else begin
                q0<=q0;
            end
        end
    
    always@(posedge clk or negedge rst)
        begin
            if(!rst)begin
                 q<=1'd0;
            end
            else if(q0)begin//T触发器即为翻转触发器
                q<=~q;
            end
            else begin
                q<=q;
            end
        end
        

//*************code***********//
endmodule

奇偶校验


奇偶校验

:指的是一个数的二进制有多少个1,奇数个1结果为1,偶数个1结果为0

比如9的二进制为4’b1001,1的个数为偶数2,奇偶校验就应该为0

奇偶校验最方便的实现方法就是用异或符^(相异为1,相同为0),叫一个数每一位自己进行异或,不管有多少个数,只要1的个数和0不同(1个数为奇数),结果就会输出为1

`timescale 1ns/1ns
module odd_sel(
input [31:0] bus,
input sel,
output check
);
//*************code***********//
wire check_temp;//定义一个异或结果
    
assign check_temp=^bus;//按位异或,可以检测二进制数字个数是奇数还是偶数
assign  check=sel ? check_temp:~check_temp;//sel为1输出check_temp,否则输出~check_temp

//*************code***********//
endmodule

还有一些常见的单目运算实现的功能:


检验一个数是否全为1

:结果=&data;     data不含0才会结果=1


检验一个数是否全为0

:结果=|data;       data不含1才会结果=0

移位拼接乘法

根据波形图,d的第3个输出6只持续了一个周期,但是输出依然为4个数,所以每个数输入之后都要先寄存,之后我们乘1、3、7、8,都使用这个寄存的数,而不是用当前d的值

`timescale 1ns/1ns
module multi_sel(
input [7:0]d ,
input clk,
input rst,
output reg input_grant,
output reg [10:0]out
);
//*************code***********//
    reg [1:0] cnt;//设置计数器记乘法运算数的个数
    
    always@(posedge clk or negedge rst)begin
        if(~rst)begin
            cnt<=2'd0;          
        end
        else begin
            cnt<=cnt+2'd1; //0~3一共4个数
        end
    end
    
    reg [7:0] d_reg;//d的寄存器
    
    always@(posedge clk or negedge rst )begin
        if(~rst)begin
            out<=11'd0;
            d_reg<=8'd0;
            input_grant<=1'd0;
        end
        else begin
             
            case(cnt)
                2'b00:begin//乘1  
                    d_reg<=d;
                    out<=d;
                    input_grant<=1'd1;
                end
                2'b01:begin//乘3
                    out<=d_reg+(d_reg<<1);//乘2(左移1位)+1
                    input_grant<=1'd0;
                end
                2'b10:begin//乘7
                    out<=(d_reg<<1)+(d_reg<<2)+d_reg;//乘4+乘2+1
                    input_grant<=1'd0;
                end
                2'b11:begin//乘8
                    out<=(d_reg<<3);//乘8(左移3位)
                    input_grant<=1'd0;
                end                   
            endcase
        end
    end

//*************code***********//
endmodule

乘2的次方的数,可以通过移位实现

不是2的次方的数,可以通过移位在进行加减运算

位拆分与运算


这个题目主要考察的是数据的位提取,想要

提取一个数的某几位

,data[高位:低位]

`timescale 1ns/1ns

module data_cal(
input clk,
input rst,
input [15:0]d,
input [1:0]sel,

output [4:0]out,
output validout
);
//*************code***********//
    reg [15:0]d_reg;//输入寄存器
    
    reg validout_reg;
    reg [4:0]out_reg;//赋值需要reg型,输出为wire型,所以需要自己加寄存器
    
    always@(posedge clk or negedge rst)begin
        if(~rst)begin
            out_reg<=5'd0;
            validout_reg<=1'd0;
            d_reg<=16'd0;
        end
        else begin
            case(sel)
                2'b00:begin
                    d_reg<=d;
                    out_reg<=5'd0;
                    validout_reg<=1'd0;
                end
                2'b01:begin
                    out_reg<=d_reg[3:0]+d_reg[7:4];
                    validout_reg<=1'd1;
                end
                2'b10:begin
                    out_reg<=d_reg[3:0]+d_reg[11:8];
                    validout_reg<=1'd1;
                end
                2'b11:begin
                    out_reg<=d_reg[3:0]+d_reg[15:12];
                    validout_reg<=1'd1;
                end
            endcase
            
        end
    end

    assign out=out_reg;
    assign validout=validout_reg;
//*************code***********//
endmodule



版权声明:本文为weixin_46188211原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。