从零开始的FPGA生活
为了快速提高Verilog能力。采用边做题目边查资料的方式。HDLBits刷题
Verilog Language篇
Basics
- Simple wire
module top_module( input in, output out );
assign out = in;
endmodule
- Four wires
module top_module(
input a,b,c,
output w,x,y,z );
assign w=a,x=b,y=b,z=c;
endmodule
- Inverter
module top_module( input in, output out );
assign out =~in;
endmodule
- AND gate
module top_module(
input a,
input b,
output out );
assign out=a&b;
endmodule
- NOR gate //或非
module top_module(
input a,
input b,
output out );
assign out = ~(a|b);
endmodule
- XNOR//同或门
module top_module(
input a,
input b,
output out );
assign out = a~^b;
endmodule
- Declaring wires
`default_nettype none
module top_module(
input a,
input b,
input c,
input d,
output out,
output out_n );
wire and_in1,and_in2;
assign and_in1 = a&b;
assign and_in2 = c&d;
assign out= and_in1|and_in2;
assign out_n=~(and_in1|and_in2);
endmodule
- 7458 chip
module top_module (
input p1a, p1b, p1c, p1d, p1e, p1f,
output p1y,
input p2a, p2b, p2c, p2d,
output p2y );
assign p2y =(p2a&p2b)|(p2c&p2d);
assign p1y =(p1a&p1b&p1c)|(p1d&p1e&p1f);
endmodule
Vectors
- Vectors
module top_module (
input wire [2:0] vec,
output wire [2:0] outv,
output wire o2,
output wire o1,
output wire o0 ); // Module body starts after module declaration
assign outv = vec;
assign o2 = vec[2];
assign o1 = vec[1];
assign o0 = vec[0];
endmodule
- Vectors in more detail
`default_nettype none // Disable implicit nets. Reduces some types of bugs.
module top_module(
input wire [15:0] in,
output wire [7:0] out_hi,
output wire [7:0] out_lo );
assign out_hi = in[15:8];
assign out_lo = in[7:0];
endmodule
- Vector part select
module top_module(
input [31:0] in,
output [31:0] out );//
// assign out[31:24] = ...;
assign out = {in[7:0], in[15:8], in[23:16], in[31:24]};
endmodule
- Bitwise operators
module top_module(
input [2:0] a,
input [2:0] b,
output [2:0] out_or_bitwise,
output out_or_logical,
output [5:0] out_not
);
assign out_or_bitwise = a|b;
assign out_or_logical = a||b;
assign out_not ={~b,~a};
endmodule
- Four-input gates
module top_module(
input [3:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = ∈
assign out_or = |in;
assign out_xor = ^in;
endmodule
- Vector concatenation operator
module top_module (
input [4:0] a, b, c, d, e, f,
output [7:0] w, x, y, z );//
// assign { ... } = { ... };
assign {w, x, y, z} = {a, b, c, d, e, f, 2'b11};
endmodule
- Vector reversal 1
module top_module(
input [7:0] in,
output [7:0] out
);
integer i;
always@(*) begin
for(i = 0;i<=7;i=i+1)begin
out[i]= in[7-i];
end
end
endmodule
- Replication operator
module top_module (
input [7:0] in,
output [31:0] out );//
// assign out = { replicate-sign-bit , the-input };
assign out ={{24{in[7]}},in};
endmodule
- More replication
module top_module (
input a, b, c, d, e,
output [24:0] out );//
// The output is XNOR of two vectors created by
// concatenating and replicating the five inputs.
// assign out = ~{ ... } ^ { ... };
assign out =~{{5{a}},{5{b}},{5{c}},{5{d}},{5{e}}}^{5{a,b,c,d,e}};
endmodule
Modules:Hierarchy
- Modules
module top_module ( input a, input b, output out );
mod_a instance1(.in1(a),.in2(b),.out(out));
endmodule
- Connecting ports by position
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a ( out1, out2,a,b,c,d );
endmodule
- Connecting ports by name
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a instance1(.out1(out1),.out2(out2),.in1(a),.in2(b),.in3(c),.in4(d));
endmodule
- Three modeles
module top_module ( input clk, input d, output q );
wire q1,q2;
my_dff my_dff1(.clk(clk),.d(d),.q(q1));
my_dff my_dff2(.clk(clk),.d(q1),.q(q2));
my_dff my_dff3(.clk(clk),.d(q2),.q(q));
endmodule
- Modeles and vectors
module top_module (
input clk,
input [7:0] d,
input [1:0] sel,
output [7:0] q
);
wire [7:0]q1;
wire [7:0]q2;
wire [7:0]q3;
my_dff8 my_dff1(.clk(clk),.d(d),.q(q1));
my_dff8 my_dff2(.clk(clk),.d(q1),.q(q2));
my_dff8 my_dff3(.clk(clk),.d(q2),.q(q3));
always@(*) begin
case(sel)
2'd0:begin
q=d;
end
2'd1:begin
q=q1;
end
2'd2:begin
q=q2;
end
2'd3:begin
q=q3;
end
endcase
end
endmodule
- Adder 1
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire cout1;
add16 u1_add16(.a(a[15:0]),.b(b[15:0]),.cin(1'b0),.sum(sum[15:0]),.cout(cout1));
add16 u2_add16(.a(a[31:16]),.b(b[31:16]),.cin(cout1),.sum(sum[31:16]),.cout());
endmodule
- Adder 2
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);//
wire cout1;
add16 u1_add16(.a(a[15:0]),.b(b[15:0]),.cin(1'b0),.sum(sum[15:0]),.cout(cout1));
add16 u2_add16(.a(a[31:16]),.b(b[31:16]),.cin(cout1),.sum(sum[31:16]),.cout());
endmodule
module add1 ( input a, input b, input cin, output sum, output cout );
// Full adder module here
assign {cout, sum} = a + b + cin;
endmodule
- Carry-select adder
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire [15:0] sum1;
wire [15:0] sum2;
wire [15:0] sum3;
wire cout1;
add16 u1_add16(.a(a[15:0]),.b(b[15:0]),.cin(0),.sum(sum1),.cout(cout1));
add16 u2_add16(.a(a[31:16]),.b(b[31:16]),.cin(0),.sum(sum2),.cout());
add16 u3_add16(.a(a[31:16]),.b(b[31:16]),.cin(1),.sum(sum3),.cout());
assign sum = cout1 ? {sum3, sum1} : {sum2, sum1};
endmodule
- Adder-subtractor
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire [31:0] b_in;
wire cout1;
assign b_in ={32{sub}} ^ b;
add16 u1_add16(.a(a[15:0]),.b(b_in[15:0]),.cin(sub),.sum(sum[15:0]),.cout(cout1));
add16 u2_add16(.a(a[31:16]),.b(b_in[31:16]),.cin(cout1),.sum(sum[31:16]),.cout());
endmodule
Procedures
- Always blocks(combinational)
// synthesis verilog_input_version verilog_2001
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
- Always blocks(clocked)
// synthesis verilog_input_version verilog_2001
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
endmodule
- If statement
// synthesis verilog_input_version verilog_2001
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)begin
out_always = b;
end
else begin
out_always = a;
end
end
endmodule
- If statement latches
// synthesis verilog_input_version verilog_2001
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 statement
// synthesis verilog_input_version verilog_2001
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 // This is a combinational circuit
case(sel)
0:begin
out = data0;
end
1:begin
out = data1;
end
2:begin
out = data2;
end
3:begin
out = data3;
end
4:begin
out = data4;
end
5:begin
out = data5;
end
default:begin
out = 4'd0;
end
endcase
end
endmodule
- Priority encoder
// synthesis verilog_input_version verilog_2001
module top_module (
input [3:0] in,
output reg [1:0] pos );
always@(*) begin
casez(in)
4'bzz10:begin
pos =2'b01;
end
4'bz100:begin
pos =2'b10;
end
4'b1000:begin
pos =2'b11;
end
default:begin
pos = 2'b00;
end
endcase
end
endmodule
- Priority encoder with casez
//…刚才已经用了casez了
// synthesis verilog_input_version verilog_2001
module top_module (
input [7:0] in,
output reg [2:0] pos );
always@(*) begin
casez(in)
8'bzzzzzz10:begin
pos = 3'b001;
end
8'bzzzzz100:begin
pos = 3'b010;
end
8'bzzzz1000:begin
pos = 3'b011;
end
8'bzzz10000:begin
pos = 3'b100;
end
8'bzz100000:begin
pos = 3'b101;
end
8'bz1000000:begin
pos = 3'b110;
end
8'b10000000:begin
pos = 3'b111;
end
default:begin
pos = 3'b00;
end
endcase
end
endmodule
- List item
// synthesis verilog_input_version verilog_2001
module top_module (
input [15:0] scancode,
output reg left,
output reg down,
output reg right,
output reg up );
always@(*)begin
left = 1'b0;
down = 1'b0;
right = 1'b0;
up = 1'b0;
case(scancode)
16'he06b:begin
left = 1'b1;
end
16'he072:begin
down = 1'b1;
end
16'he074:begin
right = 1'b1;
end
16'he075:begin
up = 1'b1;
end
endcase
end
endmodule
Conditional
- Conditional ternary operator
//用w ? B : A模式会不利于观看
module top_module (
input [7:0] a, b, c, d,
output [7:0] min);//
// assign intermediate_result1 = compare? true: false;
always@(*) begin
min=a;
if(min>b) begin
min=b;
end
if(min>c) begin
min=c;
end
if(min>d) begin
min=d;
end
end
endmodule
- Reduction operators
module top_module (
input [7:0] in,
output parity);
assign parity = ^in;
endmodule
- Reduction: Even wider gates
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
- Combinational for-loop:Vector reversal 2
module top_module(
input [99:0] in,
output [99:0] out
);
integer i;
always@(*)begin
for(i = 0; i <= 99; i = i + 1)begin
out[i] = in[99 - i];
end
end
endmodule
- Combinational for-lop:255-bit population count
module top_module(
input [254:0] in,
output [7:0] out );
integer i;
always@(*)begin
out=0;
for(i = 0; i <= 254; i = i + 1)begin
out = (in[i])?out+1:out;
end
end
endmodule
- Generate for-loop:100-bit binary adder 2
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
integer i;
always@(*) begin
for(i=0;i<=99;i=i+1)begin
if(i==0)begin
{cout[0],sum[0]}=a[0]+b[0]+cin;
end
else begin
{cout[i], sum[i]} = a[i] + b[i] + cout[i-1];
end
end
end
endmodule
- Generate for-loop:100-digit BCD adder
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
wire[99:0] cout_b;
integer i;
always@(*) begin
for(i=0;i<=99;i=i+1) begin
if(i==0)begin
bcd_fadd u0_bcd_fadd(.a(a[3:0]),.b(b[3:0]),.cin(cin),.sum(sum[3:0]),.cout(cout_b[0]));
end
else begin
bcd_fadd ui_bcd_fadd(.a(a[4*i+3:4*i]),.b(b[4*i+3:4*i]),.cin(cout_b[i-1]),.sum(sum[4*i+3:4*i]),.cout(cout_b[i]));
end
end
end
assign cout = cout_b[99];
endmodule
- Gennerate for-loop:100-digit BCD adder
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
wire[99:0] cout_b;
generate
genvar i;
for(i=0;i<=99;i=i+1) begin:adder
if(i==0)begin
bcd_fadd u0_bcd_fadd(
.a(a[3:0]),
.b(b[3:0]),
.cin(cin),
.sum(sum[3:0]),
.cout(cout_b[0]));
end
else begin
bcd_fadd ui_bcd_fadd(
.a(a[4*i+3:4*i]),
.b(b[4*i+3:4*i]),
.cin(cout_b[i-1]),
.sum(sum[4*i+3:4*i]),
.cout(cout_b[i]));
end
end
assign cout = cout_b[99];
endgenerate
endmodule
Verilog Language篇结束。