集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 1156|回复: 0

TLC5615 的FPGA驱动

[复制链接]
fpga_feixiang 发表于 2019-4-20 14:19:09 | 显示全部楼层 |阅读模式
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
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-4-30 20:22 , Processed in 0.056886 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表