Table of contents
1. Quartus II and Modelsim software installation and cracking
2. Complete the basic circuit simulation
(2), half adder and full adder
(5), data selector (choose one of the two)
(1), registers and shift registers
(3), frequency divider (two frequency / ten frequency)
1. Quartus II and Modelsim software installation and cracking
(Remarks: If the chip is EP2XXX, then the corresponding programming uses Cyclone II or the following version . This version is only supported in Quartus13.0 and below, while EP4XXX and above are applicable to Quartus13.0 and above.)
Quartus13.0 installation package link:
http://Link: https://pan.baidu.com/s/1TvCEyduApTvVlgcFJO9h_g Extraction code: 6666.
Quartus13.0 installation tutorial link:
https://blog.csdn.net/pang9998/article/details/83447190
Quartus18.0 installation package and tutorial links:
https://mp.weixin.qq.com/s/m1sFpNMR79V0Mk81axJ22Q
2. Complete the basic circuit simulation
1. Combination logic circuit
(1) Basic NOR gate circuit simulation and basic addition, subtraction, multiplication and division simulation
Original circuit diagram (addition, subtraction, multiplication and division are not included):
code:
//与门
module door(
input in1,
input in2,
output out
);
//连续赋值(逻辑描述)
assign out = in1 & in2;
//位置调用(结构描述)
// and (out, in1, in2);
endmodule
//或门
module door(
input in1,
input in2,
output out
);
//连续赋值(逻辑描述)
assign out = in1 | in2;
//位置调用(结构描述)
// or (out, in1, in2);
endmodule
//非门
module door(
input in,
output out
);
//连续赋值(逻辑描述)
assign out = ~ in;
//位置调用(结构描述)
// not (out, in1);
endmodule
//除此之外还有“nor”异或 “xnor”同或
//加减乘除
module door(
input in1,
input in2,
output out
);
assign out = in1 + in2; //1+1=0,1+0=1
assign out = in1 - in2; //0-1=1,1-1=0
assign out = in1 * in2; //0*1=0,1*1=1
assign out = in1 / in2; //1/1=1,当in1=1,in2=0和in1=0,in2=0时出现1/2
endmodule
(2), half adder and full adder
Design ideas reference link:
https://wuzhikai.blog.csdn.net/article/details/124116237
- half adder
A half adder is an adder operation circuit that adds two one-bit binary numbers and outputs "result" and "carry" accordingly.
main code:
//半加器
module add(
input in1, //加数1
input in2, //加数2
output sum, //两个数的加和
output cout //加数和的进位
);
//第一种方式
assign sum = in1 ^ in2;
assign cout = in1 & in2;
//第二种方式
assign {cout, sum} = in1 + in2;
endmodule
Testbench simulation code:
`timescale 1ns/1ns
module sim_add();
//输入reg定义
reg in1, in2;
//输出wire定义
wire cout, sum;
//给初始信号
initial begin
in1<=1'b0;
in2<=1'b0;
end
//↓写成令每10ns,产生一次随机输入
always #10 in1<= {$random} %2; //每10个时钟周期产生1个随机数
always #10 in2<= {$random} %2;
//创建模块
add adder(
.in1(in1),
.in2(in2),
.sum(sum),
.cout(cout)
);
endmodule
Its simulation circuit diagram (from left to right is the first and second):
ModelSim simulation waveform:
- Full Adder (link)
A full adder is a device that can add two one-bit binary data and output "result", "carry" and "low bit carry".
main code:
module add(
input in1, //加数1
input in2, //加数2
input cin, //低位向高位的进位
output sum, //两个数的加和
output cout //加数和的进位
);
assign {cout, sum} = in1 + in2 + cin;
endmodule
Testbench simulation code:
`timescale 1ns/1ns
module sim_add();
//输入reg定义
reg in1, in2, cin;
//输出wire定义
wire cout, sum;
//给初始信号
initial begin
in1<=1'b0;
in2<=1'b0;
cin<=1'b0;
end
//↓写成令每10ns,产生一次随机输入
always #10 in1<= {$random} %2; //每10个时钟周期产生1个随机数
always #10 in2<= {$random} %2;
always #10 cin<= {$random} %2;
//创建模块
add adder(
.in1(in1),
.in2(in2),
.cin(cin),
.sum(sum),
.cout(cout)
);
endmodule
Simulation circuit diagram:
ModelSim simulation waveform:
(3), Encoder and Decoder
- Encoder
An encoder is a device that converts a few-bit input signal into a specific multi-bit code.
8-3 Encoder design reference link:
main code:
//8-3编码器
module encode_decode(
input [7:0]in,
output reg [2:0]out
);
always @(*) begin
case (in)
8'b00000001: out = 3'b000;
8'b00000010: out = 3'b001;
8'b00000100: out = 3'b010;
8'b00001000: out = 3'b011;
8'b00010000: out = 3'b100;
8'b00100000: out = 3'b101;
8'b01000000: out = 3'b110;
8'b10000000: out = 3'b111;
endcase
end
endmodule
Testbench simulation code:
`timescale 1ns/1ns
module sim_encode_decode();
//输入reg定义
reg [7:0]in;
//输出wire定义
wire [2:0]out;
//给初始信号
initial begin
in[0] = 1;in[1] = 0;in[2] = 0;in[3] = 0;
in[4] = 0;in[5] = 0;in[6] = 0;in[7] = 0;
#100;
in= in << 1;
#100;
in= in << 1;
#100;
in= in << 1;
end
//创建模块
encode_decode encode(
.in(in[7:0]),
.out(out[2:0])
);
endmodule
Simulation circuit diagram (partial display):
ModelSim simulation waveform:
- Decoder (including 3-8 decoder and digital tube decoder)
A decoder is a device that converts a few-bit input signal into a specific multi-bit code.
Design reference link:
https://blog.csdn.net/quanqueen/article/details/113094663
>3-8 decoder main code:
//3-8译码器
module encode_decode(
input [2:0]in,
output reg [7:0]out
);
always @(*) begin
case (in)
3'b000: out = 8'b00000001;
3'b001: out = 8'b00000010;
3'b010: out = 8'b00000100;
3'b011: out = 8'b00001000;
3'b100: out = 8'b00010000;
3'b101: out = 8'b00100000;
3'b110: out = 8'b01000000;
3'b111: out = 8'b10000000;
endcase
end
endmodule
Testbench simulation code:
`timescale 1ns/1ns
module sim_encode_decode();
//输入reg定义
reg [2:0]in;
//输出wire定义
wire [7:0]out;
//给初始信号
initial in<=3'b0;
//↓写成令每10ns,产生一次随机输入
always #10 in<= {$random} %2;
//创建模块
encode_decode decode(
.in(in[2:0]),
.out(out[7:0])
);
endmodule
Simulation circuit diagram:
ModelSim simulation waveform:
Digital tube decoder :
The digital tube decoder is a kind of decoder for the digital tube display of the revolving door.
Design reference link:
https://blog.csdn.net/weixin_63090979/article/details/121106854
>The main code of the digital tube decoder:
//数码管编码器(共阳极)
module ni_tub_dec(
input [3:0]in,
output reg [7:0]out
);
always @(*) begin
case (in)
4'b0000: out = 8'b1100_0000;
4'b0001: out = 8'b1111_1001;
4'b0010: out = 8'b1010_0100;
4'b0011: out = 8'b1011_0000;
4'b0100: out = 8'b1001_1001;
4'b0101: out = 8'b1000_0010;
4'b0110: out = 8'b1100_0000;
4'b0111: out = 8'b1111_1000;
4'b1000: out = 8'b1000_0000;
4'b1001: out = 8'b1001_0000;
endcase
end
endmodule
Testbench simulation code:
`timescale 1ns/1ns
module sim_ni_tub_dec();
//输入reg定义
reg [3:0]in;
//输出wire定义
wire [7:0]out;
//给初始信号
initial begin
in = 4'd0;
#100;
in = 4'd1;
#100;
in = 4'd2;
#100;
in = 4'd3;
#100;
in = 4'd4;
#100;
in = 4'd5;
#100;
in = 4'd6;
#100;
in = 4'd7;
#100;
in = 4'd8;
#100;
in = 4'd9;
#100;
$stop;
end
//创建模块
ni_tub_dec decode(
.in(in[3:0]),
.out(out[7:0])
);
endmodule
Simulation circuit diagram:
ModelSim simulation waveform:
(5), data selector (choose one of the two)
A data selector is a device that outputs a corresponding signal based on a selected bit.
Design reference link:
https://blog.csdn.net/hyhop150/article/details/51222711
main code:
//二选一数据选择器
module dat_sel(
input in1,
input in2,
input sel,
output out
);
assign out = sel? in1:in2 ;
endmodule
Testbench simulation code:
`timescale 1ns/1ns
module sim_dat_sel();
//输入reg定义
reg in1, in2, sel;
//输出wire定义
wire out;
//给初始信号
initial begin
in1 <= 0;in2 <= 1;sel <= 0;
#100
in1 <= 1;in2 <= 0;sel <= 0;
#100
in1 <= 0;in2 <= 1;sel <= 1;
#100
in1 <= 1;in2 <= 0;sel <= 1;
#100
$stop;
end
//创建模块
dat_sel selector(
.in1(in1),
.in2(in2),
.sel(sel),
.out(out)
);
endmodule
Simulation circuit diagram:
ModelSim simulation waveform:
2. Sequential logic circuit
(1), registers and shift registers
- register
A device used to register data triggered by a clock edge.
Register design reference link:
https://blog.csdn.net/cjx_csdn/article/details/105203494
main code:
//基本寄存器
module rag_srag(
input in,
input clk,
output reg out
);
always @(posedge clk) begin
out = in;
end
endmodule
Testbench simulation code:
//基本寄存器
`timescale 1ns/1ns
module sim_rag_srag();
//输入reg定义
reg clk, in;
//输出wire定义
wire out;
//给初始信号
initial begin
in <= 0;clk <= 1;
#50
in <= 1;clk <= 1;
#50
in <= 0;clk <= 0;
#50
in <= 1;clk <= 0;
#50
$stop;
end
//创建模块
rag_srag rag(
.in(in),
.clk(clk),
.out(out)
);
endmodule
Simulation circuit diagram:
ModelSim simulation waveform:
- Shift Register
A register that is triggered by a clock edge and shifts the registered data left and right.
Design reference link:
https://reborn.blog.csdn.net/article/details/80377919
main code:
//移位寄存器(右)
module rag_srag(
input clk,
input [15:0]in,
output reg [15:0]out
);
always @(posedge clk) begin
out = {in[0], in[15:1]};
end
endmodule
Testbench simulation code:
//移位寄存器(16位)
`timescale 1ns/1ns
module sim_rag_srag();
//输入reg定义
reg clk;
reg [15:0]in;
//输出wire定义
wire [15:0]out;
always #50 clk = ~clk;
//给初始信号
initial begin
in =16'b0;clk = 1;
#50
in =16'b0000_0000_0000_0001;
#50
in =16'b1100_0000_0000_0011;
#50
in =16'b0011_0000_0000_1111;
#50
in =16'b0011_0000_0011_1111;
#50
in =16'b0011_0110_0000_1000;
#50
$stop;
end
//创建模块
rag_srag srag(
.in(in[15:0]),
.clk(clk),
.out(out[15:0])
);
endmodule
Simulation circuit diagram:
ModelSim simulation waveform:
(2), counter (decimal/24/60)
A device whose counting is triggered mainly by the edge signal of the clock.
Design reference link:
https://blog.csdn.net/weixin_43758368/article/details/101517017
main code:
//计数器(四位十进制)
//无输入,内定一个寄存器进行时钟上升沿计数,最后通过输出反映出来
module counter(
input clk,rst, //时钟,复位
output [3:0]out
);
reg [3:0]q;
assign out = q;
always @(posedge clk)
begin
if(rst==0)
q = 0;
else if(q>=4'd9)
q = 0;
else
q = q + 1;
end
endmodule
//计数器(五位二十四进制)
module counter(
input clk,rst, //时钟,复位
output [4:0]out
);
reg [4:0]q;
assign out = q;
always @(posedge clk)
begin
if(rst==0)
q = 0;
else if(q>=5'd24)
q = 0;
else
q = q + 1;
end
endmodule
//计数器(五位二十四进制)
module counter(
input clk,rst, //时钟,复位
output [5:0]out
);
reg [5:0]q;
assign out = q;
always @(posedge clk)
begin
if(rst==0)
q = 0;
else if(q>=6'd60)
q = 0;
else
q = q + 1;
end
endmodule
Testbench simulation code:
//计数器(十进制)
`timescale 1ns/1ns
module sim_counter();
//十进制定义
reg clk, rst;
wire [3:0]out;
//二十四进制定义
reg clk, rst;
wire [4:0]out;
//六十进制定义
reg clk, rst;
wire [5:0]out;
always #5 clk <= ~clk;
//给初始信号
initial begin
clk <= 0;rst <= 0;
#10;
rst <= 1;
end
//十进制模块
counter coun10(
.rst(rst),
.clk(clk),
.out(out[3:0])
);
//二十四进制模块
counter coun24(
.rst(rst),
.clk(clk),
.out(out[4:0])
);
//六十进制模块
counter coun60(
.rst(rst),
.clk(clk),
.out(out[5:0])
);
endmodule
Simulation circuit diagram:
(decimal)
(24 hexadecimal)
(sexadecimal)
ModelSim simulation waveform (example sexagesimal):
(3), frequency divider (two frequency / ten frequency)
A device used to generate a low clock frequency signal from an existing high clock frequency signal.
Design reference link:
https://blog.csdn.net/supenman_mwg/article/details/7654141
Main code (2/10 frequency):
//二分频
//使用复位仿照时钟由边沿改变输出信号,配合着原本的时钟,这就形成了二分的频率
module fre_div(
input clk,rst, //时钟,复位
output out_clk
);
reg q;
assign out_clk = q;
always @(posedge clk, posedge rst)
begin
if(rst==1)
q = 0;
else
q = ~q;
end
endmodule
//十分频
//需要定义一个计数器,计五个二分频
module fre_div(
input clk,rst, //时钟,复位
output out_clk
);
parameter N = 5;
reg [N-1:0]cnt; //计数器
reg q;
assign out_clk = q;
always @(posedge clk, posedge rst) begin
if(rst==1) begin
q <= 0;
cnt <= 0;
end
else begin
if(cnt>=N-1)begin
q <= ~q;
cnt <= 0;
end
else begin
cnt <= cnt + 1;
end
end
end
endmodule
Testbench simulation code:
//二分频/十分频
`timescale 1ns/1ns
module sim_fre_div();
reg clk, rst;
wire out_clk;
always #20 clk <= ~clk;
//给初始信号
initial begin
clk=0;rst=1;
#24 rst =0;
end
fre_div divider2(
.rst(rst),
.clk(clk),
.out_clk(out_clk)
);
endmodule
Simulation circuit diagram:
(two-way frequency)
(very often)
ModelSim simulation waveform:
(two-way frequency)
(very often)
3. State machine
State machine, the full name is finite state machine , is a sequential circuit that switches between finite states according to certain rules, and can be considered as a combination of combinational logic and sequential logic.
➢ Mealy state machine: the output of combinatorial logic depends not only on the current state, but also on the input state.
➢ Moore state machine: the output of combinatorial logic depends only on the current state.
State machine design reference link:
https://wuzhikai.blog.csdn.net/article/details/119421783
main code:
/**********<三段式状态机>*************/
//特点:在二段的基础上,再次细分,将输出的状态分离,形成划分明确的状态机
//------"摩尔型"-----//
//三段米勒型写法,同上段与摩尔的关系写法一样
module sta_mac(
input clk, //时钟信号
input rst, //复位信号(低电平有效)
input money, //投币信号(高电平有效)
output reg cola //可乐信号(高电平为出可乐)
);
//独热码定义(状态参数)
localparam Init = 4'b0001,
One_cin = 4'b0010,
Two_cin = 4'b0100,
There_cin= 4'b1000;
reg [3:0] curr_sta; //现态
reg [3:0] next_sta; //次态(相当于一个中间传递数据的寄存器)
//***第一段:同步时序"状态转移"
always @(posedge clk, negedge rst) begin
if(!rst)
curr_sta <= Init; //回到初始
else
curr_sta <= next_sta; //向现态传递次态数据
end
//***第二段:组合逻辑状态"转移条件"
always @(*) begin
case (curr_sta) // 依据现态情况转移状态
Init: begin //初始状态
if(money)
next_sta <= One_cin;
else
next_sta <= Init;
end
One_cin: begin //一个硬币状态
if(money)
next_sta <= Two_cin;
else
next_sta <= One_cin;
end
Two_cin: begin //二个硬币状态
if(money)
next_sta <= There_cin;
else
next_sta <= Two_cin;
end
There_cin: begin //三个硬币状态
if(money)
next_sta <= One_cin;
else
next_sta <= Init;
end
default: begin //其他情况,同初始状态
if(money)
next_sta <= One_cin;
else
next_sta <= Init;
end
endcase
end
//***第三段:各个"状态对应的输出情况"
always @(posedge clk, negedge rst) begin
if(!rst)
cola <= 1'b0;
else
case (curr_sta)
Init: cola <= 1'b0;
One_cin: cola <= 1'b0;
Two_cin: cola <= 1'b0;
There_cin: cola <= 1'b1;
default: cola <= 1'b0;
endcase
end
endmodule
Testbench simulation code:
//状态机仿真代码
`timescale 1ns/1ns
module sim_sta_mac();
reg clk; //时钟信号
reg rst; //复位信号
reg money; //投币信号
wire cola; //可乐信号
//建立模块
sta_mac machin_1duan(
.money(money),
.rst(rst),
.clk(clk),
.cola(cola)
);
//给初始信号
initial begin
clk = 1'b0; //初始时钟为0
rst <= 1'b0; //初始复位
money <= 1'b0; //投币初始化为0
#5
rst <= 1'b1; //拉高复位,系统进入工作状态
#25
money <= 1'b1; //拉高投币信号(投币)
#40
money <= 1'b0; //拉低投币信号(不投币)
#20
money <= 1'b1; //拉高投币信号(投币)
#80
money <= 1'b0; //拉低投币信号(不投币)
end
//给时钟信号
always #10 clk <= ~clk;
//状态名称查看器(看不了)
/*reg [71:0] state_name;
always @(*) begin
case (machin_1duan.state)
4'b0001: state_name = "Init";
4'b0010: state_name = "One_cin";
4'b0100: state_name = "Two_cin";
4'b1000: state_name = "There_cin";
default: state_name = "Init";
endcase
end*/
endmodule
State diagram:
Simulation circuit diagram:
ModelSim simulation waveform:
4. The last step is to do simulation experiments on the FPGA board
The advanced board experiment can be searched at station B: Wildfire FPGA