牛客网上面有FPGA的刷题平台,打算暑假把上面的题刷了,代码思路给大家分享
目录
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