FPGA basic self-study process

Table of contents

1. Quartus II and Modelsim software installation and cracking

2. Complete the basic circuit simulation

1. Combination logic circuit

(1) Basic NOR gate circuit simulation and basic addition, subtraction, multiplication and division simulation

(2), half adder and full adder

(3), Encoder and Decoder

(5), data selector (choose one of the two)

2. Sequential logic circuit

 (1), registers and shift registers

(2), counter (decimal/24/60)

(3), frequency divider (two frequency / ten frequency)

3. State machine


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:

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:

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=distribute.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

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

Guess you like

Origin blog.csdn.net/m0_56883893/article/details/126918807