目录
基础语法
VL1 四选一多路器
VL2 异步复位的串联T触发器
VL3 奇偶校验
VL4 移位运算与乘法
VL5 位拆分与运算
VL6 多功能数据处理器
VL7 求两个数的差值
VL8 使用generate…for语句简化代码
VL9 使用子模块实现三输入数的大小比较
VL10 使用函数实现数据大小端转换
思路1:case语句(4路以上用case更方便)
case(sel)
2'b00: mux_out = d3;
2'b01: mux_out = d2;
2'b10: mux_out = d1;
2'b11: mux_out = d0;
default:mux_out = 2'bxx;
endcase
思路2:三目运算符
assign mux_out = (sel==2'd0)?d3:((sel==2'd1)?d2:((sel==2'd2)?d1:(d0)));
T触发器功能:
当输入端T=0时,时钟脉冲到达触发器保持原态不变;
当输入端T=1时,每来一个时钟脉冲触发器的状态翻转一次。
信号示意图:
奇偶校验概念:
奇校验:就是让原有数据序列中(包括你要加上的一位)1的个数为奇数
1000110(0)你必须添0这样原来有3个1已经是奇数了所以你添上0之后1的个数还是奇数个。
偶校验:就是让原有数据序列中(包括你要加上的一位)1的个数为偶数
1000110(1)你就必须加1了这样原来有3个1要想1的个数为偶数就只能添1了。
缺点:1位误码能检测出,2位及2位以上检测不出来,而且不能纠错。
思路:^a操作,可以检测a中的“1”是否为奇数;
若a=100,^a=1^0^0=1,则1的数量为奇数,
若a=1100,^a=1^1^0^0=0,则1的数量为偶数。
assign check_ji = ^bus; //每个位相异或,
assign check = (sel == 1) ? check_ji : ~check_ji;
在硬件中进行乘除运算比较消耗资源,因此我们采用移位操作。
out <= d_reg + {d_reg ,1'b0}; //1+2=3
out <= d_reg + {d_reg,1'b0} + {d_reg,2'b0}; //1+2+4=7
out <= {d_reg,3'b0}; //8*d_reg
vivado仿真图:
注意:
wire变量只能用于组合逻辑中的assign语句(组合逻辑的always语句中不能用);
reg型变量用于时序逻辑中的always语句。
所以要注意看 该题设定好了输出变量类型,意味着要用下图设计方法。
if else即可完成
if else即可完成,要注意if eles的赋值语句超过1个,就要加begin...end
1、作用:generate…for是用于简化代码,
2、generate…for和for循环的区别:
generate-for只针对于module、regnet、assign、always、parameter、function.initial.task等语匀或煮模块,而g只针对打美例化的踊坎
3、使用方式:
5、本题实现代码
思路:ab比较,可得min_ab,再用min_ab和c比较,可得abc的最小值min_abc。
注意:t1时刻进行ab比较,t2时刻min_ab和c比较。但是有个问题,t2时刻c和t1时刻的c不一样。所以我们要给c延迟一个clk,加一个d触发器即可。
设计代码
`timescale 1ns/1ns
module main_mod(
input clk,
input rst_n,
input [7:0]a,
input [7:0]b,
input [7:0]c,
output [7:0]d
);
wire [7:0] min_ab;
reg [7:0] c_reg;
//给c加寄存器延迟一个clk
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
c_reg <= 8'b0;
else
c_reg <= c;
end
//先得到ab中的最小值min_ab
minare u1(
.clk(clk),
.rst_n(rst_n),
.x_1(a),
.x_2(b),
.y(min_ab)
);
//再得到min_ab和c中的最小值d
minare u2(
.clk(clk),
.rst_n(rst_n),
.x_1(min_ab),
.x_2(c_reg), //不能直接和c比较,因为ab的比较已经消耗了1个clk
.y(d) //此刻的c是下个时刻c,所以会出错。
);
endmodule
module minare(
input clk,
input rst_n,
input [7:0] x_1,
input [7:0] x_2,
output reg [7:0] y
);
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
y <= 8'b0;
else if(x_1 <= x_2)
y <= x_1;
else
y <= x_2;
end
endmodule
题目:请用函数实现一个4bit数据大小端转换的功能。实现对两个不同的输入分别转换并输出。
在数字芯片设计中,经常把实现特定功能的模块编写成函数function,在需要的时候再在主模块中调用,以提高代码的复用性和提高设计的层次,方便后续的修改。
大端小端区别:
大端:高字节数据存储在低地址。小端:低字节数据存储在低地址。
在verilog中,是以比特为单位,例如十进制8,小端是1000,大端是0001。
在c语言中,是以字节为单位,例如16进制1234,小端存储是3412,大端存储1234。
function和task的区别:
(1)任务能调用任务和函数,但是函数只能调用函数,不能调用任务;
(2)任务可以描述组合逻辑和时序逻辑,可以有时延;函数只能描述组合逻辑,仿真时延为0;
(3)任务可以有任意多个各种类型的输入;函数只能有input端口的输入参数,且至少输入一个参数;
(4)任务可以没有返回值;函数必须有一个返回值;
设计代码
module function_mod(
input [3:0]a,
input [3:0]b,
output [3:0]c,
output [3:0]d
);
assign c = data_reverse(a);
assign d = data_reverse(b);
function [3:0] data_reverse; //函数名
input [3:0] data_in; //输入变量
begin
data_reverse[0] = data_in[3];
data_reverse[1] = data_in[2];
data_reverse[2] = data_in[1];
data_reverse[3] = data_in[0];
end
endfunction
endmodule