首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

发点CH451芯片控制的代码,详细讲解,正规代码!!!!

发点CH451芯片控制的代码,详细讲解,正规代码!!!!

FPGA应用于很多场合。比如通信,验证,接口控制。
接口比较多,相对多个PLD来说,成本和速度节省。
CH451资料比较多,上网可以下载。
具体分析下怎么用FPGA写这些控制。


第一个阅读器件,了解器件初始化过程,以及显示数据具体过程。也就是说一个芯片工作应该经过什么的过程,才能正常工作。
第二个写状态机。接口控制,很多都是状态机。状态机包括两个方面,一个整体数据控制,另一个是内部数据传输协议。

状态机表达方式有两种,一个是MELY型,另一个摩尔型。

下面具体讲解。第一个定义参数。
对于内部命令,使用常数定义值。

`timescale 1ns/1ns
//对于命令,自定位常数值
`define CH451_RESET 12'H201
`define CH451_SYSON1 12'H401
`define CH451_DSP 12'H500
`define CH451_BCD 12`H580

第二个定义状态机
module CH451DISLAY(clk,
                   rst_n,
                   data,
                   //wr,
                   CH451_DCLK,
                   CH451_DIN,
                   CH451_LOAD,
                   ACK);
parameter clk_div_factor =4'b1001;
parameter point_i        =8'b0000_0000;
parameter digit_on_num   =4'b1000;

parameter CH451_DISPLAY =32'H F_E_D_C_B_A_9_8;

//状态机有两个,第一个是器件总体显示过程 ,第二个是内部线时序状态机
parameter CH451_Idle       =9'b0_0000_0001;
parameter CH451_Enable_serial_port =9'b0_0000_0010;
parameter CH451_Reset      =9'b0_0000_0100;
parameter CH451_Set_display_mode =9'b0_0000_1000;
parameter CH451_Open_display =9'b0_0001_0000;
parameter CH451_Get_data =9'b0_0010_000;
parameter CH451_Display_ready =9'b0_0100_0000;
parameter CH451_Display =9'b0_1000_000;
parameter CH451_Display_temp =9'1_0000_0000;
//外部连线的时序过程
parameter Shift12_out_idle =7'b000_0001;
parameter Pull_down_ch451_load=7'b000_0010;
parameter Get_shift_out_data=7'b000_0100;
parameter Pull_down_ch451_dclk=7'b000_1000;
parameter Pull_up_ch451_dclk=7'b001_0000;
parameter Shift_paralell_data=7'b010_0000;
parameter Pull_up_ch451_load=7'b100_0000;我说过状态机最小单位制,必须是以输出CLK的周期为准的。这是以CLK数据传输。
没有CLK的时候,必须以对于波特率(UART)为基准。

输入输出信号定义
input  clk;//系统时钟
input  rst_n;//复位
input [5*digit_on_num-1:0] data;//输入数据
//input wr;//用于锁定输入数据
output CH451_DCLK;
output CH451_DIN;
output CH451_LOAD;
output ACK;//输出响应的信号

reg CH451_DCLK;
reg CH451_DIN;
reg CH451_LOAD;
reg ACK;
输入输出信号一般以芯片接口,是个体模块的控制参考。
内部状态机寄存器
reg   trans_over_flag;
reg[3:0] clk_div_counter;
reg[3:0] shift_counter;
reg[11:0] CH451_cmd;
reg[2:0]  transfer_count;
reg[digit_on_num-1:0] decemial_point_sel;
reg[4*digit_on_num-1:0] display_led_sel;
reg[5*digit_on_num-1:0] display_data;
reg[10:0] state;
reg[6:0] shift_state;
时钟分频
always@(posedge clk or negedge rst_n)
begin
if(!rst_n) clk_div_counter<=0;
else if(clk_div_counter==clk_div_factor) clk_div_counter<=0;
     else clk_div_counter<=clk_div_counter+1'b1;
end
探索未知领域
下面自己看代码
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)

   begin
     state<=CH451_Idle;
     shift_state<=Shift12_out_idle;
     CH451_DIN<=1'b1;
     CH451_DCLK<=1'b1;
     CH451_LOAD<=1'b1;
         transfer_count<=0;
         shift_counter<=0;
         display_data<=0;
         decemial_point_sel<=0;
         display_led_sel<=0;
         CH451_cmd<=12'h0;
         trans_over_flag<=1'b0;
         ACK<=1'b0;
        end
        else

           if(clk_div_counter==clk_div_factor)
           begin
            case(state)
                 CH451_Idle:begin
                              CH451_DIN<=1'b0;
                                          state<=CH451_Enable_serial_port;
                                         end
                 CH451_Enable_serial_port:begin
                               CH451_DIN<=1'b1;
                                           trans_over_flag<=1'b0;
                                           CH451_cmd<=`CH451_RESET;
                                           state<=CH451_Reset;
                                           end
                 CH451_Reset:begin
                     if(trans_over_flag==1'b0)
                          shift12_out;//调用任务函数
                         else
                           begin
                            trans_over_flag<=1'b0;
                                CH451_cmd<=`CH451_BCD;
                                state<=CH451_Set_display_mode;
                          end
                         end
                 CH451_Set_display_mode:begin
                   if(trans_over_flag==0)
                     shift12_out;
                   else
                     begin
                          trans_over_flag<=1'b0;
                          CH451_cmd<=`CH451_SYSON1;
                          state<=CH451_Open_display;
                         end
                         end
                 CH451_Open_display:begin
            if(trans_over_flag==0)
                shift12_out;
            else begin
              trans_over_flag<=1'b0;
              state<=CH451_Get_data;
            end
            end
         CH451_Get_data:begin
                   display_data[5*digit_On_num-1:0]<=data[5*digit_on_num-1:0];
                   decemial_point_sel<=point_i[7:8-digit_on_num];
                   display_led_sel<=CH451_DISPLAY[4*digit_on_num-1:0];
                   state<=CH451_Display_ready;
                   end
                 CH451_Display_ready:begin
                   CH451_cmd<={
                                display_led_sel[3:0],
                                                decemial_point_sel[0].
                                                2'b00,
                                                display_data[4:0]
                                                };
                   state<=CH451_Display;
                   end
                 CH451_Display:begin
                  if(trans_over_flag==0)
                   shift12_out;
                  else begin
                   trans_over_flag<=1'b0;
                   state<=CH451_Display_temp;
                   end
                   end
                  CH451_Display_temp:begin
                    if(trans_count==digit_on_num-1) begin
                         state<=CH451_Get_data;
                         transfer_count<=0;
                         end
                         else begin
                           state<=CH451_Display_ready;
                           transfer_count<=transfer_count+1'b1;
                           display_data<={
                                          display_data[4:0]
                                                          display_data{5*digit_on_num-1:5]
                                                          };
                           decemial_point_sel<={
                                           display_led_sel[3:0],
                                                           display_led_sel[4*digit_on_num-1:4]
                                                           };
                                display_led_sel<={
                                                display_led_sel[3:0],
                                                                display_led_sel[4*digit_on_num-1:4]
                                                                };
                            end
                        end
                        default:state<=CH451_Idle;
                        endcase
                end
        end
        end
                           

task shift12_out;//12位数据输出
begin
casex(shift_state_
   Shift12_out_idle:begin
     shift_state<=Pull_down_ch451_load;
         ACK<=1'b0;
     end
   Pull_down_ch451_load:begin
     shift_state<=Get_shift_out_data;
     CH451_LOAD<=1'b0;
         shift_state<=Pull_up_ch451_dclk;
         end
         Get_shift_out_data:begin
            shift_state<=Pull_down_ch451_dclk;
                CH451_DIN<=CH451_cmd[0];
        end
        Pull_down_ch451_dclk:begin
          CH451_DCLK<=1'b0;
          shift_state<=Pull_up_ch451_dclk;
         end
        Pull_up_ch451_dclk:begin
           CH451_DCLK<=1'b1;
           shift_state<=Shift_paralell_data;
           end
         Shift_paralell_data:begin
           if(shift_counter==11)begin
             shift_state<=Pull_up_ch451_load;
                 shift_counter<=0;
           end
           else begin
           shif_counter<=shift_counter+1'b1;
           CH451_cmd<={1'b0,CH451_cmd[11:1]};
           shift_state<=Get_shift_out_data;
           ACK<=1'b1;
           end
           end
          default:begin
             shift_state<=Shift12_out_idle;
                 end
                 endcase
                end
                endtask
探索未知领域
返回列表