|
module Da_Data_Module
(
//输入端口
CLK_50M,RST_N,
//输出端口
da_data,da_start
);
//---------------------------------------------------------------------------
//-- 外部端口声明
//---------------------------------------------------------------------------
input CLK_50M; //时钟端口,开发板用的50M晶振
input RST_N; //复位端口,低电平复位
output [9:0] da_data; //从ROM中读出的DA数据
output da_start; //DA模块的开始标志位
//---------------------------------------------------------------------------
//-- 内部端口声明
//---------------------------------------------------------------------------
reg [7:0] time_cnt; //计数器
reg [7:0] time_cnt_n; //time_cnt的下一个状态
reg [9:0] rom_addr; //rom的地址端口
reg [9:0] rom_addr_n; //rom_addr的下一个状态
reg da_start; //DA模块的开始标志位
reg da_start_n; //da_start的下一个状态
//---------------------------------------------------------------------------
//-- 逻辑功能实现
//---------------------------------------------------------------------------
//例化ROM模块
ROM ROM_Init
(
.address (rom_addr ), //rom的地址端口
.clock (CLK_50M ), //rom的时钟端口
.q (da_data[9:2] ) //rom的数据端口
);
//时序电路,用来给time_cnt寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
time_cnt <= 8'h0; //初始化time_cnt值
else
time_cnt <= time_cnt_n; //用来给time_cnt赋值
end
//1KHz的正弦波,周期为1ms,即1ms送出一个完整的512个点的波形
//每个点的时间是1 / 512 * 1000000(ns) 我们采用开发板上的50Mhz晶振系统周期为20ns
//FPGA内部的计数器值为 1 / 512 * 1000000(ns) / 20 = 97
always @ (*)
begin
if(time_cnt == 8'd96) //判断计数器是否到97,从0开始即96
time_cnt_n = 8'h0; //如果到97就将time_cnt_n置0
else
time_cnt_n = time_cnt + 8'h1; //否则,time_cnt_n加1
end
//时序电路,用来给rom_addr寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
rom_addr <= 10'h0; //初始化time_cnt值
else
rom_addr <= rom_addr_n; //用来给time_cnt赋值
end
//组合电路,发送一个完整的512个点的波形,我们的mif文件中有1024个点
always @ (*)
begin
if(time_cnt == 8'd96) //判断计数器是否到97,从0开始即96
rom_addr_n = rom_addr + 10'h2;//如果到97,rom_addr_n加2,1024 / 2 = 512
else
rom_addr_n = rom_addr; //否则保持不变
end
//时序电路,用来给da_start寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
da_start <= 1'h0; //初始化da_start值
else
da_start <= da_start_n; //用来给da_start赋值
end
//组合电路,生成DA工作开始标识
always @ (*)
begin
if(time_cnt == 8'h0) //判断计数器的值
da_start_n = 1'h1; //如果计数器为0,标识为1
else
da_start_n = 1'h0; //否则计数器则为0
end
assign da_data[1:0] = 2'h0; //给da_data低两位赋值
endmodule
module Da_Module
(
//输入端口
CLK_50M,RST_N,
//TLC5615输出管脚
DA_CLK,DA_DIN,DA_CS,
//用户逻辑输入与输出
DA_DATA,send_start,send_finish
);
//---------------------------------------------------------------------------
//-- 外部端口声明
//---------------------------------------------------------------------------
input CLK_50M; //时钟的端口,开发板用的50M晶振
input RST_N; //复位的端口,低电平复位
output reg DA_CLK; //DA时钟端口
output DA_DIN; //DA数据输出端口
output reg DA_CS; //DA片选端口
input [ 9:0] DA_DATA; //DA数据的输入
input send_start; //DA工作开始标识
output send_finish; //DA工作完成标识
//---------------------------------------------------------------------------
//-- 内部端口声明
//---------------------------------------------------------------------------
reg [ 3:0] FSM_CS; //状态机的当前状态
reg [ 3:0] FSM_NS; //状态机的下一个状态
reg [ 3:0] bit_cnt; //用来记录数据发送个数的计数器
reg [ 3:0] bit_cnt_n; //bit_cnt的下一个状态
reg [11:0] shift_reg; //移位寄存器,将最高位数据移给DA_DIN
reg [11:0] shift_reg_n; //shift_reg的下一个状态
reg [ 3:0] time_cnt; //用于记录时钟个数的计数器
reg [ 3:0] time_cnt_n; //time_cnt的下一个状态
reg DA_CLK_N; //DA_CLK的下一个状态
reg DA_CS_N; //DA_CS的下一个状态
parameter FSM_IDLE = 4'h0; //状态机的空闲状态
parameter FSM_READY = 4'h1; //状态机的准备状态,将CS拉低
parameter FSM_SEND = 4'h2; //状态机的发送状态,发送12个数据
parameter FSM_FINISH= 4'h4; //状态的完成状态,将CS拉高
//---------------------------------------------------------------------------
//-- 逻辑功能实现
//---------------------------------------------------------------------------
//时序电路,用来给time_cnt寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
time_cnt <= 4'h0; //初始化time_cnt值
else
time_cnt <= time_cnt_n; //用来给time_cnt赋值
end
//组合电路,用于记录时钟个数的计数器
always @ (*)
begin
if(FSM_CS != FSM_NS) //判断状态机的当前状态
time_cnt_n = 4'h0; //如果当前的状态不等于下一个状态,计数器就清零
else if(DA_CLK != DA_CLK_N) //判断时钟的当前状态
time_cnt_n = 4'h0; //如果当前的时钟不等于下一个时钟状态,计数器清零
else
time_cnt_n = time_cnt + 4'h1;//否则计数器就加1
end
//时序电路,用来给bit_cnt寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
bit_cnt <= 4'h0; //初始化bit_cnt值
else
bit_cnt <= bit_cnt_n; //用来给bit_cnt赋值
end
//组合电路,用来记录数据发送个数的计数器
always @ (*)
begin
if(FSM_CS == FSM_FINISH) //判断状态机的当前状态
bit_cnt_n = 4'h0; //如果当前的状态不等于完成状态,bit_cnt_n就置0
else if(DA_CLK && (!DA_CLK_N)) //判断时钟的当前状态
bit_cnt_n = bit_cnt + 4'h1;//如果当前的时钟等于下一个时钟取非的状态,bit_cnt_n就加1
else
bit_cnt_n = bit_cnt; //否则保持不变
end
//时序电路,用来给shift_reg寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
shift_reg <= 12'h0; //初始化shift_reg值
else
shift_reg <= shift_reg_n; //用来给shift_reg赋值
end
//组合电路,移位寄存器,将DA_DATA的数据依次移给DA_DIN
always @ (*)
begin
if(send_start) //判断开始标识
shift_reg_n = {DA_DATA,2'h0};//如果标志为1,则将DA_DATA的数据赋值给移位寄存器
else if(DA_CLK && (time_cnt == 4'h0))//判断DA_CLK的状态
shift_reg_n = {shift_reg[10:0] , 1'h0};//如果DA_CLK为高,移位寄存器开始移位
else
shift_reg_n = shift_reg; //否则保持不变
end
//---------------------------------------------------------------------------
//-- 状态机
//---------------------------------------------------------------------------
//时序电路,用来给FSM_CS寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
FSM_CS <= FSM_IDLE; //初始化FSM_CS值
else
FSM_CS <= FSM_NS; //用来给FSM_CS赋值
end
//组合电路,用来实现状态机
always @ (*)
begin
case(FSM_CS) //判断状态机的当前状态
FSM_IDLE:
if(send_start) //判断开始标识
FSM_NS = FSM_READY; //如果标识符为1,则进入准备状态
else
FSM_NS = FSM_CS; //否则保持原状态不变
FSM_READY:
if(time_cnt == 4'h1) //等待两个时钟
FSM_NS = FSM_SEND; //两个时钟到了便进入发送状态
else
FSM_NS = FSM_CS; //否则保持原状态不变
FSM_SEND:
if((bit_cnt == 4'hC)&&(!DA_CLK))//发送数据12个
FSM_NS = FSM_FINISH; //发送完成进入完成状态
else
FSM_NS = FSM_CS; //否则保持原状态不变
FSM_FINISH:
if(time_cnt == 4'h2) //等待三个时钟
FSM_NS = FSM_IDLE; //完成一次数据转换,进入下一次转换
else
FSM_NS = FSM_CS; //否则保持原状态不变
default:FSM_NS = FSM_IDLE;
endcase
end
//时序电路,用来给DA_CS寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
DA_CS <= 1'h1; //初始化DA_CS值
else
DA_CS <= DA_CS_N; //用来给DA_CS赋值
end
//组合电路,用来生成DA的片选波形
always @ (*)
begin
if(FSM_CS == FSM_READY) //判断状态机的当前状态
DA_CS_N = 1'h0; //如果当前的状态等于准备状态,DA_CS_N就置0
else if((FSM_CS == FSM_FINISH) && (time_cnt == 4'h1))//判断状态机的当前状态
DA_CS_N = 1'h1; //如果当前的状态等于完成状态并且时钟计数器等于1,DA_CS_N就置1
else
DA_CS_N = DA_CS; //否则保持不变
end
//时序电路,用来给DA_CLK寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
DA_CLK <= 1'h0; //初始化DA_CLK值
else
DA_CLK <= DA_CLK_N; //用来给DA_CLK赋值
end
//组合电路,用来生成DA的时钟波形
always @ (*)
begin
if((FSM_CS == FSM_SEND) && (!DA_CLK) && (time_cnt == 4'h1))//判断状态机的当前状态
DA_CLK_N = 1'h1; //如果符合上述条件,每两个时钟就会生成一个高电平的DA_CLK
else if((FSM_CS == FSM_SEND) && (DA_CLK) && (time_cnt == 4'h1))//判断状态机的当前状态
DA_CLK_N = 1'h0; //如果符合上述条件,每两个时钟就会生成一个低电平的DA_CLK
else
DA_CLK_N = DA_CLK; //否则保持不变
end
assign DA_DIN = shift_reg[11]; //将移位寄存器的最高位赋值给DA_DIN
assign send_finish = (FSM_CS == FSM_IDLE); //标识发送完成
endmodule
|
|