我用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个时钟周期。谢谢!
|