Kraklog
Avalon BUS + reg 설계 본문
- 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
'[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 |