建立一个与门,用assign
语句和always
语句
module top_module(
input a,
input b,
output wire out_assign,
output reg out_alwaysblock
);
assign out_assign = a & b;
always @(*) begin
out_alwaysblock = a & b;
end
endmodule
建立一个异或门,使用assign
语句、组合always
语句和时序always
语句
module top_module(
input clk,
input a,
input b,
output wire out_assign,
output reg out_always_comb,
output reg out_always_ff );
assign out_assign = a ^ b;
always @(*) begin
out_always_comb = a ^ b;
end
always @(posedge clk) begin
out_always_ff <= a ^ b;
end
endmodul
if
语句通常用于创建2选1选择器,等同于三目运算符:assign out = (condition) ? x : y;
建立一个2选1选择器,如果sel_b1
和sel_b2
为真,选择b,其他情况选择a,使用assign
和always
module top_module(
input a,
input b,
input sel_b1,
input sel_b2,
output wire out_assign,
output reg out_always );
assign out_assign = (sel_b1 & sel_b2) ? b : a;
always @(*) begin
if(sel_b1 & sel_b2)
out_always = b;
else
out_always = a;
end
endmodule
如下代码产生了锁存器,修复代码:
always @(*) begin
if (cpu_overheated)
shut_off_computer = 1;
end
always @(*) begin
if (~arrived)
keep_driving = ~gas_tank_empty;
end
修复后:
module top_module (
input cpu_overheated,
output reg shut_off_computer,
input arrived,
input gas_tank_empty,
output reg keep_driving ); //
always @(*) begin
if (cpu_overheated)
shut_off_computer = 1;
else
shut_off_computer = 0;
end
always @(*) begin
if (~arrived)
keep_driving = ~gas_tank_empty;
else
keep_driving = 0;
end
endmodule
用case
语句创建一个6选1多路选择器
module top_module (
input [2:0] sel,
input [3:0] data0,
input [3:0] data1,
input [3:0] data2,
input [3:0] data3,
input [3:0] data4,
input [3:0] data5,
output reg [3:0] out );
always@(*) begin
case(sel)
3'b000: out = data0;
3'b001: out = data1;
3'b010: out = data2;
3'b011: out = data3;
3'b100: out = data4;
3'b101: out = data5;
default: out = 4'h0;
endcase
end
endmodule
优先编码器输出一个向量中第一个1的位置,建立一个4bit优先编码器,如果输入中没有1,则输出0,
module top_module (
input [3:0] in,
output reg [1:0] pos );
always @(*) begin
case(in)
4'h0 : pos = 2'h0;
4'h1 : pos = 2'h0;
4'h2 : pos = 2'h1;
4'h3 : pos = 2'h0;
4'h4 : pos = 2'h2;
4'h5 : pos = 2'h0;
4'h6 : pos = 2'h1;
4'h7 : pos = 2'h0;
4'h8 : pos = 2'h3;
4'h9 : pos = 2'h0;
4'ha : pos = 2'h1;
4'hb : pos = 2'h0;
4'hc : pos = 2'h2;
4'hd : pos = 2'h0;
4'he : pos = 2'h1;
4'hf : pos = 2'h0;
default: pos = 2'h0;
endcase
end
endmodule
建立一个8bit优先编码器,从低位开始,输出第一个1的位置,如果输入全0,则输出0,使用casez
语句
module top_module (
input [7:0] in,
output reg [2:0] pos );
always @(*) begin
casez(in)
8'bzzzzzzz1: pos = 3'd0;
8'bzzzzzz10: pos = 3'd1;
8'bzzzzz100: pos = 3'd2;
8'bzzzz1000: pos = 3'd3;
8'bzzz10000: pos = 3'd4;
8'bzz100000: pos = 3'd5;
8'bz1000000: pos = 3'd6;
8'b10000000: pos = 3'd7;
default : pos = 3'd0;
endcase
end
endmodule
假设你在建立一个电路处理PS/2键盘的信号,给定2字节信号,你需要判断被按下的按键是哪个
Scancode[15:0] | Arrow key |
---|---|
16’he06b | left arrow |
16’he072 | down arrow |
16’he074 | right arrow |
16’he075 | up arrow |
Anything else | none |
你的电路有1个16bit输入,和4个输出,避免产生锁存器
module top_module (
input [15:0] scancode,
output reg left,
output reg down,
output reg right,
output reg up );
// 方法一:case
always @(*) begin
left = 1'b0;
down = 1'b0;
right = 1'b0;
up = 1'b0;
case(scancode)
16'he06b: left = 1'b1;
16'he072: down = 1'b1;
16'he074: right = 1'b1;
16'he075: up = 1'b1;
endcase
end
// 方法二:assign
// assign left = scancode == 16'he06b;
// assign down = scancode == 16'he072;
// assign right = scancode == 16'he074;
// assign up = scancode == 16'he075;
endmodule
输入4个无符号数,输出最小值,使用条件三元运算符
module top_module (
input [7:0] a, b, c, d,
output [7:0] min);
wire [7:0] min_of_ab = a < b ? a : b;
wire [7:0] min_of_cd = c < d ? c : d;
assign min = min_of_ab < min_of_cd ? min_of_ab : min_of_cd;
endmodule
奇偶校验常用于传输数据时检测错误,建立一个电路输出8bit数据的奇偶校验位,使用偶校验
奇校验:若8bit数据中1的个数为偶数,则校验位为1,添加校验位后的9bit数据中1的个数为奇数
偶校验:若8bit数据中1的个数为奇数,则校验位为1,添加校验位后的9bit数据中1的个数为偶数
module top_module (
input [7:0] in,
output parity);
assign parity = ^ in;
endmodule
建立一个电路,有100bit输入,输出其与、或、异或
module top_module(
input [99:0] in,
output out_and,
output out_or,
output out_xor );
assign out_and = ∈
assign out_or = |in;
assign out_xor = ^in;
endmodule
输入100bit信号,反转其bit顺序输出
module top_module(
input [99:0] in,
output [99:0] out
);
generate
genvar i;
for(i = 0; i < 100; i = i + 1) begin:reversal
assign out[i] = in[99-i];
end
endgenerate
endmodule
人口计数器,计算一个向量中1的个数,建立一个255位宽的人口计数器
module top_module (
input [254:0] in,
output reg [7:0] out
);
integer i;
always @(*) begin
out = 0;
for (i = 0; i < 255; i++)
out = out + in[i];
end
endmodule
实例化100个全加器实现一个100bit的行波进位加法器
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
// 方法一:genearte-for
generate
genvar i;
for(i = 0; i < 100; i = i + 1) begin:gen
fadd ins(a[i], b[i], (i == 0) ? cin : cout[i - 1], cout[i], sum[i]);
end
endgenerate
/* 方法二:实例化数组
fadd ins[99:0](a, b, {cout[98:0], cin}, cout, sum);
*/
endmodule
module fadd(
input a, b, cin,
output cout, sum);
assign sum = a ^ b ^ cin;
assign cout = (a & b) | (b & cin) | (a & cin);
endmodule
提供bcd_add
模块:
module bcd_fadd (
input [3:0] a,
input [3:0] b,
input cin,
output cout,
output [3:0] sum );
实例化100个该模块,实现100位数BCD行波进位加法器
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
// 方法一:generate-for
wire [99:0] cout_vec;
generate
genvar i;
for(i = 0; i < 100; i = i + 1) begin:gen
bcd_fadd ins(a[i*4+3 -: 4], b[i*4+3 -: 4], (i == 0) ? cin : cout_vec[i-1], cout_vec[i], sum[i*4+3 -: 4]);
end
endgenerate
assign cout = cout_vec[99];
/*
// 方法二:实例化数组
wire [99:0] cout_vec;
bcd_fadd ins[99:0](a, b, {cout_vec[98:0], cin}, cout_vec, sum);
assign cout = cout_vec[99];
*/
endmodule