本实验可按功能进行模块化设计,最终由顶层文件LED.v将各模块实例化后完成上述要求的设计。设计分为以下两个模块:寄存器接口模块interface.v,七段数码管显示模块display.v。总体架构如下图所示This experiment can be modularized according to function. Finally, the top-level file LED.v instantiates each module to complete the design of the above requirements. The design is divided into the following two modules: register interface module interface.v, seven-segment digital display module display.v. The overall architecture is shown below
...
顶层实例模块Top-level instance module (LED.v):
实例化接口模块和显示模块,组成最终的完整设计
接口模块(interface.v):
用于和APB BUS进行通信,实现APB BUS MASTER对寄存器的读写操作;完成定时器操作及中断处理;
显示模块(display.v):
将显示缓冲区的内容通过七段数码管显示
: Instantiate the interface module and display module to form the final complete design Interface module (interface.v): Used to communicate with APB BUS to realize the APB BUS MASTER read and write operations to the register; complete the timer operation and interrupt processing; Display module (display.v): Display the content of the display buffer through the seven-segment digital tube
4.6.1
...
本设计实例中共包含3个Verilog文件,其对应完成整体设计中各独立模块的功能。通过从总线接口读取数据和命令,控制七段数码管显示Design module implementation
There are 3 Verilog files in this design example, which correspond to the functions of each independent module in the overall design. By reading data and commands from the bus interface, the seven-segment digital tube display is controlled
4.6.2
...
本模块设计中共包含1个Verilog文件interface.v,完成寄存器的读写操作,定时器操作及中断处理的功能。相关代码如下Bus interface function design
This module design includes a Verilog file interface.v, which completes the functions of reading and writing registers, timer operation and interrupt processing. The relevant code is as follows:
`define EX_CON_REG 5'h00 //EX_CON_REG
`define EX_TO_REG 5'h01 //EX_TO_REG
`define EX_BUFFER_REG 5'h02 //EX_BUFFER_REG
`define EX_STATE_REG 5'h03 //EX_STATE_REG
/////////register files/////////////////////////////////////
reg [31:0] EX_CON; //Control register
reg [31:0] EX_TO; //Timer set register
reg [31:0] EX_BUFFER; //Display buffer register
wire [31:0] EX_STATE; //State register
/////////register R/W judge /////////////////////////////////////
wire READ_OPER;
wire WRITE_OPER;
assign READ_OPER = (!PWRITE) & (!PENABLE) & PSEL;
assign WRITE_OPER = PWRITE & (!PENABLE) & PSEL;
////////////////////////////write EX_CON register ////////////////////
reg [31:0] EX_CON_N;
always @ (posedge SYSCLK or negedge RST_B)
begin
if(!RST_B)
EX_CON <= `UD 32'B0;
else
EX_CON <= `UD EX_CON_N;
end
always @(*)
begin
if( WRITE_OPER && ( PADDR == `EX_CON_REG) )
EX_CON_N = PWDATA;
else
EX_CON_N = EX_CON;
end
/////////////////////////write EX_TO register ///////////////////////////////
reg [31:0] EX_TO_N; //
always @ (posedge SYSCLK or negedge RST_B)
begin
if(!RST_B)
EX_TO <= `UD 32'hffff_ffff;
else
EX_TO <= `UD EX_TO_N;
end
always @(*)
begin
if(WRITE_OPER && (PADDR == `EX_TO_REG))
EX_TO_N = PWDATA;
else
EX_TO_N = EX_TO;
end
//////////////////////////////write EX_BUFFER register //////////////////////
reg [31:0] EX_BUFFER_N;
always @ (posedge SYSCLK or negedge RST_B)
begin
if(!RST_B)
EX_BUFFER <= `UD 32'B0;
else
EX_BUFFER <= `UD EX_BUFFER_N;
end
always @(*)
begin
if( WRITE_OPER && (PADDR == `EX_BUFFER_REG))
EX_BUFFER_N = PWDATA;
else
EX_BUFFER_N = EX_BUFFER;
End
////////////////////// read register//////////////////
reg [31:0] SLAVE_APB_BUS_N,PRDATA;
always @ (posedge SYSCLK or negedge RST_B)
begin
if(!RST_B)
PRDATA <= `UD 32'B0;
else
PRDATA <= `UD SLAVE_APB_BUS_N;
end
always @(*)
begin
case({READ_OPER,PADDR})
{1'b1,`EX_CON_REG} : SLAVE_APB_BUS_N = EX_CON;
{1'b1,`EX_TO_REG} : SLAVE_APB_BUS_N = EX_TO;
{1'b1,`EX_BUFFER_REG} : SLAVE_APB_BUS_N = EX_BUFFER;
{1'b1,`EX_STATE_REG} : SLAVE_APB_BUS_N = EX_STATE;
default : SLAVE_APB_BUS_N = PRDATA;
endcase
end
//////////////////////定时器操作(Timer to EX_TO and overflow)/////////////////
reg [31:0] COUNT,COUNT_N;
wire CNT_START; //CNT_START signal
wire COUNT_OVERFLOW;
assign CNT_START=EX_CON[1];
assign COUNT_OVERFLOW= (COUNT < EX_TO)? 0:1;
always @(posedge SYSCLK or negedge RST_B)
begin
if(!RST_B)
COUNT <= `UD 32'B0;
else
COUNT <= `UD COUNT_N;
end
always @(*)
begin
if( CNT_START && (!COUNT_OVERFLOW))
COUNT_N = COUNT +1'B1;
else
COUNT_N = 32'B0;
End
///////////////////////////中断信号INT_B 处理 ////////////////////////////////
reg OVFL_STA,OVFL_STA_N;
wire INT_EN;
wire OVFL_CLS;
assign INT_EN= EX_CON[2];
assign OVFL_CLS=EX_CON[3];
assign INT_B = OVFL_STA & INT_EN; //high active
//////////////////////状态寄存器处理EX_STATE//////////////////////////////////
assign EX_STATE={31'B0,OVFL_STA};
always @ (posedge SYSCLK or negedge RST_B)
begin
if(!RST_B)
OVFL_STA <= `UD 1'B0;
else
OVFL_STA <= `UD OVFL_STA_N;
end
always @(*)
begin
if(COUNT_OVERFLOW)
OVFL_STA_N = `UD 1'B1;
else if(OVFL_CLS)
OVFL_STA_N = `UD 1'B0;
else
OVFL_STA_N = OVFL_STA;
end
4.6.3 显示功能设计实现
本模块设计中共包含1个Verilog文件display.v,完成将显示缓冲区的内容通过七段数码管显示的功能。七段数码管显示原理图如下:
...
相关设计实现代码如下 Display function design and implementation
This module design contains a Verilog file display.v, which completes the function of displaying the contents of the display buffer through the seven-segment digital tube. The schematic diagram of the seven-segment display is as follows:
...
The relevant design and implementation code is as follows:
//////////
计数器实现数码管扫描时间Counter clock time (Count system clock for Scan the led) ////////////
`define SCAN_COEF 24’h10120 //
七段数码管扫描时间5msSeven-segment digital tube scanning time 5ms
always @ (posedge SYSCLK or negedge RST_B)
begin
if(!RST_B)
LED_SCAN_CNT <= `UD 24'h0;
else
LED_SCAN_CNT <= `UD LED_SCAN_CNT_N;
end
always @ (*)
begin
if(LED_SCAN_CNT == `SCAN_COEF)
LED_SCAN_CNT_N = 24'h0;
else
LED_SCAN_CNT_N = LED_SCAN_CNT + 24'h1;
end
////////////
扫描时间记数器,从0到3共记4次Scan time counter, total 4 times from 0 to 3////////////////////////////////////////
always @ (posedge SYSCLK or negedge RST_B)
begin
if(!RST_B)
LED_SEL_NUM <= `UD 2'h0;
else
LED_SEL_NUM <= `UD LED_SEL_NUM_N;
end
always @ (*)
begin
if(LED_SCAN_CNT == `SCAN_COEF)
LED_SEL_NUM_N = LED_SEL_NUM +1;
else
LED_SEL_NUM_N = LED_SEL_NUM;
End
////////////
根据扫描时间记数器,依次选择1到4个LED数码管工作According to the scanning time counter, select 1 to 4 LED digital tubes to work in sequence//////////////////////
wire DISP_SEL;
assign DISP_SEL=EX_CON[0];
always @ (*)
begin
if(DISP_SEL)
case(LED_SEL_NUM)
2'b00 : COM = 4'b0001;
2'b01 : COM = 4'b0010;
2'b10 : COM = 4'b0100;
2'b11 : COM = 4'b1000;
default : COM= 4'b0000;
endcase
else
COM = 4'b0000;
end
//////
根据扫描时间记数器,依次将显示缓冲区的内容送到1到4个LED数码管显示According to the scanning time counter, the contents of the display buffer are sent to 1 to 4 LED digital tubes in turn///////////////
always @ (*)
begin
case(LED_SEL_NUM)
2'b00 : LED_DATA_HEX = EX_BUFFER[15:12];
2'b01 : LED_DATA_HEX = EX_BUFFER[11:8];
2'b10 : LED_DATA_HEX = EX_BUFFER[7:4];
2'b11 : LED_DATA_HEX = EX_BUFFER[3:0];
default : LED_DATA_HEX = 4'h0;
endcase
end
//////
显示缓冲区的内容16进制译码为0到9,a到f The contents of the display buffer are decoded in hexadecimal from 0 to 9, a to f /////////////////////////////////////
always @ (*)
begin
case(LED_DATA_HEX)
4'h0 : SEG_HEX = 8'b01111110;
4'h1 : SEG_HEX = 8'b00000110;
4'h2 : SEG_HEX = 8'b11011010;
4'h3 : SEG_HEX = 8'b11001110;
4'h4 : SEG_HEX = 8'b10100110;
4'h5 : SEG_HEX = 8'b11101100;
4'h6 : SEG_HEX = 8'b11111100;
4'h7 : SEG_HEX = 8'b01000110;
4'h8 : SEG_HEX = 8'b11111110;
4'h9 : SEG_HEX = 8'b11101110;
4'ha : SEG_HEX = 8'b11100110;
4'hb : SEG_HEX = 8'b10111100;
4'hc : SEG_HEX = 8'b10011000;
4'hd : SEG_HEX = 8'b10011110;
4'he : SEG_HEX = 8'b11111010;
4'hf : SEG_HEX = 8'b11110000;
default : SEG_HEX = 8'b01111110;
endcase
end