FPGA基礎独習の流れ

目次

1. Quartus II および Modelsim ソフトウェアのインストールとクラッキング

2. 基本的な回路シミュレーションを完了する

1. 組み合わせ論理回路

(1) 基本的な NOR ゲート回路シミュレーションと基本的な加減乗除シミュレーション

(2)、半加算器と全加算器

(3)、エンコーダとデコーダ

(5)、データセレクター(2つのうち1つを選択)

2. 順序論理回路

 (1)、レジスタとシフトレジスタ

(2)、カウンタ(10進数/24/60)

(3)、分周器(2周波/10周波)

3. ステートマシン


1. Quartus II および Modelsim ソフトウェアのインストールとクラッキング

(注: チップがEP2XXX の場合、対応するプログラミングはCyclone IIまたは次のバージョンを使用します。このバージョンは Quartus13.0 以下でのみサポートされますが、EP4XXX 以降は Quartus13.0 以降に適用されます。)

Quartus13.0 インストールパッケージのリンク:

http://リンク: https://pan.baidu.com/s/1TvCEyduApTvVlgcFJO9h_g    抽出コード: 6666。

Quartus13.0 インストールチュートリアルのリンク:

https://blog.csdn.net/pang9998/article/details/83447190

Quartus18.0 インストール パッケージとチュートリアルのリンク:

https://mp.weixin.qq.com/s/m1sFpNMR79V0Mk81axJ22Q

2. 基本的な回路シミュレーションを完了する

1. 組み合わせ論理回路

(1) 基本的な NOR ゲート回路シミュレーションと基本的な加減乗除シミュレーション

元の回路図 (加算、減算、乗算、除算は含まれていません):

コード:

//与门
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)、半加算器と全加算器

デザインアイデアの参考リンク:

https://wuzhikai.blog.csdn.net/article/details/124116237

  • 半加算器

半加算器は、1ビットの2進数を2つ加算し、「結果」と「桁上げ」を出力する加算演算回路です。

メインコード:

//半加器
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

テストベンチのシミュレーション コード:

`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

そのシミュレーション回路図 (左から右に 1 番目と 2 番目):

 ModelSim シミュレーション波形:

全加算器は、2つの1ビットバイナリデータを加算し、「結果」、「キャリー」、「下位ビットキャリー」を出力できるデバイスです。

メインコード:

module add(
	input in1,  //加数1
	input in2,	//加数2
	input cin,  //低位向高位的进位
	output sum, //两个数的加和
	output cout //加数和的进位
);
	assign {cout, sum} = in1 + in2 + cin;

endmodule

テストベンチのシミュレーション コード:

`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

シミュレーション回路図:

ModelSim シミュレーション波形:

 

(3)、エンコーダとデコーダ

  • エンコーダ

エンコーダは、数ビットの入力信号を特定のマルチビット コードに変換するデバイスです。

8-3 エンコーダ設計のリファレンスリンク:

https://blog.csdn.net/Ding_ding_fly/article/details/54882615?ops_request_misc=&request_id=&biz_id=102&utm_term=8-3%E7%BC%96%E7%A0%81%E5%99%A8&utm_medium=配布。 pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-54882615.142^v47^pc_rank_34_1,201^v3^control_2&spm=1018.2226.3001.4187

メインコード:

//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

テストベンチのシミュレーション コード:

`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

シミュレーション回路図(一部表示):

ModelSim シミュレーション波形:

  • デコーダ(3-8デコーダおよびデジタルチューブデコーダを含む)

デコーダは、数ビットの入力信号を特定のマルチビット コードに変換するデバイスです。

設計参照リンク:

https://blog.csdn.net/quanqueen/article/details/113094663

>3-8 デコーダのメインコード:

//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

テストベンチのシミュレーション コード:

`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

シミュレーション回路図:

ModelSim シミュレーション波形:

デジタル真空管デコーダ:

デジタル管デコーダは、回転ドアのデジタル管表示用のデコーダの一種です。

設計参照リンク:

https://blog.csdn.net/weixin_63090979/article/details/121106854

>デジタル真空管デコーダのメインコード:

//数码管编码器(共阳极)
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

テストベンチのシミュレーション コード:

`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

シミュレーション回路図:

ModelSim シミュレーション波形:

(5)、データセレクター(2つのうち1つを選択)

データセレクターは、選択されたビットに基づいて対応する信号を出力するデバイスです。

設計参照リンク:

https://blog.csdn.net/hyhop150/article/details/51222711

メインコード:

//二选一数据选择器
module dat_sel(
	input   in1,
	input   in2,
	input   sel,
	output  out 
);
	
	assign out = sel? in1:in2 ; 
	
endmodule

テストベンチのシミュレーション コード:

`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

シミュレーション回路図:

ModelSim シミュレーション波形:

2. 順序論理回路

 (1)、レジスタと シフトレジスタ

  • 登録する

クロックエッジによってトリガーされたデータを登録するために使用されるデバイス。

 レジスタ設計参照リンク:

https://blog.csdn.net/cjx_csdn/article/details/105203494

メインコード:

//基本寄存器
module rag_srag(
	input   in,
	input   clk,
	output  reg out 
);

	always @(posedge clk) begin
		out = in;
	end
	
endmodule

テストベンチのシミュレーション コード:

//基本寄存器
`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

シミュレーション回路図:

ModelSim シミュレーション波形:

  • シフトレジスタ

クロックエッジによってトリガされ、登録されたデータを左右に​​シフトするレジスタ。

設計参照リンク:

https://reborn.blog.csdn.net/article/details/80377919

メインコード:

//移位寄存器(右)
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

テストベンチのシミュレーション コード:

//移位寄存器(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

シミュレーション回路図:

ModelSim シミュレーション波形:

(2)、カウンタ(10進数/24/60)

主にクロックのエッジ信号によってカウントが開始されるデバイス。

設計参照リンク:

https://blog.csdn.net/weixin_43758368/article/details/101517017

メインコード:

//计数器(四位十进制)
//无输入,内定一个寄存器进行时钟上升沿计数,最后通过输出反映出来
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

テストベンチのシミュレーション コード:

//计数器(十进制)
`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

シミュレーション回路図:

(10進数)

(16進数24)

(16進数)

 ModelSim シミュレーション波形 (60 進数の例):

(3)、分周器(2周波/10周波)

既存の高クロック周波数信号から低クロック周波数信号を生成するために使用されるデバイス。

設計参照リンク:

https://blog.csdn.net/supenman_mwg/article/details/7654141

メインコード (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

テストベンチのシミュレーション コード:

//二分频/十分频
`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

シミュレーション回路図:

(双方向周波数)

(よく)

ModelSim シミュレーション波形:

(双方向周波数)

(よく)

3. ステートマシン

ステートマシンは、正式名は有限状態マシンといい、ある規則に従って有限状態を切り替える順序回路であり、組み合わせ論理と順序論理を組み合わせたものと考えることができます。
➢ Mealy ステート マシン: 組み合わせロジックの出力は、現在の状態だけでなく入力状態にも依存します。
➢ ムーア ステート マシン: 組み合わせロジックの出力は現在の状態にのみ依存します。
 

 ステート マシン設計のリファレンス リンク:

https://wuzhikai.blog.csdn.net/article/details/119421783

メインコード:

/**********<三段式状态机>*************/
//特点:在二段的基础上,再次细分,将输出的状态分离,形成划分明确的状态机
//------"摩尔型"-----//
//三段米勒型写法,同上段与摩尔的关系写法一样
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

テストベンチのシミュレーション コード:

//状态机仿真代码
`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

状態図:

シミュレーション回路図:

ModelSim シミュレーション波形:

4. 最後のステップは、FPGA ボード上でシミュレーション実験を行うことです。

高度なボード実験はステーション B で検索できます: Wildfire FPGA

おすすめ

転載: blog.csdn.net/m0_56883893/article/details/126918807