2208|0

3249

帖子

0

TA的资源

五彩晶圆(初级)

楼主
 

CPLD驱动MAX7219传送8位参数的问题 [复制链接]

我用CPLD驱动MAX7219传送16位参数的方法成功了。

我看单片机里都是一次传送8位数据,我也想用CPLD传送8位数据。

但是有个问题,就是MAX7219的LOAD引脚也就是片选,需要传送两次8位数据才锁存。

我传送一次8位数据锁存一次,仿真没问题。

代码如下:

  • module MAX7219
  • (
  • input clk_i,
  • input rst_i,
  • output reg sdin_o,//串行输出数据
  • output reg sclk_o,//串行时钟
  • output reg load_o,//更新da寄存器
  • output reg [7:0] data
  • );
  • reg [7:0] olddata;
  • reg [22:0] currentstate;
  • parameter s1 = 23'b000_0000_0000_0000_0000_0001;
  • parameter s2 = 23'b000_0000_0000_0000_0000_0010;//s1和S2状态设置译码寄存器
  • parameter s3 = 23'b000_0000_0000_0000_0000_0100;
  • parameter s4 = 23'b000_0000_0000_0000_0000_1000;//S3和S4状态设置亮度寄存器
  • parameter s5 = 23'b000_0000_0000_0000_0001_0000;//
  • //reg sclk_o;
  • reg [5:0]counter;
  • parameter
  • seg1 = 8'h01, //1.
  • seg2 = 8'h81, //2
  • seg3 = 8'h02, //3
  • seg4 = 8'h02, //4
  • seg5 = 8'h03, //1.
  • seg6 = 8'h03, //2
  • seg7 = 8'h04, //3
  • seg8 = 8'h09; //4
  • reg [2:0]cnt;
  • //产生时钟
  • always @(posedge clk_i)
  • begin
  • if(!rst_i) begin
  • counter<=6'd0;
  • sclk_o <= 1'b1;
  • end
  • else begin
  • if(counter==6'd9) begin
  • sclk_o <= ~sclk_o;
  • counter<=6'd0;
  • end
  • else counter<=counter+6'd1;
  • end
  • end
  • reg [2:0] sclk_cnt;//同步时钟计数器,7
  • //reg [4:0] sclk_cnt;//同步时钟计数器,7
  • always @(posedge sclk_o or negedge rst_i)
  • begin
  • if(!rst_i) sclk_cnt <= 3'b0;
  • else
  • case(currentstate)
  • s2,s4:
  • if(3'd7 == sclk_cnt)
  • sclk_cnt <= 3'b0;
  • else sclk_cnt <= sclk_cnt + 3'b1;
  • default: sclk_cnt <= 3'b0;
  • endcase
  • end
  • //主状态机
  • always @(posedge sclk_o or negedge rst_i)
  • begin
  • if(!rst_i) begin currentstate <=s1; cnt = 3'b0; end
  • else
  • case(currentstate)
  • s1: currentstate <= s2; //s1和S2状态设置译码寄存器
  • s2:begin
  • if(3'd7 == sclk_cnt) //8个时钟周期将数据送出去
  • currentstate <= s3;
  • else
  • currentstate <= s2;
  • end
  • s3: currentstate <= s4; //s1和S2状态设置译码寄存器
  • s4:begin
  • if(3'd7 == sclk_cnt) //8个时钟周期将数据送出去
  • currentstate <= s5;
  • else
  • currentstate <= s4;
  • end
  • s5: currentstate <= s1; //s1和S2状态设置译码寄存器
  • endcase
  • end
  • //各状态的处理
  • always @(posedge sclk_o or negedge rst_i)
  • begin
  • if(!rst_i)begin data <= 8'h00; olddata <= 8'h00; end
  • else case(currentstate)
  • s1:begin data <= 8'h0a; end //正常显示模式
  • s3:begin data <= 8'h04; end //正常显示模式
  • s2,s4: begin data <= data << 1; olddata <= olddata; end//循环移位 将高位送出
  • default: begin data <= 8'h00; olddata <= olddata; end
  • endcase
  • end
  • //----------数据串行---------
  • always @(posedge sclk_o or negedge rst_i)
  • begin
  • if(!rst_i) sdin_o <= 1'b0;
  • else case(currentstate)
  • s2,s4: sdin_o <= data[7];
  • default: sdin_o <= 1'b0;
  • endcase
  • end
  • //----------串行数据写有效LOAD----------
  • always @(posedge sclk_o or negedge rst_i)
  • begin
  • if(!rst_i) load_o <= 1'b1;
  • else case(currentstate)
  • s2,s4: begin load_o <= 1'b0; end //送数的时候处于低
  • default: load_o <= 1'b1; //非送数时候,拉高 锁存数据
  • endcase
  • end
  • endmodule

仿真波形如下:

可见传送一次8位数据,我传了两个8位数据0x0a,0x04,都是8个脉冲,但是都是传送之前LOAD拉低,传送完8位数据,LOAD拉高。

我想实现连续传送两次8位数据,16个时钟周期,代码如下

  • module MAX7219
  • (
  • input clk_i,
  • input rst_i,
  • output reg sdin_o,//串行输出数据
  • output reg sclk_o,//串行时钟
  • output reg load_o,//更新da寄存器
  • output reg [7:0] data
  • );
  • reg [7:0] olddata;
  • reg [22:0] currentstate;
  • parameter s1 = 23'b000_0000_0000_0000_0000_0001;
  • parameter s2 = 23'b000_0000_0000_0000_0000_0010;//s1和S2状态设置译码寄存器
  • parameter s3 = 23'b000_0000_0000_0000_0000_0100;
  • parameter s4 = 23'b000_0000_0000_0000_0000_1000;//S3和S4状态设置亮度寄存器
  • parameter s5 = 23'b000_0000_0000_0000_0001_0000;//
  • //reg sclk_o;
  • reg [5:0]counter;
  • parameter
  • seg1 = 8'h01, //1.
  • seg2 = 8'h81, //2
  • seg3 = 8'h02, //3
  • seg4 = 8'h02, //4
  • seg5 = 8'h03, //1.
  • seg6 = 8'h03, //2
  • seg7 = 8'h04, //3
  • seg8 = 8'h09; //4
  • reg [2:0]cnt;
  • //产生时钟
  • always @(posedge clk_i)
  • begin
  • if(!rst_i) begin
  • counter<=6'd0;
  • sclk_o <= 1'b1;
  • end
  • else begin
  • if(counter==6'd9) begin
  • sclk_o <= ~sclk_o;
  • counter<=6'd0;
  • end
  • else counter<=counter+6'd1;
  • end
  • end
  • reg [2:0] sclk_cnt;//同步时钟计数器,7
  • //reg [4:0] sclk_cnt;//同步时钟计数器,7
  • always @(posedge sclk_o or negedge rst_i)
  • begin
  • if(!rst_i) sclk_cnt <= 3'b0;
  • else
  • case(currentstate)
  • s2,s4:
  • if(3'd7 == sclk_cnt)
  • sclk_cnt <= 3'b0;
  • else sclk_cnt <= sclk_cnt + 3'b1;
  • default: sclk_cnt <= 3'b0;
  • endcase
  • end
  • //主状态机
  • always @(posedge sclk_o or negedge rst_i)
  • begin
  • if(!rst_i) begin currentstate <=s1; cnt = 3'b0; end
  • else
  • case(currentstate)
  • s1: currentstate <= s2; //s1和S2状态设置译码寄存器
  • s2:begin
  • if(3'd7 == sclk_cnt) //8个时钟周期将数据送出去
  • currentstate <= s3;
  • else
  • currentstate <= s2;
  • end
  • s3: currentstate <= s4; //s1和S2状态设置译码寄存器
  • s4:begin
  • if(3'd7 == sclk_cnt) //8个时钟周期将数据送出去
  • currentstate <= s5;
  • else
  • currentstate <= s4;
  • end
  • s5: currentstate <= s1; //s1和S2状态设置译码寄存器
  • endcase
  • end
  • //各状态的处理
  • always @(posedge sclk_o or negedge rst_i)
  • begin
  • if(!rst_i)begin data <= 8'h00; olddata <= 8'h00; end
  • else case(currentstate)
  • s1:begin data <= 8'h0a; end //正常显示模式
  • s3:begin data <= 8'h04; end //正常显示模式
  • s2,s4: begin data <= data << 1; olddata <= olddata; end//循环移位 将高位送出
  • default: begin data <= 8'h00; olddata <= olddata; end
  • endcase
  • end
  • //----------数据串行---------
  • always @(posedge sclk_o or negedge rst_i)
  • begin
  • if(!rst_i) sdin_o <= 1'b0;
  • else case(currentstate)
  • s2,s4: sdin_o <= data[7];
  • default: sdin_o <= 1'b0;
  • endcase
  • end
  • //----------串行数据写有效LOAD----------
  • always @(posedge sclk_o or negedge rst_i)
  • begin
  • if(!rst_i) load_o <= 1'b1;
  • else case(currentstate)
  • s2,s3,s4: begin load_o <= 1'b0; end //送数的时候处于低
  • default: load_o <= 1'b1; //非送数时候,拉高 锁存数据
  • endcase
  • end
  • endmodule

仿真结果如下

可以看到多了一个时钟周期,一共17个时钟周期。

请问高手,有什么办法让它凑够16个时钟周期。谢谢!

此帖出自FPGA/CPLD论坛
点赞 关注
个人签名为江山踏坏了乌骓马,为社稷拉断了宝雕弓。
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
【有奖直播】2025是德科技数字月-数字新品来助阵
直播时间:3月19日(周三)14:00
直播奖励:小米口红充电宝、倍思充电线、是德科技十周年鼠标垫

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表