4.6 Introduction to the overall design architecture
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 LED display module display.v. The overall architecture is shown below
Top-level instance module (LED.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 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 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 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 //Seven-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
////////////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
////////////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
//////
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
//////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