Table des matières
1. Installation et crackage des logiciels Quartus II et Modelsim
2. Terminez la simulation de circuit de base
(2), demi-additionneur et additionneur complet
(5), sélecteur de données (choisissez l'un des deux)
(1), registres et registres à décalage
(3), diviseur de fréquence (deux fréquences/dix fréquences)
1. Installation et crackage des logiciels Quartus II et Modelsim
(Remarques : si la puce est EP2XXX, alors la programmation correspondante utilise Cyclone II ou la version suivante . Cette version n'est prise en charge que dans Quartus13.0 et versions antérieures, tandis que EP4XXX et versions ultérieures sont applicables à Quartus13.0 et versions ultérieures.)
Lien du package d'installation Quartus13.0 :
http://Lien : https://pan.baidu.com/s/1TvCEyduApTvVlgcFJO9h_g Code d'extraction : 6666.
Lien du didacticiel d'installation de Quartus13.0 :
https://blog.csdn.net/pang9998/article/details/83447190
Package d'installation Quartus18.0 et liens vers le didacticiel :
https://mp.weixin.qq.com/s/m1sFpNMR79V0Mk81axJ22Q
2. Terminez la simulation de circuit de base
1. Circuit logique combiné
(1) Simulation de base du circuit de porte NOR et simulation de base de l'addition, de la soustraction, de la multiplication et de la division
Schéma de circuit original (l'addition, la soustraction, la multiplication et la division ne sont pas incluses) :
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), demi-additionneur et additionneur complet
Lien de référence des idées de conception :
https://wuzhikai.blog.csdn.net/article/details/124116237
- demi-additionneur
Un demi-additionneur est un circuit d'opération d'additionneur qui ajoute deux nombres binaires d'un bit et génère « résultat » et « carry » en conséquence.
Code principal:
//半加器
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
Code de simulation du banc de test :
`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
Son schéma de circuit de simulation (de gauche à droite le premier et le deuxième) :
Forme d'onde de simulation ModelSim :
- Additionneur complet (lien)
Un additionneur complet est un appareil qui peut ajouter deux données binaires d'un bit et produire un « résultat », un « report » et un « report de bit faible ».
Code principal:
module add(
input in1, //加数1
input in2, //加数2
input cin, //低位向高位的进位
output sum, //两个数的加和
output cout //加数和的进位
);
assign {cout, sum} = in1 + in2 + cin;
endmodule
Code de simulation du banc de test :
`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
Schéma du circuit de simulation :
Forme d'onde de simulation ModelSim :
(3), encodeur et décodeur
- Encodeur
Un encodeur est un appareil qui convertit un signal d'entrée de quelques bits en un code multi-bits spécifique.
8-3 Lien de référence sur la conception du codeur :
Code principal:
//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
Code de simulation du banc de test :
`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
Schéma de circuit de simulation (affichage partiel) :
Forme d'onde de simulation ModelSim :
- Décodeur (y compris décodeur 3-8 et décodeur à tube numérique)
Un décodeur est un appareil qui convertit un signal d'entrée de quelques bits en un code multi-bits spécifique.
Lien de référence de conception :
https://blog.csdn.net/quanqueen/article/details/113094663
>3-8 code principal du décodeur :
//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
Code de simulation du banc de test :
`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
Schéma du circuit de simulation :
Forme d'onde de simulation ModelSim :
Décodeur numérique à tubes :
Le décodeur numérique à tube est une sorte de décodeur pour l'affichage numérique à tube de la porte tournante.
Lien de référence de conception :
https://blog.csdn.net/weixin_63090979/article/details/121106854
>Le code principal du décodeur de tube numérique :
//数码管编码器(共阳极)
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
Code de simulation du banc de test :
`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
Schéma du circuit de simulation :
Forme d'onde de simulation ModelSim :
(5), sélecteur de données (choisissez l'un des deux)
Un sélecteur de données est un appareil qui émet un signal correspondant basé sur un bit sélectionné.
Lien de référence de conception :
https://blog.csdn.net/hyhop150/article/details/51222711
Code principal:
//二选一数据选择器
module dat_sel(
input in1,
input in2,
input sel,
output out
);
assign out = sel? in1:in2 ;
endmodule
Code de simulation du banc de test :
`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
Schéma du circuit de simulation :
Forme d'onde de simulation ModelSim :
2. Circuit logique séquentiel
(1), registres et registres à décalage
- registre
Un appareil utilisé pour enregistrer des données déclenchées par un front d’horloge.
Lien de référence de conception d'enregistrement :
https://blog.csdn.net/cjx_csdn/article/details/105203494
Code principal:
//基本寄存器
module rag_srag(
input in,
input clk,
output reg out
);
always @(posedge clk) begin
out = in;
end
endmodule
Code de simulation du banc de test :
//基本寄存器
`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
Schéma du circuit de simulation :
Forme d'onde de simulation ModelSim :
- Registre à décalage
Un registre qui est déclenché par un front d'horloge et décale les données enregistrées vers la gauche et la droite.
Lien de référence de conception :
https://reborn.blog.csdn.net/article/details/80377919
Code principal:
//移位寄存器(右)
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
Code de simulation du banc de test :
//移位寄存器(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
Schéma du circuit de simulation :
Forme d'onde de simulation ModelSim :
(2), compteur (décimal/24/60)
Un appareil dont le comptage est déclenché principalement par le signal de front de l'horloge.
Lien de référence de conception :
https://blog.csdn.net/weixin_43758368/article/details/101517017
Code principal:
//计数器(四位十进制)
//无输入,内定一个寄存器进行时钟上升沿计数,最后通过输出反映出来
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
Code de simulation du banc de test :
//计数器(十进制)
`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
Schéma du circuit de simulation :
(décimal)
(24 hexadécimal)
(sexadécimal)
Forme d'onde de simulation ModelSim (exemple sexagésimal) :
(3), diviseur de fréquence (deux fréquences/dix fréquences)
Un dispositif utilisé pour générer un signal à basse fréquence d'horloge à partir d'un signal à haute fréquence d'horloge existant.
Lien de référence de conception :
https://blog.csdn.net/supenman_mwg/article/details/7654141
Code principal (fréquence 2/10) :
//二分频
//使用复位仿照时钟由边沿改变输出信号,配合着原本的时钟,这就形成了二分的频率
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
Code de simulation du banc de test :
//二分频/十分频
`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
Schéma du circuit de simulation :
(fréquence bidirectionnelle)
(très souvent)
Forme d'onde de simulation ModelSim :
(fréquence bidirectionnelle)
(très souvent)
3. Machine à états
Machine à états, le nom complet est machine à états finis , est un circuit séquentiel qui bascule entre des états finis selon certaines règles et peut être considéré comme une combinaison de logique combinatoire et de logique séquentielle.
➢ Machine à états Mealy : la sortie de la logique combinatoire dépend non seulement de l'état actuel, mais aussi de l'état d'entrée.
➢ Machine à états de Moore : la sortie de la logique combinatoire dépend uniquement de l'état actuel.
Lien de référence sur la conception de la machine d'état :
https://wuzhikai.blog.csdn.net/article/details/119421783
Code principal:
/**********<三段式状态机>*************/
//特点:在二段的基础上,再次细分,将输出的状态分离,形成划分明确的状态机
//------"摩尔型"-----//
//三段米勒型写法,同上段与摩尔的关系写法一样
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
Code de simulation du banc de test :
//状态机仿真代码
`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
Diagramme d'état :
Schéma du circuit de simulation :
Forme d'onde de simulation ModelSim :
4. La dernière étape consiste à faire des expériences de simulation sur la carte FPGA
L'expérience de carte avancée peut être recherchée à la station B : Wildfire FPGA