Kraklog

Avalon BUS + reg 설계 본문

[Harman] 하만 반도체 설계/NiosII

Avalon BUS + reg 설계

Krakens 2023. 8. 28. 10:26
728x90

  • Avalon Bus 설계

 

`timescale 1ns / 1ns

module avalon_module (
    input               clk         ,
    input               rst         ,
	input               mp_waitR	,       //Avalon bus
	input       [31:0]	mp_rData	,
    output reg  [31:0]	mp_addr	    ,
	output reg  [ 3:0] 	mp_bEn      ,  
    output reg  		mp_rD		,
	output reg  		mp_wR    	,
	output reg  [31:0]	mp_wData     
);
    
    parameter FF = 1;

    initial begin
        mp_addr     =32'hx; //unknown value
        mp_bEn      =4'bx;
        mp_rD       =1'b0;
        mp_wR       =1'b0;
      //mp_waitR    =;
      //mp_rData    =;
        mp_wData    =32'hx;

    avalon_write(32'h1000,32'hAABBCCDD);
    avalon_write(32'h1000,32'hDEADBEEF);

    end
	
	
	//avalon write (bus modeling)
    task avalon_write;
        input   [31:0]  wAddr;
        input   [31:0]  wData;
        
        begin
            @(posedge clk);
            #(FF);		   //step 1 delay
            mp_addr     = wAddr;
			mp_bEn      = 4'b1;
			mp_wR 		= 1'b1	;
			mp_wData		= wData	;
			@(posedge clk);
			while (!mp_waitR) begin  //mp_waitR == 0
				@(posedge clk);			
			end
			#(FF);
			//initial value
			mp_addr		= 32'hx ;
			mp_bEn  		= 4'bx  ;
			mp_wR 		= 1'b0  ;
			mp_wData		= 32'hx ;
		end
	
	endtask
	
endmodule

 

1nano 의 딜레이를 주기위해

parameter 의 값을 지정해주고 (parameter FF = 1) 

top module을 maste, task를 slave라 생각하여 합성하였음.

 

 

write signal이 high 일때 write data 에 그 값이 들어가는데

 

adress 32'h1000의  첫 번째에서는 avalon_write(32'h1000,32'hAABBCCDD);

코드에 따라 AABBCCDD가 들어가고

 

adress 32'h1000의 두 번째 에서는 avalon_write(32'h1000,32'hDEADBEEF);

코드에 따 DEADBEEF가 들어가게 된다.

 

`timescale 1ns / 1ns

module avalon_module (
    input               clk         ,
    input               rst         ,
	input               mp_waitR	,       //Avalon bus
	input       [31:0]	mp_rData	,
    output reg  [31:0]	mp_addr	    ,
	output reg  [ 3:0] 	mp_bEn      ,  
    output reg  		mp_rD		,
	output reg  		mp_wR    	,
	output reg  [31:0]	mp_wData     
);
    
    parameter FF = 1;

    initial begin
        mp_addr     =32'hx; //unknown value
        mp_bEn      =4'bx;
        mp_rD       =1'b0;
        mp_wR       =1'b0;
      //mp_waitR    =;
      //mp_rData    =;
        mp_wData    =32'hx;

    #200;
    avalon_write(32'h1000,32'hAABBCCDD);
    avalon_write(32'h2000,32'hDEADBEEF);
    avalon_read(32'h1000);
    avalon_read(32'h2000);

    end
	
	
	//avalon write (bus modeling)
    task avalon_write;
        input   [31:0]  wAddr;
        input   [31:0]  wData;
        
        begin
            @(posedge clk);
            #(FF);		   //step 1 delay
            mp_addr     = wAddr;
			mp_bEn      = 4'b1;
			mp_wR 		= 1'b1	;
			mp_wData		= wData	;
			@(posedge clk);
			while (mp_waitR) begin  //mp_waitR == 0
				@(posedge clk);			
			end
			#(FF);
			//initial value
			mp_addr		= 32'hx ;
			mp_bEn  	= 4'bx  ;
			mp_wR 		= 1'b0  ;
			mp_wData	= 32'hx ;
		end
	
	endtask
	
    task avalon_read;
        input   [31:0]  rAddr;

        begin
            @(posedge clk);
            #(FF);		   //step 1 delay
            mp_addr     = rAddr;
			mp_bEn      = 4'b1;
			mp_rD 		= 1'b1	;
			
			@(posedge clk);
			while (mp_waitR) begin  //mp_waitR == 0
				@(posedge clk);			
			end
			#(FF);
            $display("AV rAddr 0x%x, rData 0x%x", mp_addr, mp_rData);
			//initial value
			mp_addr		= 32'hx ;
			mp_bEn  	= 4'bx  ;
			mp_rD 		= 1'b0  ;
			@(posedge clk);
        end
    endtask

endmodule

 

avalon read 추가

 

`define clk_50MHz 20

module tb_avalon_module;
    reg             clk         ;
    reg             rst         ;
	reg             mp_waitR	;       //Avalon bus
	reg  [31:0]	    mp_rData	;
    wire [31:0]	    mp_addr	    ;
	wire [ 3:0] 	mp_bEn      ;  
    wire 			mp_rD		;
	wire 			mp_wR    	;
	wire [31:0]	    mp_wData    ;


avalon_module uAvalon_module (
    .clk        (clk     ),
    .rst        (rst     ),
	.mp_waitR   (mp_waitR),  
	.mp_rData   (mp_rData),
    .mp_addr	(mp_addr ),
	.mp_bEn     (mp_bEn  ),  
    .mp_rD	    (mp_rD	 ),
	.mp_wR      (mp_wR   ),
	.mp_wData   (mp_wData)   
);
    
initial fork
	clk_gen;
	rst_gen;
	data_gen;
join

task clk_gen; 
 begin
	clk = 1'b0;
	forever #(`clk_50MHz/2) clk = ~clk; 
 end
endtask

task rst_gen; 
 begin
	rst =1'b0;
	repeat(2) @(posedge clk);
	rst =1'b1;
	repeat(2) @(posedge clk);
	rst =1'b0;
 end
endtask

task data_gen;
begin
	#75;
	mp_rData = 32'h11223344;
end
endtask

endmodule

75ns 후에 rData에 32'h11223344 으로 초기값 할당을 해주었고

이에따른 시뮬레이션 결과는 다음과 같다.

데이터 값을 할당하지 않았다면 read data signal이 들어와도 어떤 데이터가 있는지에 대해 알 수 없게 되지만

값을 할당하고나서 초기값을 할당해주고, address 1000번과 address 2000번에 값이 읽혀 들어온다.

 

 

 

my_reg

module my_reg (    
    input           clk  ,
    input           rst  ,
    //Avalon Bus
    input           addr ,  //reg 하나만 받을거라 한비트만 사용
    input   [3:0]   bEn  ,
    input           rD   ,
    input           wR   ,
    output          waitR,
    output  [31:0]  rData,
    input   [31:0]  wData 
);
    reg [31:0] rMy_reg;

    always @(posedge clk or posedge rst) begin
        if(rst)
            rMy_reg <= 0;
        else if(wR)
            rMy_reg <= wData;
    end
    
    assign rData = rMy_reg;
    assign waitR = 1'b0;

endmodule
`define clk_50MHz 20
`define regs

module tb_avalon_module;
    reg             clk         ;
    reg             rst         ;
	//Avalon bus
	`ifdef regs
	wire           	mp_waitR	;       
	wire  [31:0]	mp_rData	;
	`else
	reg             mp_waitR	;       
	reg  [31:0]	    mp_rData	;
	`endif 
    wire [31:0]	    mp_addr	    ;
	wire [ 3:0] 	mp_bEn      ;  
    wire 			mp_rD		;
	wire 			mp_wR    	;
	wire [31:0]	    mp_wData    ;


avalon_module uAvalon_module (
    .clk        (clk     ),
    .rst        (rst     ),
	.mp_waitR   (mp_waitR),  
	.mp_rData   (mp_rData),
    .mp_addr	(mp_addr ),
	.mp_bEn     (mp_bEn  ),  
    .mp_rD	    (mp_rD	 ),
	.mp_wR      (mp_wR   ),
	.mp_wData   (mp_wData)   
);
`ifdef regs
my_reg uMy_reg (    
    .clk(clk)  	,
    .rst(rst)  	,
    //Avalon Bus
    .addr (mp_addr ), 
    .bEn  (mp_bEn  ),
    .rD   (mp_rD   ),
    .wR   (mp_wR   ),
    .waitR(mp_waitR),
    .rData(mp_rData),
    .wData(mp_wData) 
);
`else
`endif
    
initial fork
	clk_gen;
	rst_gen;
	`ifdef regs
	`else
	data_gen;
	`endif
join

task clk_gen; 
 begin
	clk = 1'b0;
	forever #(`clk_50MHz/2) clk = ~clk; 
 end
endtask

task rst_gen; 
 begin
	rst =1'b0;
	repeat(2) @(posedge clk);
	rst =1'b1;
	repeat(2) @(posedge clk);
	rst =1'b0;
 end
endtask

`ifdef regs
`else
task data_gen;
begin
	#75;
	mp_rData = 32'h11223344;
end
endtask
`endif
endmodule

avalon_write(32'h1000,32'hAABBCCDD);

avalon_write(32'h1000,32'hDEADBEEF);

위 값이 else if(wR)

rMy_reg <= wData; 에 의해

rMy_reg에 쓰여짐

 

Platform Designer을 열고, my_reg를 analyze 해준다.

 

signal을 설정해주고  intrface에서 reset sink를 맞춰준다.

 

연결해주고, 주소 값 재할당을 해주고 나면 erro 메시지가 제거 된다.

 

 

설정값을 generate 해줘서 sof 파일 생성

 

다시 quartus에 돌아와서 컴파일을 해준다.

 

 

 

 

#include <stdio.h>
#include "system.h"  

#define my_reg_baseaddr 0x00001080

int main(void)
{
   int data = 0x01010101;
   printf("before data vaule : 0x%x\n", *(volatile unsigned int *) my_reg_baseaddr);
   *(volatile unsigned int *) my_reg_baseaddr = data;
   printf("after data vaule : 0x%x", *(volatile unsigned int *) my_reg_baseaddr);
}

 

reg의 주소값에 맞춰서 코드를 수정해준다. 0x00000000 -> 0x00001080
*(volatile unsigned int *) my_reg_baseaddr = data;  ->포인터 공

 

 

bsp 파일을 빌드해주어 elf 파일 생성

그 후 run as 를 통해 실행하면 console 창에 data value 값이 나온다.

reg의 addrss 인 0x00001080 의 촉기값이 0 이였고

실행 후 0x1010101의 값이 입력됨을 확인 할 수 있다.

 

`define reg2

module my_reg (    
    input           clk  ,
    input           rst  ,
    
    //Avalon Bus
    `ifdef reg2
    input   [1:0]   addr ,
    `else
    input           addr ,  //reg 하나만 받을거라 한비트만 사용
    `endif

    input   [3:0]   bEn  ,
    input           rD   ,
    input           wR   ,
    output          waitR,
    output  [31:0]  rData,
    input   [31:0]  wData 
);
    `ifdef reg2
    reg [31:0] rMy_reg[0:3];
    
    always @(posedge clk or posedge rst) begin
    if(rst)
        rMy_reg[0] <= 0;
    else if(wR)
        rMy_reg[addr] <= wData;
    end
    assign rData = rMy_reg[addr];
    
    `else
    reg [31:0] rMy_reg;
    
    always @(posedge clk or posedge rst) begin
        if(rst)
            rMy_reg <= 0;
        else if(wR)
            rMy_reg <= wData;
    end
    assign rData = rMy_reg;
    
    `endif
    
    assign waitR = 1'b0;

endmodule

 

728x90

'[Harman] 하만 반도체 설계 > NiosII' 카테고리의 다른 글

GPIO , UART  (0) 2023.09.09
Avalon PWM, PWM Interrupt  (0) 2023.09.08
PWM / CRC  (0) 2023.08.28
Nios Processor  (0) 2023.07.28
SoC sytem  (0) 2023.07.28