本实验可按功能进行模块化设计,最终由顶层文件LED.v将各模块实例化后完成上述要求的设计。设计分为以下两个模块:寄存器接口模块interface.v,七段数码管显示模块display.v。总体架构如下图所示
顶层实例模块(LED.v):
实例化接口模块和显示模块,组成最终的完整设计
接口模块(interface.v):
用于和APB BUS进行通信,实现APB BUS MASTER对寄存器的读写操作;完成定时器操作及中断处理;
显示模块(display.v):
将显示缓冲区的内容通过七段数码管显示
4.6.1 设计模块实现
本设计实例中共包含3个Verilog文件,其对应完成整体设计中各独立模块的功能。通过从总线接口读取数据和命令,控制七段数码管显示
4.6.2 总线接口功能设计
本模块设计中共包含1个Verilog文件interface.v,完成寄存器的读写操作,定时器操作及中断处理的功能。相关代码如下:
`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,完成将显示缓冲区的内容通过七段数码管显示的功能。七段数码管显示原理图如下:
相关设计实现代码如下:
//////////计数器实现数码管扫描时间(Count system clock for Scan the led)////////////
`define SCAN_COEF 24'h1F090 //七段数码管扫描时间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到7共记8次////////////////////////////////////////
always @ (posedge SYSCLK or negedge RST_B)
begin
if(!RST_B)
LED_SEL_NUM <= `UD 3'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 +3'h1;
else
LED_SEL_NUM_N = LED_SEL_NUM;
End
////////////根据扫描时间记数器,依次选择1到8个LED数码管工作//////////////////////
wire DISP_SEL;
assign DISP_SEL=EX_CON[0];
always @ (*)
begin
if(DISP_SEL)
case(LED_SEL_NUM)
3'b000 : COM = 8'b00000001;
3'b001 : COM = 8'b00000010;
3'b010 : COM = 8'b00000100;
3'b011 : COM = 8'b00001000;
3'b100 : COM = 8'b00010000;
3'b101 : COM = 8'b00100000;
3'b110 : COM = 8'b01000000;
3'b111 : COM = 8'b10000000;
default : COM= 8'b00000000;
endcase
else
COM = 8'b00000000;
end
//////根据扫描时间记数器,依次将显示缓冲区的内容送到1到8个LED数码管显示///////////////
always @ (*)
begin
case(LED_SEL_NUM)
3'b000 : LED_DATA_HEX = EX_BUFFER[31:28];
3'b001 : LED_DATA_HEX = EX_BUFFER[27:24];
3'b010 : LED_DATA_HEX = EX_BUFFER[23:20];
3'b011 : LED_DATA_HEX = EX_BUFFER[19:16];
3'b100 : LED_DATA_HEX = EX_BUFFER[15:12];
3'b101 : LED_DATA_HEX = EX_BUFFER[11:8];
3'b110 : LED_DATA_HEX = EX_BUFFER[7:4];
3'b111 : LED_DATA_HEX = EX_BUFFER[3:0];
default : LED_DATA_HEX = 4'h0;
endcase
end
//////显示缓冲区的内容16进制译码为0到9,a到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
Add Comment