?? top_hc164_driver.v
字號:
////////////////////////////////////////////////////////////////////////////////
// ____ _ __ ___ //
// / __ \(_)____/ / / (_)____ 本設(shè)計(jì)由 www.richic.com 提供,并在其低//
// / /_/ / / ___/ /_/ / / ___/ 端產(chǎn)品:FPGA學(xué)習(xí)板、FPGA試驗(yàn)系統(tǒng)以及其//
// / _, _/ / /__/ __ / / /__ 高端產(chǎn)品:FPGA開發(fā)系統(tǒng)中驗(yàn)證通過,您可//
// /_/ |_/_/\___/_/ /_/_/\___/ 以在此基礎(chǔ)上修改,復(fù)制并分發(fā)。但我們并//
// 不承諾本設(shè)計(jì)可以用做商業(yè)產(chǎn)品,同時(shí)我們//
// 不保證設(shè)計(jì)的通用性。為了方便更新以及修改請保留設(shè)計(jì)的版本信息,請對自行修改//
// 部分添加足夠注釋。對設(shè)計(jì)如有其他建議請到 www.richic.com網(wǎng)站進(jìn)行討論 //
// //
////////////////////////////////////////////////////////////////////////////////
// //
// FPGA實(shí)驗(yàn)教程 http://www.richic.com/lab //
// FPGA實(shí)驗(yàn)教程EDACN鏡像 http://www.edacn.com/rhic/ //
// 本教程所有設(shè)計(jì)在本公司開發(fā)板上驗(yàn)證通過 //
// //
////////////////////////////////////////////////////////////////////////////////
// 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用來驅(qū)動(dòng)數(shù)碼管以及LED指示燈,動(dòng)態(tài)掃描數(shù)碼管的是利用視覺暫留的特性進(jìn)行顯
//示景物引起人的視覺印象,在景物消失后還能在視網(wǎng)膜上保持0。1秒的時(shí)間叫做視覺暫
//留。可以將數(shù)據(jù)刷新速率可以為10Hz(0.1s),同時(shí)我們需要對四位數(shù)據(jù)進(jìn)行掃描,因此
//數(shù)據(jù)刷新速率最低應(yīng)該為10Hz×4。最高可以為50MHz(HC164可以工作在50-175MHz)。
//根據(jù)實(shí)際情況我們可以定為 762.939453125 = 50MHz/2**16,
//因此接口處led,seg_value,dot數(shù)據(jù)的變化速率最大不能超過為50MHz/2**14
// ---------------------------------------------------------------------------
module top_hc164_driver(
clk,
rst_n,
led,
seg_value,
dot,
hc_si,
hc_cp
);
// ---------------------------------------------------------------------------
//
// input signals
// led[3:0] : led3-led0 對應(yīng)原理圖中D5,D4,D3,D2四位LED燈,高電平有效。
// seg_value[15:0] :四位共陰極數(shù)碼顯示的數(shù)據(jù),從高到低每4bit為數(shù)碼管一位。
// dot[3:0] : 四位共陰極數(shù)碼管顯示的小數(shù)點(diǎn)位,從高到低
// hc_si : 本模塊數(shù)據(jù)串行輸出,hc164數(shù)據(jù)串行輸入。
// hc_cp : 本模塊輸出,hc164時(shí)鐘輸入。
//
// ---------------------------------------------------------------------------
input clk;
input rst_n;
input [3 :0] led;
input [15:0] seg_value;
input [3 :0] dot;
output reg 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 : 送到兩個(gè)hc164中16bit的數(shù)據(jù)(每個(gè)hc164有8bit),hc164 data input
// hc_data_44bit: hc_data的第四個(gè)4BIT數(shù)據(jù),
// LED顯示信號,對應(yīng)原理圖中HC_Q15,HC_Q14,HC_Q13,HC_Q12四位,
// 用來點(diǎn)亮D5,D4,D3,D2四位LED燈,高電平有效。
// hc_data_34bit: hc_data的第三個(gè)4bit數(shù)據(jù),即hc_data[11:8];對應(yīng)原理圖中
// HC_Q11,HC_Q10,HC_Q9,HC_Q8數(shù)碼管位選信號,低電平有效。
// hc_data_31bit: hc_data的第三個(gè)1bit數(shù)據(jù),即hc_data[2];對應(yīng)原理圖中HC_Q2,數(shù)
// 碼管小數(shù)點(diǎn)位,高電平有效。
// hc_data[7:0]: 包括hc_data_31bit,這8bit用來做為數(shù)碼管段選信號,高電平有效
//
// ---------------------------------------------------------------------------
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]
};
// ---------------------------------------------------------------------------
//
// 之所以需要取反,是因?yàn)閷c_si賦值時(shí)從最低位開始,而原理圖中設(shè)計(jì)希望從最高位
// 開始發(fā)送數(shù)據(jù)。
//
// ---------------------------------------------------------------------------
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;
// ---------------------------------------------------------------------------
//
// 數(shù)據(jù)管4位計(jì)數(shù)器,本計(jì)數(shù)器用來區(qū)分每位數(shù)值,位碼,以及每位的小數(shù)點(diǎn)等三個(gè)
// 信息,每一位數(shù)值將通過hex2led模塊變換成數(shù)碼管位碼。
//
// ---------------------------------------------------------------------------
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 @ ( * )
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 @ ( * )
begin
case (hex) //數(shù)值
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 @ ( * )
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 @ ( * )
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信號的產(chǎn)生,通過一個(gè)6位的計(jì)數(shù)器來控制.hc_si從信號
// hc_data_inv的最低位開始發(fā)送,原理圖中需要從最高位發(fā)送,因此在此之前需要對整
// 個(gè)信號取反。
//
// ---------------------------------------------------------------------------
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;
always @ ( posedge clk or negedge rst_n )
if (!rst_n ) hc_si <= 1'b1;
else hc_si <= hc_data_inv[tx_cnt[4:1]];
// 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
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -