📄 hc164_driver.v
字号:
////////////////////////////////////////////////////////////////////////////////// ____ _ __ ___ //// / __ \(_)____/ / / (_)____ 本设计由 www.richic.com 提供,并在其低//// / /_/ / / ___/ /_/ / / ___/ 端产品:FPGA学习板、FPGA试验系统以及其//// / _, _/ / /__/ __ / / /__ 高端产品:FPGA开发系统中验证通过,您可//// /_/ |_/_/\___/_/ /_/_/\___/ 以在此基础上修改,复制并分发。但我们并//// 不承诺本设计可以用做商业产品,同时我们//// 不保证设计的通用性。为了方便更新以及修改请保留设计的版本信息,请对自行修改//// 部分添加足够注释。对设计如有其他建议请到 www.richic.com网站进行讨论 //// //////////////////////////////////////////////////////////////////////////////////// //// FPGA实验教程 http://www.richic.com/lab //// FPGA实验教程EDACN镜像 http://www.edacn.com/rhic/ //// 本教程所有设计在本公司开发板上验证通过 //// //////////////////////////////////////////////////////////////////////////////////// Company: www.richic.com //// Engineer: mail007 (Gavin.xue) //// //// Design Name: //// Module Name: //// Target Device: //// Tool versions: Simulation: //// Synthesis: XST(ise6.3...sp2) //// Place&Routing: ISE6.3...sp2 //// Others tools: //// Create Date: 2006-01-31 11:37 //// Description: //// //// LOG: //// //////////////////////////////////////////////////////////////////////////////////`timescale 1ns/1ns // --------------------------------------------------------------------------- //HC164用来驱动数码管以及LED指示灯,动态扫描数码管的是利用视觉暂留的特性进行显 //示景物引起人的视觉印象,在景物消失后还能在视网膜上保持0。1秒的时间叫做视觉暂 //留。可以将数据刷新速率可以为10Hz(0.1s),同时我们需要对四位数据进行扫描,因此 //数据刷新速率最低应该为10Hz×4。最高可以为50MHz(HC164可以工作在50-175MHz)。 //根据实际情况我们可以定为 762.939453125 = 50MHz/2**16, //因此接口处led,seg_value,dot数据的变化速率最大不能超过为50MHz/2**14 // ---------------------------------------------------------------------------module hc164_driver
( clk, rst_n, led, seg_value, dot, hc_si, hc_cp ); // --------------------------------------------------------------------------- // // input signals // led[3:0] : led3-led0 对应原理图中D5,D4,D3,D2四位LED灯,高电平有效。 // seg_value[15:0] :四位共阴极数码显示的数据,从高到低每4bit为数码管一位。 // dot[3:0] : 四位共阴极数码管显示的小数点位,从高到低 // hc_si : 本模块数据串行输出,hc164数据串行输入。 // hc_cp : 本模块输出,hc164时钟输入。 // // --------------------------------------------------------------------------- input clk; input rst_n; input [3 :0] led; input [15:0] seg_value; input [3 :0] dot; output hc_si; //HC164 Data input output reg hc_cp; //HC164 Clock input active Rising edges reg [5 :0] tx_cnt; // wire [15:0] seg_value = 16'h1234;// wire [3:0] dot = 4'b0010; // wire [3:0] led = 4'b1111; // --------------------------------------------------------------------------- // // 信号命名说明 // hc_data : 送到两个hc164中16bit的数据(每个hc164有8bit),hc164 data input // hc_data_44bit: hc_data的第四个4BIT数据, // LED显示信号,对应原理图中HC_Q15,HC_Q14,HC_Q13,HC_Q12四位, // 用来点亮D5,D4,D3,D2四位LED灯,高电平有效。 // hc_data_34bit: hc_data的第三个4bit数据,即hc_data[11:8];对应原理图中 // HC_Q11,HC_Q10,HC_Q9,HC_Q8数码管位选信号,低电平有效。 // hc_data_31bit: hc_data的第三个1bit数据,即hc_data[2];对应原理图中HC_Q2,数 // 码管小数点位,高电平有效。 // hc_data[7:0]: 包括hc_data_31bit,这8bit用来做为数码管段选信号,高电平有效 // // --------------------------------------------------------------------------- reg [6:0] hex2led; //hex-to-seven-segment decoder output reg [3:0] hc_data_34bit; reg hc_data_31bit; wire [15:0] hc_data = {led, hc_data_34bit, hex2led[6:2], hc_data_31bit, hex2led[1:0] }; // --------------------------------------------------------------------------- // // 之所以需要取反,是因为对hc_si赋值时从最低位开始,而原理图中设计希望从最高位 // 开始发送数据。 // // --------------------------------------------------------------------------- wire [15:0] hc_data_inv = { hc_data[0], hc_data[1], hc_data[2], hc_data[3], hc_data[4], hc_data[5], hc_data[6], hc_data[7], hc_data[8], hc_data[9], hc_data[10], hc_data[11], hc_data[12], hc_data[13], hc_data[14], hc_data[15] }; reg [15:0] clk_cnt; always @ ( posedge clk or negedge rst_n ) if ( !rst_n ) clk_cnt <= 16'd0; else clk_cnt <= clk_cnt + 1'b1; // reg [9:0] clk_cnt; // always @ ( posedge clk or negedge rst_n ) // if ( !rst_n ) clk_cnt <= 10'd0; // else clk_cnt <= clk_cnt + 1'b1; // --------------------------------------------------------------------------- // // 数据管4位计数器,本计数器用来区分每位数值,位码,以及每位的小数点等三个 // 信息,每一位数值将通过hex2led模块变换成数码管位码。 // // --------------------------------------------------------------------------- reg [1:0] seg_led_num; always @ ( posedge clk or negedge rst_n ) if (!rst_n ) seg_led_num <= 2'b00; else if ( clk_cnt == 16'hFFFF ) seg_led_num <= seg_led_num + 1'b1; reg [3:0] hex; // always @ ( * ) always @ ( seg_led_num or hex or seg_value ) case ( seg_led_num ) 2'b00: hex = seg_value[15:12]; 2'b01: hex = seg_value[11:8]; 2'b10: hex = seg_value[7:4]; 2'b11: hex = seg_value[3:0]; endcase // --------------------------------------------------------------------------- // hex-to-seven-segment decoder // // segment encoding // 11 // --- // 10 | | 7 // --- <- 5 // 1 | | 4 // --- . 3 // 2 // Q[6:0] = p11 p10 p7 p5 _ p4 p2 p1 // ---------------------------------------------------------------------------// always @ ( * ) always @ ( hex or hex2led ) begin case (hex) //数值 4'H1 : hex2led = 7'b0010_100; //1 4'H2 : hex2led = 7'b1011_011; //2 4'H3 : hex2led = 7'b1011_110; //3 4'H4 : hex2led = 7'b0111_100; //4 4'H5 : hex2led = 7'b1101_110; //5 4'H6 : hex2led = 7'b1101_111; //6 4'H7 : hex2led = 7'b1010_100; //7 4'H8 : hex2led = 7'b1111_111; //8 4'H9 : hex2led = 7'b1111_100; //9 4'HA : hex2led = 7'b1111_101; //A 4'HB : hex2led = 7'b0101_111; //b 4'HC : hex2led = 7'b1100_011; //C 4'HD : hex2led = 7'b0011_111; //d 4'HE : hex2led = 7'b1101_011; //E 4'HF : hex2led = 7'b1101_001; //F default : hex2led = 7'b1110_111; //0 endcase end//hex2led_common_cathode hex2led_inst(// .hex ( hex ),// .led ( hex2led )); // always @ ( * ) always @ ( seg_led_num or hc_data_34bit ) case ( seg_led_num ) 2'b00:hc_data_34bit[3:0] = 4'b0111; 2'b01:hc_data_34bit[3:0] = 4'b1011; 2'b10:hc_data_34bit[3:0] = 4'b1101; 2'b11:hc_data_34bit[3:0] = 4'b1110; endcase // always @ ( * ) always @ ( seg_led_num or hc_data_31bit or dot ) case ( seg_led_num ) 2'b00:hc_data_31bit = dot[3]; 2'b01:hc_data_31bit = dot[2]; 2'b10:hc_data_31bit = dot[1]; 2'b11:hc_data_31bit = dot[0]; endcase // --------------------------------------------------------------------------- // // HC164 的 hc_si 以及hc_cp信号的产生,通过一个6位的计数器来控制.hc_si从信号 // hc_data_inv的最低位开始发送,原理图中需要从最高位发送,因此在此之前需要对整 // 个信号取反。 // // --------------------------------------------------------------------------- always @ ( posedge clk or negedge rst_n ) if (!rst_n ) tx_cnt <= 6'd0; else if ( clk_cnt[15] ) tx_cnt <= 6'd0; else if ((!clk_cnt[15]) && (tx_cnt <= 6'd32 )) tx_cnt <= tx_cnt + 1'b1; always @ ( posedge clk or negedge rst_n ) if (!rst_n) hc_cp <= 1'b0; else if ( clk_cnt[15] ) hc_cp <= 1'b0; else if ((!clk_cnt[15]) && (tx_cnt < 6'd32 )) hc_cp <= !hc_cp; assign hc_si = hc_data_inv[tx_cnt[4:1]]; // reg [5:0] tx_cnt;// always @ ( posedge clk or negedge rst_n )// if (!rst_n ) tx_cnt <= 6'd0;// else if ( clk_cnt[9] ) tx_cnt <= 6'd0; // else if ( (!clk_cnt[9]) && (tx_cnt < 6'd32 )) tx_cnt <= tx_cnt + 1'b1;//// always @ ( posedge clk or negedge rst_n )// if (!rst_n) hc_cp <= 1'b0;// else if ( clk_cnt[9] ) hc_cp <= 1'b0;// else if ((!clk_cnt[9]) && (tx_cnt < 6'd32 )) hc_cp <= !hc_cp; endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -