FPGA基础模块练习(基于牛客刷题)1

本文介绍了使用Verilog编程语言设计数字逻辑电路的一些基本组件,包括四选一多路器、异步复位T触发器、奇偶校验、移位运算以及4位数值比较器和加法器。在比较器和加法器的设计中,探讨了不同的实现方法,如行波进位和超前进位加法器,以及优先译码器和编码器的实现细节。
摘要由CSDN通过智能技术生成

1. 四选一多路器

较为基础根据sel进行输出选择。

2. 异步复位T触发器

T触发器:

Qn+1 = T Qn ' +T ' Qn= T⊕Qn 即每个CLK,T为0保持,T为1翻转。

`timescale 1ns/1ns
module Tff_2 (
input wire data, clk, rst,
output reg q  
);
//*************code***********//

reg databuffer;
always@(posedge clk or negedge rst)
if(!rst)
    databuffer<=0;
else
    databuffer<=data?(~databuffer):databuffer;


always@(posedge clk or negedge rst)
if(!rst)
    q<=0;
else
    q<=databuffer?(~q):q;

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

同步复位:复位受到CLK控制

异步复位:复位不受CLK控制

3. 奇偶校验

二进制代码的数位中“1”的个数是奇数或偶数来进行校验

用异或 (^sel)来判断是否是奇校验

`timescale 1ns/1ns
module odd_sel(
input [31:0] bus,
input sel,
output check
);
//*************code***********//

wire checkbuff;
assign checkbuff = (sel)?^bus:~(^bus);
assign check = checkbuff;


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

4. 移位运算与乘法

`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;
    reg [7:0] reg_d; 
always@(posedge clk or negedge rst)
    if(rst == 1'b0)
        cnt <= 2'd0;
    else if(cnt == 2'd3)
        cnt <= 2'd0;
    else 
        cnt <= cnt + 1'b1;
always@(posedge clk or negedge rst)
    if(rst == 1'b0)begin
        reg_d <= 8'd0;
        input_grant <= 1'b0;
    end
    else if(cnt == 2'd0)begin
        reg_d <= d;
        input_grant <= 1'b1;
    end
    else begin
        reg_d <= reg_d;
        input_grant <= 1'b0;
    end     
always@(posedge clk or negedge rst)
    if(rst == 1'b0) 
        out <= 11'd0;
    else case (cnt)
        2'd0 : out <= d;
        2'd1 : out <= (reg_d<<2)-reg_d;
        2'd2 : out <= (reg_d<<3)-reg_d;
        2'd3 : out <= (reg_d<<3);
        default : out <= 11'd0;
    endcase
//*************code***********//
endmodule

8. generate...for...简化

`timescale 1ns/1ns
module gen_for_module( 
    input [7:0] data_in,
    output [7:0] data_out
);

genvar gv_i;
generate
for(gv_i=0;gv_i<8;gv_i=gv_i+1)
begin:test
    assign data_out [gv_i] = data_in [7-gv_i];
end
endgenerate
    
endmodule

11. 4位数值比较器电路

结构化描述方式: 是使用实例化低层次模块的方法,即调用其他已经定义过的低层次模块对整个电路的功能进行描述,或者直接调用Verilog内部预先定义的基本门级元件描述电路的结构。

数据流描述方式: 是使用连续赋值语句(assign)对电路的逻辑功能进行描述,该方式特别便于对组合逻辑电路建模。

行为级描述方式: 是使用过程块语句结构(always)和比较抽象的高级程序语句对电路的逻辑功能进行描述。

此题只能用门电路,即与,或,非等等

1位比较器:

module compare_1(
 input A,
 input B,
 output Y2,//A>B
 output Y1,//A=B
 output Y0 //A<B
);

assign Y2 = A & (!B);
assign Y0 = (!A) & B;
assign Y1 = !(Y2 | Y0);

endmodule
`timescale 1ns/1ns

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
);
// wire [3:0] A_buffer,B_buffer;
// assign A_buffer=A;
// assign B_buffer=B;
 
 
// assign Y1=(A_buffer==B_buffer)?1:0;
// assign Y2=(A_buffer>B_buffer)?1:0;
// assign Y0=(A_buffer<B_buffer)?1:0;

wire W_y2[0:3];
wire W_y1[0:3];
wire W_y0[0:3];

genvar gen_i;
for (gen_i = 0; gen_i < 4; gen_i = gen_i + 1) begin
 compare_1 compare_1_u(
 .A (A[gen_i]   ),
    .B (B[gen_i]   ),
 .Y2(W_y2[gen_i]),//A>B
 .Y1(W_y1[gen_i]),//A=B
 .Y0(W_y0[gen_i]) //A<B
);
end

assign Y2 = W_y2[3] | ((W_y1[3]) & (W_y2[2])) | ((W_y1[3]) & (W_y1[2]) & (W_y2[1])) | ((W_y1[3]) & (W_y1[2]) & (W_y1[1]) & (W_y2[0]));
assign Y0 = W_y0[3] | ((W_y1[3]) & (W_y0[2])) | ((W_y1[3]) & (W_y1[2]) & (W_y0[1])) | ((W_y1[3]) & (W_y1[2]) & (W_y1[1]) & (W_y0[0]));
assign Y1 = W_y1[3] & W_y1[2] & W_y1[1] & W_y1[0];



endmodule 

module compare_1(
 input A,
 input B,
 output Y2,//A>B
 output Y1,//A=B
 output Y0 //A<B
);

assign Y2 = A & (!B);
assign Y0 = (!A) & B;
assign Y1 = !(Y2 | Y0);

endmodule

12. 4位加法器设计

加法器中半加器为:
 

assign S=A^B;

assign C_out = A&B;

全加器为:
 

assign S = A^B^C_i;

assign C_o = A&B|C_i&(a^b);

我之前的思路为设计RCA,行波进位加法器,即将全加器串联起来:

module rca #(
    parameter width = 4
)(
    input  [width-1:0] A,
    input  [width-1:0] B,
    output [width-1:0] S,
    
    input  C_i,
    output C_o
);
    wire [width:0] C;
    genvar i;
    generate
      	for (i=0; i<width; i=i+1)begin
            full_adder myadder(
                .A    (A[i]),
                .B    (B[i]),
                .C_i  (C[i]),
                .S    (S[i]),
                .C_o  (C[i+1]),
            );
        end
    endgenerate
  	assign C[0] = C_i;
    assign C_o  = C[width];
endmodule

按照此思路设计的代码如下:

`timescale 1ns/1ns

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 [4:0]C_IN;
	// reg [3:0]COO;
	assign C_IN[0]=C_1;
	genvar i;
	generate
		for(i=0;i<4;i=i+1)
		begin
			lca_1 mylca(.a_0(A_in[i]),.b_0(B_in[i]),.ci_0(C_IN[i]),.s_0(S[i]),.co_0(C_IN[i+1]));
		end
	endgenerate
	assign CO=C_IN[4];
    
endmodule


module lca_1(
	input a_0,
	input b_0,
	input ci_0,
	output wire co_0,
	output wire s_0
);

// assign s = a^b^cin;
// assign cout = a&b | (cin & (a^b));
	assign s_0=a_0^b_0^ci_0;
	assign co_0=a_0&b_0|(ci_0&(a_0^b_0));
endmodule

	

此种方式由于多位串联,很可能产生时延,导致数据接受异常,因此设计另一种加法器方式:

LCA,超前进位加法器,思路为并行计算进位。

此处新开一节记录加法器:加法器笔记

超前进位加法器的设计思路如此链接:超前进位加法器

超前进位加法器并行计算进位Ck。

assign S = A^B^C_i;
assign C_o = A&B|C_i&(a^b);
P = A^B;
G = A&B;

转换公式变为:

Si=Pi^ci-1;
ci=Gi+ci-1Pi;
c0=cin;
cout=cN;

 根据这个原理,开始加法器设计!

13. 优先译码器①

考察case,casez,casex的用法:

  • 在case语句中,敏感表达式中与各项值之间的比较是一种全等比较,每一位都相同才认为匹配。

  • 在casez语句中,如果分支表达式某些位的值为高阻z,那么对这些位的比较就会忽略,不予考虑,而只关注其他位的比较结果。

  • 在casex语句中,则把这种处理方式进一步扩展到对x的处理,即如果比较双方有一方的某些位的值是z或x,那么这些位的比较就不予考虑。

15.优先编码器

此题仅为简单测试,我也不知道和之前有什么区别,应该是case,casez,casex的使用

`timescale 1ns/1ns
module encoder_83(
   input      [7:0]       I   ,
   input                  EI  ,
   
   output wire [2:0]      Y   ,
   output wire            GS  ,
   output wire            EO    
);

reg [2:0] Ybuf;
always@(*)
begin
    casex(I)
        8'b0000_0000:Ybuf=3'd0;
        8'b0000_0001:Ybuf=3'd0;
        8'b0000_001x:Ybuf=3'd1;
        8'b0000_01xx:Ybuf=3'd2;
        8'b0000_1xxx:Ybuf=3'd3;
        8'b0001_xxxx:Ybuf=3'd4;
        8'b001x_xxxx:Ybuf=3'd5;
        8'b01xx_xxxx:Ybuf=3'd6;
        8'b1xxx_xxxx:Ybuf=3'd7;
        default:Ybuf=3'd0;
    endcase
end
assign EO=(&(~I))&EI;
assign GS=I&&EI;
assign Y=(EI)?Ybuf:3'd0;
endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值