热度 1| |
数字电路设计
RTL设计所需要的理论知识庞杂而繁多,本文所介绍的内容均由个人参阅了许多书籍之后加以整合的,很多内容本人也不是很熟,只是罗列出来作为参考学习的资料。主要有三个部分的内容,第一部分主要是数字电路设计的基础,这是在大学时期应该予以掌握的内容,第二部分是进阶的学习内容附带一个专业方向——MCU,第三部分是有关于各类算法处理的专业知识,需要更多的复合型知识,例如通信方向需要有较好的数学功底—傅立叶变换。由于这部分内容实在太多,个人没有能力也没有必要将每一部分的内容都详细的罗列出来,所以这里只是整理出一些需要把握的关键点。至于具体的内容,还请大家按照个人需求,参阅推荐的各类书籍。
一、基础
组合逻辑与时序逻辑:布尔代数,卡诺图,基本与非门,锁存器,触发器,冲突与冒险。——《Verilog HDL高级数字设计》
Verilog语言基础:数值类型,表达式与运算符,assign语句,always语句,if-else语句,case语句,阻塞与非阻塞。——《Verilog HDL 硬件描述语言》
状态机:一段式、二段式、三段式状态机的区别;独热码、二进制码、格雷码的区别及应用场合。——《Verilog HDL高级数字设计》
同步电路和异步电路:两者的本质,异步电路跨时钟域,亚稳态。——IC_learner博客
复位与时钟:同步复位、异步复位、异步复位同步释放的区别,时钟分频——二分频、三分频、任意整数分频,门控时钟,时钟切换。——《深入浅出玩转FPGA》,百度文档
数据通路与控制通路:本质上任何数字电路都可以划分为简单的两种类型——控制通路与数据通路,控制通路的核心是状态机,数据通路是各类算术处理算法、并行总线等等。——《Verilog HDL高级数字设计》
Testbench验证:无论什么电路,最终都需要验证其功能的正确性。Testbench的结构主要由a,复位和时钟,b,激励产生电路,c,系统监视器,d,结果比较电路,e,波形产生函数,f,待验证的MODULE等主要模块组成,其中,b是最重要的模块,一切验证都是从激励信号开始的。——《verilogHDL代码风格规范》。初学者推荐使用windows版qustasim 或者modelsim 仿真工具,简单又方便,以后可学习使用VCS+Verdi(比较折腾人)。
二、进阶
代码风格:良好的代码风格很有必要,参考一下企业用的代码风格,有助于个人养成良好的编码习惯。——《企业用verilog代码风格规范》《verilog语言编码风格》
基本常用电路:具备以上庞杂的理论基础之后,需要积累一些常用的基础电路。——《华为Verilog典型电路设计》
接口电路,I2C,UART,SPI:接口电路是中小规模芯片常用的对外接口电路,无论是与上位机(PC)通信还是控制其它芯片。I2C从机常用于EEPROM芯片中,主机可以直接使用单片机模拟,ARM单片机直接集成了I2C主机,I2C的IP代码网络上有现成的;UART是全双工电路,宏晶单片机通过UART进行烧录,SPI电路最常用于SD卡上。——《Verilog HDL高级数字设计》《通信IC设计(上下册)》有简单的UART和SPI的代码。
RISC,8051 MCU ——IP:通过下载EETOP上相关的IP及文档来学习。
三、专业
数值的表示方法:浮点数,定点数的表示办法——《Verilog HDL高级数字设计》《通信IC设计(上下册)》
算术处理算法:浮点数的加法、乘法电路设计。——《Verilog HDL高级数字设计》
通信算法:FIR滤波器,IIR滤波器,傅立叶变换,冗余编码等等各种通信方向必须掌握的。——《通信IC设计(上下册)》《数字信号处理的FPGA实现》
图像处理算法:静态图像,动态图像去噪。——《数字图像处理与图像通信》
SOC:SOC类芯片的组成结构,AMBA总线,IP复用,SV验证。——《Soc设计方法与实现》
四、工具:
文档代码编辑器:GVIM,Notpad++
RTL设计规则检查:Nlin,spyglass
五、示例
下列代码为UART全双工串口示例代码,代码来源于《Verilog HDL高级数字设计》,随后的章节将会使用到该示例代码,代码功能细节需结合书籍了解。
下面的代码已经过modelsim验证。
UART发送器:
module UART_XMTR #(
parameter word_size = 8
)(
output Serial_out,
input [word_size - 1 : 0] Data_Bus,
input Load_XMT_datareg,
Byte_ready,
T_byte,
Clock,
rst_b
);
Control_Unit M0( Load_XMT_DR,
Load_XMT_shftreg,start,shift,clear,
Load_XMT_datareg,Byte_ready,T_byte,BC_lt_Bcmax,
Clock,rst_b);
Datapath_Unit M1(
Serial_out,BC_lt_Bcmax,Data_Bus,Load_XMT_DR,
Load_XMT_shftreg,start,shift,clear,Clock,rst_b);
endmodule
module Control_Unit #(
parameter one_hot_count = 3,
state_count = one_hot_count,
size_bit_count =
3,
idle = 3'b001,
waiting = 3'b010,
sending = 3'b100
// all_ones = 9'b1_1111_11111
)(
output reg Load_XMT_DR,
output reg Load_XMT_shftreg,
output reg start,
output reg shift,
output reg clear,
input Load_XMT_datareg,
input Byte_ready,
input T_byte,
input BC_lt_Bcmax,
input Clock,
input rst_b
);
reg [state_count - 1 :
0] state, next_state;
always @(state, Load_XMT_datareg,Byte_ready,T_byte,BC_lt_Bcmax)
begin:Output_and_next_state
Load_XMT_DR = 0;
Load_XMT_shftreg = 0;
start = 0;
shift = 0;
clear = 0;
next_state = idle;
case(state)
idle: if(Load_XMT_datareg == 1'b1)begin
Load_XMT_DR = 1;
next_state =
idle;
end
else if(Byte_ready
== 1'b1)begin
Load_XMT_shftreg
= 1;
next_state =
waiting;
end
waiting: if(T_byte == 1)
begin
start = 1;
next_state
=sending;
end else
next_state =
waiting;
sending: if(BC_lt_Bcmax)
begin
shift = 1;
next_state =
sending;
end
else begin
clear = 1;
next_state =
idle;
end
default: next_state = idle;
endcase
end
always @(posedge Clock,negedge rst_b)
begin: State_Transitions
if(rst_b == 1'b0)
state <= idle;
else
state <= next_state;
end
endmodule
module Datapath_Unit #(
parameter word_size = 8,
size_bit_count =
3,
all_ones = 9'b1_1111_1111
)(
output Serial_out,
BC_lt_Bcmax,
input [word_size -1:0]
Data_Bus,
input Load_XMT_DR,
input Load_XMT_shftreg,
input start,
input shift,
input clear,
input Clock,
input rst_b
);
reg [word_size -1:0] XMT_datareg;
reg [word_size :0] XMT_shftreg;
reg [size_bit_count:0]
bit_count;
assign Serial_out =
XMT_shftreg [0];
assign BC_lt_Bcmax = (bit_count < word_size +1);
always @(posedge Clock,negedge rst_b)
if(rst_b == 0)
begin
XMT_shftreg <=
all_ones;
XMT_datareg <=
9'b0_0000_0000;
bit_count <= 0;
end
else
begin:Register_Transfers
if(Load_XMT_DR == 1'b1)
XMT_datareg <= Data_Bus;
if(Load_XMT_shftreg ==
1'b1)
XMT_shftreg <= {XMT_datareg,1'b1};
if(start == 1'b1)
XMT_shftreg[0] <= 0;
if(clear == 1'b1)
bit_count <= 0;
if(shift ==1'b1)
begin
XMT_shftreg <= {1'b1,XMT_shftreg[word_size:1]};
bit_count <= bit_count + 1;
end
end
endmodule
UART接收器:
module UART_RCVR #(
parameter word_size = 8,
half_word
=word_size/2
)(
output [word_size - 1 :0]
RCV_datareg,
output read_not_ready_out,
Error1,Error2,
input Serial_in,
read_not_ready_in,
Sample_clk,
rst_b
);
Control_Unit2 M0(
read_not_ready_out,Error1,Error2,
clr_Sample_counter,inc_Sample_counter,
clr_Bit_counter,inc_Bit_counter,shift,
load,read_not_ready_in,Ser_in_0,SC_eq_3,
SC_lt_7,BC_eq_8,Sample_clk,rst_b);
Datapath_Unit2 M1(
RCV_datareg,Ser_in_0,SC_eq_3,SC_lt_7,
BC_eq_8,Serial_in,clr_Sample_counter,
inc_Sample_counter,clr_Bit_counter,
inc_Bit_counter,shift,load,Sample_clk,rst_b);
endmodule
module Control_Unit2 #(
parameter word_size = 8,
half_word = word_size/2,
Num_state_bits = 2,
idle = 2'b00,
starting =
2'b01,
receiving = 2'b10
)(
output reg
read_not_ready_out,
Error1,Error2,
clr_Sample_counter,
inc_Sample_counter,
clr_Bit_counter,
inc_Bit_counter,
shift,
load,
input read_not_ready_in,
Ser_in_0,
SC_eq_3,
SC_lt_7,
BC_eq_8,
Sample_clk,
rst_b
);
reg [word_size - 1 :0] RCV_shftreg;
reg [Num_state_bits - 1 : 0]
state;
reg [Num_state_bits - 1 :
0] next_state;
always @(posedge Sample_clk or negedge rst_b)
if(rst_b == 1'b0)
state <= idle;
else
state <= next_state;
always @(state,Ser_in_0,SC_eq_3,SC_lt_7,read_not_ready_in)
begin
read_not_ready_out = 0;
clr_Sample_counter = 0;
clr_Bit_counter = 0;
inc_Sample_counter = 0;
inc_Bit_counter = 0;
shift = 0;
Error1 = 0;
Error2 = 0;
load = 0;
next_state = idle;
case(state)
idle: if(Ser_in_0 == 1'b1)
next_state = starting;
else
next_state = idle;
starting: if(Ser_in_0
==1'b0)
begin
next_state = idle;
clr_Sample_counter = 1;
end else
if(SC_eq_3 ==
1'b1)
begin
next_state = receiving;
clr_Sample_counter = 1;
end
else begin
inc_Sample_counter
= 1;
next_state = starting;
end
receiving: if(SC_lt_7 ==
1'b1)
begin
inc_Sample_counter = 1;
next_state = receiving;
end
else begin
clr_Sample_counter = 1;
if(!BC_eq_8)
begin
&nb