1,需求:使用xc720 开发板的8个数码管显示12345678
2,需求分析:
75hc595
1,74hc595驱动,将串行数据转换成并行输出。对应研究手册
2,发送之前将要发的数据,合并成高8位:SEG,低8位:SEL, 结合testbanch查看波形,使用测试代码验证显示。
//实现承有数码管显示1
`timescale 1ns/1ps
module vlg_74hc595_v(input i_clk,input i_rest_n,input [15:0]i_data,output reg o_ds,output reg o_shcp,output reg o_stcp);//parameter i_sel = 8'b1111_0000;
//parameter i_seg = 8'b1000_0000;wire clk_25m;
wire clk_12r5m;
wire clk_100m;
wire locked;clk_wiz_0 clk_div_inst(// Clock out ports.clk_out1(clk_25m), // output clk_out1.clk_out2(clk_12r5m), // output clk_out2.clk_out3(clk_100m), // output clk_out3.reset(~i_rest_n), // input reset.locked(locked), // output locked// Clock in ports.clk_in1(i_clk)); // input clk_in1//assign i_data[15:8] = i_seg;//seg7,seg6,seg5,seg4,seg3,seg2,seg1,seg0
//assign i_data[7:0] = i_sel;//s7,s6,s5,s4,s3,s2,s1,s0reg [4:0]r_cnt;//16次计
//产生o_ds 信号
always @(posedge clk_12r5m) begin
if(!i_rest_n) begino_ds <= 0;r_cnt <= 0;
end
else if(locked & r_cnt < 16) begino_ds <= i_data[15-r_cnt];r_cnt <= r_cnt + 1;
endelse begin r_cnt <= 0; o_ds <= 0; end
end//产生o_shcpalways @(negedge clk_25m) beginif(!i_rest_n) o_shcp <= 0;else if(r_cnt== 0) o_shcp <= 0;else o_shcp <= ~o_shcp;
end//产生o_stcp
always @(negedge clk_25m) beginif(!i_rest_n) o_stcp <= 0;else if(r_cnt== 16 && o_shcp) o_stcp <= 1;else o_stcp <= 0;
end
endmodule
分频
1,数码管以1Khz 切换1~8个数码管状态。 数码管刷新频率位 1KHZ/8 = 125hz/8ms 刷新一次
2,74hc595 更新bit 速率 12.5Mhz shcp
//实现分屏,12.5M,50K
`timescale 1ns/1ps
module vlg_div(input i_clk,input i_rest_n,output o_clk_12r5m,output o_clk_1khz //50*20=1000);
//`define SIMU_FLGA
`ifdef SIMU_FLGA
localparam CLK_12R5M_MAX = 50_000_000/12_500_000 -1;
localparam CLK_1KHZ_MAX = 10-1;`else
localparam CLK_12R5M_MAX = 50_000_000/12_500_000 -1;
localparam CLK_1KHZ_MAX = 50_000_000/1000 -1;`endif//12.5M 计数使能
reg [3:0]r_cnt_12r5m;
always @(posedge i_clk) begin
if(!i_rest_n) r_cnt_12r5m <= 0;
else if(r_cnt_12r5m < CLK_12R5M_MAX) r_cnt_12r5m <= r_cnt_12r5m +1;
else r_cnt_12r5m <= 0;
end
assign o_clk_12r5m = (r_cnt_12r5m == CLK_12R5M_MAX) ?1:0;//50K 计数使能
reg [19:0]r_cnt_1khz;
always @(posedge i_clk) begin
if(!i_rest_n) r_cnt_1khz <= 0;
else if(r_cnt_1khz < CLK_1KHZ_MAX) r_cnt_1khz <= r_cnt_1khz +1;
else r_cnt_1khz <= 0;
endassign o_clk_1khz = (r_cnt_1khz == CLK_1KHZ_MAX) ?1:0;endmodule
数据产生
1,当1kHZ 来临时,合并sel+seg = [15:0]data
2,合并前要将sel 转换成 0000_0001 即每一1 代表要选择的sel
3,合并前将数字转换成数码管 编码
//实现将8个数码管的数值,以20ms 输出seg+sel 的值
`timescale 1ns/1ps
module vlg_data_generate(input i_clk,input i_rest_n,input i_clk_1khz,input [31:0]i_data, //输入8个数码管的数值 ,每个数码管用4位表示,例如f:1111output reg[15:0]o_data_seg_sel //输出数码管的seg+sel 高8位seg,低8位sel);//产生20ms 的 0-7 计数
reg [7:0]r_index; //0-7
always @(posedge i_clk) beginif(!i_rest_n) r_index <= 0;else if(i_clk_1khz) beginif(r_index < 7) r_index <= r_index + 1;else r_index <= 0;end
end//根据0-7 变换,取出对应的seg 的hex码
reg [3:0]r_hex;
always @(posedge i_clk) beginif(!i_rest_n) r_hex <= 0;elsecase (r_index)4'd0: r_hex <= i_data[3:0];4'd1: r_hex <= i_data[7:4];4'd2: r_hex <= i_data[11:8];4'd3: r_hex <= i_data[15:12];4'd4: r_hex <= i_data[19:16];4'd5: r_hex <= i_data[23:20];4'd6: r_hex <= i_data[27:24];4'd7: r_hex <= i_data[31:28];default r_hex <= 0;endcase
end//将hex 变成数码管显示
reg [7:0]r_seg;
always @(posedge i_clk) beginif(!i_rest_n) r_seg <= 8'b1111_1111;else case (r_hex)4'h0:r_seg <= 8'b1100_0000;//c04'h1:r_seg <= 8'b1111_1001;//f94'h2:r_seg <= 8'b1010_0100;//a4 4'h3:r_seg <= 8'b1011_0000;//b0 4'h4:r_seg <= 8'b1001_1001;//99 4'h5:r_seg <= 8'b1001_0010;//92 4'h6:r_seg <= 8'b1000_0010;//82 4'h7:r_seg <= 8'b1111_1000;//f8 4'h8:r_seg <= 8'b1000_0000;//80 4'h9:r_seg <= 8'b1001_0000;//90 4'ha:r_seg <= 8'b1000_1000;//88 4'hb:r_seg <= 8'b1000_0011;//83 4'hc:r_seg <= 8'b1100_0110;//c64'hd:r_seg <= 8'b1010_0001;//a1 4'he:r_seg <= 8'b1000_0110;//86 4'hf:r_seg <= 8'b1000_1110;//8e default:r_seg <= 8'b1111_1111;//ff endcase
end//将sel和seg 按 i_clk_50hz组合输出
always @(posedge i_clk) beginif(!i_rest_n) o_data_seg_sel <= 0;else if(i_clk_1khz &i_clk) begino_data_seg_sel[7:0] <= (1 << r_index); //0-7o_data_seg_sel[15:8] <= r_seg;end else ;
endendmodule
输入输出
测试代码使用localparam data 赋值形式
正式代码使用vio 输入
//vlg design 显示数码箿`timescale 1ns/1ps
module vlg_design(input i_clk,input i_rest_n,output o_ds,output o_shcp,output o_stcp);//parameter i_data = 32'h12345678; wire [15:0]w_data_seg_sel;
wire w_clk_12r5m;
wire w_clk_1khz;
wire[32:0] w_data;vio_0 your_instance_name (.clk(i_clk), // input wire clk.probe_out0(w_data) // output wire [31 : 0] probe_out0
);//
vlg_74hc595_v vlg_74hc595_v_inst(
.i_clk(i_clk),
.i_rest_n(i_rest_n),
.i_data(w_data_seg_sel),
.o_ds(o_ds),
.o_shcp(o_shcp),
.o_stcp(o_stcp) );//vlg_data_generate vlg_data_generate_inst(.i_clk(i_clk),
.i_rest_n(i_rest_n),
.i_clk_1khz(w_clk_1khz),
.i_data(w_data),
.o_data_seg_sel(w_data_seg_sel)
);//vlg_div vlg_div_inst(
.i_clk(i_clk),
.i_rest_n(i_rest_n),
.o_clk_12r5m(w_clk_12r5m),
.o_clk_1khz(w_clk_1khz)
);endmodule
xdc
set_property PACKAGE_PIN Y18 [get_ports i_clk]
set_property PACKAGE_PIN F15 [get_ports i_rest_n]
set_property IOSTANDARD LVCMOS33 [get_ports i_clk]
set_property IOSTANDARD LVCMOS33 [get_ports i_rest_n]set_property IOSTANDARD LVCMOS33 [get_ports o_ds]
set_property IOSTANDARD LVCMOS33 [get_ports o_shcp]
set_property IOSTANDARD LVCMOS33 [get_ports o_stcp]
set_property PACKAGE_PIN M18 [get_ports o_ds]
set_property PACKAGE_PIN F4 [get_ports o_shcp]
set_property PACKAGE_PIN C2 [get_ports o_stcp]
测试结果
3,调试记录
2023年12月30日
问题:本想显示全1的,结果成这样
2023年12月31日
解决了,撸了一遍视频,找到原因是时钟频率的问题,我直接把数据传输的时钟用的 50M。应该是74HC595 不支持这么高。现在换成12.5M 正常了。
2024年1月2日星期二
- 完成使用vio 实现vivado自动配置数码管显示
readme