// lap_filter_axim.c
// AXI4 Master のVivado HLS出力ハードウェア・バージョン
// RGBをYに変換後にラプラシアンフィルタを掛ける。
// ピクセルのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 2013/10/15
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <ctype.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/kernel.h>
#include "lap_fil_axim_uty.h"
#define LAP_FILTER_AXIM_HW_ADDRESS 0x4a000000 // 自作ラプラシアン・フィルタのAXI4 Masterハードウェアのアドレス
#define HORIZONTAL_PIXEL_WIDTH 800
#define VERTICAL_PIXEL_WIDTH 600
#define ALL_PIXEL_VALUE (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)
#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)
#define BUFSIZE 1024
#define MEASURE_COUNT 5000
int conv_rgb2y(int rgb);
int chkhex(char *str);
volatile unsigned *setup_io(off_t mapped_addr, unsigned int *buf_addr);
int main()
{
FILE *fd;
unsigned int bitmap_dc_reg_addr;
unsigned int read_num;
volatile unsigned *bm_disp_cnt_reg;
unsigned int fb_addr, next_frame_addr;
int return_val;
struct timeval start_time, end_time;
unsigned int rmmap_cnt=0, wmmap_cnt=0;
unsigned int lap_fil_hw, *lap_fil_hw_addr;
char buf[BUFSIZE], *token;
unsigned int val;
unsigned int bitmap_buf;
gettimeofday(&start_time, NULL); // プログラム起動時の時刻を記録
// fb_start_addr.txt の内容をパイプに入れる
memset(buf, '\0', sizeof(buf)); // buf すべてに\0 を入れる
// fb_start_addr.txt を開く
fd = popen("cat /Apps/fb_start_addr.txt", "r");
if (fd != NULL){
read_num = fread(buf, sizeof(unsigned char), BUFSIZE, fd);
if (read_num > 0){
sscanf(buf, "%x\n", &fb_addr);
}
}
pclose(fd);
// ラプラシアンフィルタの結果を入れておくフレーム・バッファ
next_frame_addr = ((fb_addr + (ALL_PIXEL_VALUE*4)) & (~(int)(PAGE_SIZE-1))) + PAGE_SIZE;
// Vivado HLS で作製したラプラシアン・フィルタIPのアドレスを取得
lap_fil_hw_addr = setup_io((off_t)LAP_FILTER_AXIM_HW_ADDRESS, &lap_fil_hw);
lap_fil_initialize(lap_fil_hw_addr); // ラプラシアン・フィルタIPの初期化とap_start
lap_fil_env_set(lap_fil_hw_addr, fb_addr, next_frame_addr); // ラプラシアン・フィルタ環境セット
gettimeofday(&start_time, NULL); // プログラム起動時の時刻を記録
// ラプラシアン・フィルタAXI4 Master IPスタート
return_val = laplacian_fil_hw(lap_fil_hw_addr);
gettimeofday(&end_time, NULL);
if (end_time.tv_usec < start_time.tv_usec) {
printf("total time = %d.%6.6d sec\n", end_time.tv_sec - start_time.tv_sec - 1, 1000000 + end_time.tv_usec - start_time.tv_usec);
}
else {
printf("total time = %d.%6.6d sec\n", end_time.tv_sec - start_time.tv_sec, end_time.tv_usec - start_time.tv_usec);
}
printf("return Value = %d\n", return_val);
munmap((unsigned int *)lap_fil_hw_addr, BLOCK_SIZE);
free((unsigned int *)lap_fil_hw);
// bitmap-disp-cntrler-axi-master のアドレスを取得
memset(buf, '\0', sizeof(buf)); // buf すべてに\0 を入れる
// ls /sys/devices/axi.0 の内容をパイプに入れる
fd = popen("ls /sys/devices/axi.0", "r");
if (fd != NULL){
read_num = fread(buf, sizeof(unsigned char), BUFSIZE, fd);
if (read_num > 0){
token = buf;
if ((token=strtok(token, ".\n")) != NULL){
do {
if (chkhex(token)){ // 16進数
sscanf(token, "%x", &val);
} else {
if (strcmp(token, "bitmap-disp-cntrler-axi-master") == 0)
bitmap_dc_reg_addr = val;
}
}while((token=strtok(NULL, ".\n")) != NULL);
}
}
}
pclose(fd);
// ラプラシアンフィルタの掛かった画像のスタートアドレスを bitmap-disp-cntrler-axi-master にセット
bm_disp_cnt_reg = setup_io((off_t)bitmap_dc_reg_addr, &bitmap_buf);
*bm_disp_cnt_reg = next_frame_addr;
munmap((unsigned int *)bm_disp_cnt_reg, BLOCK_SIZE);
free((unsigned int *)bitmap_buf);
/*gettimeofday(&end_time, NULL); if (end_time.tv_usec < start_time.tv_usec) { printf("total time = %d.%6.6d sec\n", end_time.tv_sec - start_time.tv_sec - 1, 1000000 + end_time.tv_usec - start_time.tv_usec); } else { printf("total time = %d.%6.6d sec\n", end_time.tv_sec - start_time.tv_sec, end_time.tv_usec - start_time.tv_usec); } return(0);*/
}
// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y = 0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
int r, g, b, y_f;
int y;
b = rgb & 0xff;
g = (rgb>>8) & 0xff;
r = (rgb>>16) & 0xff;
y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
y = y_f >> 8; // 256で割る
return(y);
}
//
// Set up a memory regions to access GPIO
//
volatile unsigned *setup_io(off_t mapped_addr, unsigned int *buf_addr)
// void setup_io()
{
int mem_fd;
char *gpio_mem, *gpio_map;
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("can't open /dev/mem \n");
printf("mapped_addr = %x\n", mapped_addr);
exit (-1);
}
/* mmap GPIO */
// Allocate MAP block
if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
printf("allocation error \n");
exit (-1);
}
*buf_addr = gpio_mem; // mallocしたアドレスをコピー
// Make sure pointer is on 4K boundary
if ((unsigned long)gpio_mem % PAGE_SIZE)
gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE);
// Now map it
gpio_map = (unsigned char *)mmap(
(caddr_t)gpio_mem,
BLOCK_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED,
mem_fd,
mapped_addr
);
if ((long)gpio_map < 0) {
printf("mmap error %d\n", (int)gpio_map);
printf("mapped_addr = %x\n", mapped_addr);
exit (-1);
}
close(mem_fd); // /dev/mem のクローズ
// Always use volatile pointer!
// gpio = (volatile unsigned *)gpio_map;
return((volatile unsigned *)gpio_map);
} // setup_io
// 文字列が16進数かを調べる
int chkhex(char *str){
while (*str != '\0'){
if (!isxdigit(*str))
return 0;
str++;
}
return 1;
}
/* * lap_fil_axim_uty.c * * Created on: 2013/10/15 * Author: Masaaki */
#include "xlap_filter_axim_hw.h"
#define AP_START_BIT_POS 1 // ap_start のビット位置 bit0
#define AP_DONE_BIT_POS 2 // ap_done のビット位置 bit1
#define AP_AUTO_RESTART_BIT_POS 0x80 // auto_restart のビット位置 bit7
#define VLD_BIT_POS 1
void lap_fil_initialize(unsigned int *lap_fil_hw_addr)
{
*(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_CTRL) = 0;
*(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_GIE) = 0;
*(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_IER) = 1; // ap_done=1
*(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_CTRL) = 0;
*(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_CTRL) = 0;
}
// ラプラシアン・フィルタ環境セット
int lap_fil_env_set(unsigned int *lap_fil_hw_addr, unsigned int cam_fb, unsigned int lap_fb)
{
int ap_status, ap_done;
int ap_return;
int cam_fb_read, lap_fb_read;
int cam_addr_vld, lap_addr_vld;
*(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_DATA) = cam_fb;
*(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_DATA) = lap_fb;
cam_fb_read = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_DATA);
lap_fb_read = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_DATA);
// vld enable
*(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_CTRL) = VLD_BIT_POS;
*(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_CTRL) = VLD_BIT_POS;
}
// ラプラシアン・フィルタ・スタート
int laplacian_fil_hw(unsigned int *lap_fil_hw_addr)
{
int ap_status, ap_done;
int ap_return;
// ap_start enable
*(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_CTRL) = AP_START_BIT_POS;
// wait ap_done
do{
ap_status = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_CTRL);
ap_done = ap_status & AP_DONE_BIT_POS;
}while(!ap_done);
// ap_return read
ap_return = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_RETURN);
//printf("ap_return = %d\n", ap_return);
return(ap_return);
}
* lap_fil_axim_uty.h
*
* Created on: 2013/10/15
* Author: Masaaki
*/
#ifndef LAP_FIL_AXIM_UTY_H_
#define LAP_FIL_AXIM_UTY_H_
void lap_fil_initialize(unsigned int *lap_fil_hw_addr);
int laplacian_fil_hw(unsigned int *lap_fil_hw_addr);
void lap_fil_env_set(unsigned int *lap_fil_hw_addr, unsigned int *cam_fb, unsigned int *lap_fb);
#endif /* LAP_FIL_AXIM_UTY_H_ */
WARNING:Xst:2898 - Port 's_axi_lite_wstrb', unconnected in block instance 'lap_filter_axim_0', is tied to GND.
## AXI4 Lite Slave Ports
PORT s_axi_lite_awvalid = AWVALID, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_awready = AWREADY, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_awaddr = AWADDR, DIR = I, VEC = [C_S_AXI_LITE_ADDR_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_wvalid = WVALID, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_wready = WREADY, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_wdata = WDATA, DIR = I, VEC = [C_S_AXI_LITE_DATA_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_bresp = BRESP, DIR = O, VEC = [1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_bvalid = BVALID, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_bready = BREADY, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_arvalid = ARVALID, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_arready = ARREADY, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_araddr = ARADDR, DIR = I, VEC = [C_S_AXI_LITE_ADDR_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_rvalid = RVALID, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_rready = RREADY, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_rdata = RDATA, DIR = O, VEC = [C_S_AXI_LITE_DATA_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_rresp = RRESP, DIR = O, VEC = [1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
## AXI4 Lite Slave Ports
PORT s_axi_lite_awvalid = AWVALID, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_awready = AWREADY, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_awaddr = AWADDR, DIR = I, VEC = [C_S_AXI_LITE_ADDR_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_wvalid = WVALID, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_wready = WREADY, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_wdata = WDATA, DIR = I, VEC = [C_S_AXI_LITE_DATA_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_wstrb = WSTRB, DIR = I, VEC = [((C_S_AXI_LITE_DATA_WIDTH/8)-1):0], ENDIAN = LITTLE, BUS = S_AXI_LITE
PORT s_axi_lite_bresp = BRESP, DIR = O, VEC = [1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_bvalid = BVALID, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_bready = BREADY, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_arvalid = ARVALID, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_arready = ARREADY, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_araddr = ARADDR, DIR = I, VEC = [C_S_AXI_LITE_ADDR_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_rvalid = RVALID, DIR = O, BUS = S_AXI_LITE
PORT s_axi_lite_rready = RREADY, DIR = I, BUS = S_AXI_LITE
PORT s_axi_lite_rdata = RDATA, DIR = O, VEC = [C_S_AXI_LITE_DATA_WIDTH-1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
PORT s_axi_lite_rresp = RRESP, DIR = O, VEC = [1:0], BUS = S_AXI_LITE, ENDIAN = LITTLE
`default_nettype none
//
// line_read_and_y.v
// HORIZONTAL_PIXELS 分のピクセルデータを start_addr から AXI4 Master Read する
// RGB - Y変換を行い、y_data へ出力する
// 2013/11/17
//
module line_read_and_y #(
parameter integer C_M_AXI_ADDR_WIDTH = 32,
parameter integer C_M_AXI_DATA_WIDTH = 32,
parameter integer HORIZONTAL_PIXELS = 800
)
(
input wire clk,
input wire reset,
input wire [C_M_AXI_ADDR_WIDTH-1:0] start_addr,
input wire start,
output reg done,
output reg [7:0] y_data,
output reg y_data_valid,
output wire read_adfifo_wr_ena,
output reg [C_M_AXI_ADDR_WIDTH-1:0] read_adfifo_addr,
output reg [8-1:0] read_adfifo_arlen,
input wire read_adfifo_full,
output wire read_fifo_rd_ena,
input wire [C_M_AXI_DATA_WIDTH-1:0] read_fifo_read_data,
input wire read_fifo_empty_n,
input wire read_fifo_almost_empty_n
);
// Beyond Circuts, Constant Function in Verilog 2001を参照しました
// http://www.beyond-circuits.com/wordpress/2008/11/constant-functions/
function integer log2;
input integer addr;
begin
addr = addr - 1;
for (log2=0; addr>0; log2=log2+1)
addr = addr >> 1;
end
endfunction
reg [log2(HORIZONTAL_PIXELS)-1:0] h_addr_cnt;
parameter IDLE_READ_ADDR = 1'b0,
READ_ADDR_ACTIVE = 1'b1;
reg read_addr_req_cs;
wire [log2(HORIZONTAL_PIXELS)-1:0] BURST_LIMIT_VAL = 256;
wire [log2(HORIZONTAL_PIXELS)-1:0] ONE = 1;
reg op_state;
reg [log2(HORIZONTAL_PIXELS)-1:0] y_data_cnt;
// start が来たら op_state を1にする。全部のReadデータを受け取った時に0にする
always @(posedge clk) begin : proc_op_state
if(reset) begin
op_state <= 1'b0;
end else begin
if (start)
op_state <= 1'b1;
else if (y_data_cnt==ONE && y_data_valid==1'b1)
op_state <= 1'b0;
end
end
// Read Address Transaction State Machine
always @(posedge clk) begin : proc_Read_Addr_Tran_SM
if(reset) begin
read_addr_req_cs <= IDLE_READ_ADDR;
end else begin
case (read_addr_req_cs)
IDLE_READ_ADDR :
if (read_adfifo_full==1'b0 && h_addr_cnt!=0 && op_state==1'b1)
read_addr_req_cs <= READ_ADDR_ACTIVE;
READ_ADDR_ACTIVE :
read_addr_req_cs <= IDLE_READ_ADDR;
default : /* default */;
endcase
end
end
assign read_adfifo_wr_ena = (read_addr_req_cs==READ_ADDR_ACTIVE) ? 1'b1 : 1'b0;
// h_addr_cnt の処理
always @(posedge clk) begin : proc_h_addr_cnt
if(reset) begin
h_addr_cnt <= HORIZONTAL_PIXELS;
read_adfifo_arlen <= 8'd0;
end else begin
if (start) begin
h_addr_cnt <= HORIZONTAL_PIXELS;
end else if (h_addr_cnt!=0 && read_addr_req_cs==IDLE_READ_ADDR && read_adfifo_full==1'b0 && op_state==1'b1) begin
if (h_addr_cnt>=BURST_LIMIT_VAL) begin
h_addr_cnt <= h_addr_cnt - BURST_LIMIT_VAL;
read_adfifo_arlen <= 8'd255;
end else begin
h_addr_cnt <= 0;
read_adfifo_arlen <= h_addr_cnt[7:0] - 8'd1;
end
end
end
end
// read_adfifo_addr の処理
always @(posedge clk) begin : proc_read_adfifo_addr
if(reset) begin
read_adfifo_addr <= 0;
end else begin
if (start)
read_adfifo_addr <= start_addr;
else if (read_addr_req_cs == READ_ADDR_ACTIVE)
read_adfifo_addr <= read_adfifo_addr + (read_adfifo_arlen+8'd1)*(C_M_AXI_DATA_WIDTH/8);
end
end
// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y = 0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
always @(posedge clk) begin : proc_RGB2Y
reg [15:0] y_f;
reg [7:0] b, g, r;
if(reset) begin
y_data <= 8'd0;
end else begin
r = read_fifo_read_data[23:16];
g = read_fifo_read_data[15:0];
b = read_fifo_read_data[7:0];
y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
y_data <= y_f[15:8]; // 256で割る
end
end
// y_data_valid の処理
always @(posedge clk) begin : proc_y_data_valid
if(reset) begin
y_data_valid <= 1'b0;
end else begin
if (read_fifo_empty_n)
y_data_valid <= 1'b1;
else
y_data_valid <= 1'b0;
end
end
assign read_fifo_rd_ena = 1'b1;
// y_data のカウント
always @(posedge clk) begin : proc_y_data_cnt
if(reset) begin
y_data_cnt <= HORIZONTAL_PIXELS;
end else begin
if (op_state==1'b1 && y_data_valid==1'b1 && y_data_cnt!=0)
y_data_cnt <= y_data_cnt - ONE;
else if (start)
y_data_cnt <= HORIZONTAL_PIXELS;
end
end
// done の処理
always @(posedge clk) begin : proc_done
if(reset) begin
done <= 1'b0;
end else begin
if (y_data_cnt==ONE && y_data_valid==1'b1)
done <= 1'b1;
else
done <= 1'b0;
end
end
endmodule
`default_nettype wire
`default_nettype none
module Dual_Port_Memory #(
parameter integer C_MEMORY_SIZE = 1024, // Word Memory Size (not byte)
parameter integer DATA_BUS_WIDTH = 32 // RAM Data Width
)
(
input wire clk,
input wire we,
input wire [log2(C_MEMORY_SIZE)-1:0] waddr,
input wire [log2(C_MEMORY_SIZE)-1:0] raddr,
input wire [DATA_BUS_WIDTH-1:0] din,
output reg [DATA_BUS_WIDTH-1:0] dout
);
// Beyond Circuts, Constant Function in Verilog 2001を参照しました
// http://www.beyond-circuits.com/wordpress/2008/11/constant-functions/
function integer log2;
input integer addr;
begin
addr = addr - 1;
for (log2=0; addr>0; log2=log2+1)
addr = addr >> 1;
end
endfunction
reg [DATA_BUS_WIDTH-1:0] ram [0:C_MEMORY_SIZE-1];
initial begin : memory_initialize
integer i;
for (i=0; i<C_MEMORY_SIZE; i=i+1)
ram[i] = 0;
end
always @(posedge clk) begin
if (we)
ram[waddr] <= din;
dout <= ram[raddr];
end
endmodule
`default_nettype wire
// ==============================================================
// File generated by Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC
// Version: 2013.3
// Copyright (C) 2013 Xilinx Inc. All rights reserved.
//
// ==============================================================
`timescale 1ns/1ps
module lap_filter_axim_LiteS_if
#(parameter
C_ADDR_WIDTH = 6,
C_DATA_WIDTH = 32
)(
// axi4 lite slave signals
input wire ACLK,
input wire ARESETN,
input wire [C_ADDR_WIDTH-1:0] AWADDR,
input wire AWVALID,
output wire AWREADY,
input wire [C_DATA_WIDTH-1:0] WDATA,
input wire [C_DATA_WIDTH/8-1:0] WSTRB,
input wire WVALID,
output wire WREADY,
output wire [1:0] BRESP,
output wire BVALID,
input wire BREADY,
input wire [C_ADDR_WIDTH-1:0] ARADDR,
input wire ARVALID,
output wire ARREADY,
output wire [C_DATA_WIDTH-1:0] RDATA,
output wire [1:0] RRESP,
output wire RVALID,
input wire RREADY,
output wire interrupt,
// user signals
output wire [31:0] I_cam_addr,
output wire I_cam_addr_ap_vld,
input wire I_cam_addr_ap_ack,
output wire [31:0] I_lap_addr,
output wire I_lap_addr_ap_vld,
output wire I_ap_start,
input wire O_ap_ready,
input wire O_ap_done,
input wire O_ap_idle,
input wire [31:0] O_ap_return
);
//------------------------Address Info-------------------
// 0x00 : Control signals
// bit 0 - ap_start (Read/Write/COH)
// bit 1 - ap_done (Read/COR)
// bit 2 - ap_idle (Read)
// bit 3 - ap_ready (Read)
// bit 7 - auto_restart (Read/Write)
// others - reserved
// 0x04 : Global Interrupt Enable Register
// bit 0 - Global Interrupt Enable (Read/Write)
// others - reserved
// 0x08 : IP Interrupt Enable Register (Read/Write)
// bit 0 - Channel 0 (ap_done)
// bit 1 - Channel 1 (ap_ready)
// others - reserved
// 0x0c : IP Interrupt Status Register (Read/TOW)
// bit 0 - Channel 0 (ap_done)
// bit 1 - Channel 1 (ap_ready)
// others - reserved
// 0x10 : Control signal of cam_addr
// bit 0 - cam_addr_ap_vld (Read/Write/COH)
// bit 1 - cam_addr_ap_ack (Read)
// others - reserved
// 0x14 : Data signal of cam_addr
// bit 31~0 - cam_addr[31:0] (Read/Write)
// 0x18 : Control signal of lap_addr
// bit 0 - lap_addr_ap_vld (Read/Write/SC)
// others - reserved
// 0x1c : Data signal of lap_addr
// bit 31~0 - lap_addr[31:0] (Read/Write)
// 0x20 : Data signal of ap_return
// bit 31~0 - ap_return[31:0] (Read)
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)
//------------------------Parameter----------------------
// address bits
localparam
ADDR_BITS = 6;
// address
localparam
ADDR_AP_CTRL = 6'h00,
ADDR_GIE = 6'h04,
ADDR_IER = 6'h08,
ADDR_ISR = 6'h0c,
ADDR_CAM_ADDR_CTRL = 6'h10,
ADDR_CAM_ADDR_DATA_0 = 6'h14,
ADDR_LAP_ADDR_CTRL = 6'h18,
ADDR_LAP_ADDR_DATA_0 = 6'h1c,
ADDR_AP_RETURN_0 = 6'h20;
// axi write fsm
localparam
WRIDLE = 2'd0,
WRDATA = 2'd1,
WRRESP = 2'd2;
// axi read fsm
localparam
RDIDLE = 2'd0,
RDDATA = 2'd1;
//------------------------Local signal-------------------
// axi write
reg [1:0] wstate;
reg [1:0] wnext;
reg [ADDR_BITS-1:0] waddr;
wire [31:0] wmask;
wire aw_hs;
wire w_hs;
// axi read
reg [1:0] rstate;
reg [1:0] rnext;
reg [31:0] rdata;
wire ar_hs;
wire [ADDR_BITS-1:0] raddr;
// internal registers
wire ap_idle;
reg ap_done;
wire ap_ready;
reg ap_start;
reg auto_restart;
reg gie;
reg [1:0] ier;
reg [1:0] isr;
reg [31:0] _cam_addr;
reg _cam_addr_ap_vld;
wire _cam_addr_ap_ack;
reg [31:0] _lap_addr;
reg _lap_addr_ap_vld;
wire [31:0] ap_return;
//------------------------Body---------------------------
//++++++++++++++++++++++++axi write++++++++++++++++++++++
assign AWREADY = (wstate == WRIDLE);
assign WREADY = (wstate == WRDATA);
assign BRESP = 2'b00; // OKAY
assign BVALID = (wstate == WRRESP);
assign wmask = { {8{WSTRB[3]}}, {8{WSTRB[2]}}, {8{WSTRB[1]}}, {8{WSTRB[0]}} };
assign aw_hs = AWVALID & AWREADY;
assign w_hs = WVALID & WREADY;
// wstate
always @(posedge ACLK) begin
if (~ARESETN)
wstate <= WRIDLE;
else
wstate <= wnext;
end
// wnext
always @(*) begin
case (wstate)
WRIDLE:
if (AWVALID)
wnext = WRDATA;
else
wnext = WRIDLE;
WRDATA:
if (WVALID)
wnext = WRRESP;
else
wnext = WRDATA;
WRRESP:
if (BREADY)
wnext = WRIDLE;
else
wnext = WRRESP;
default:
wnext = WRIDLE;
endcase
end
// waddr
always @(posedge ACLK) begin
if (aw_hs)
waddr <= AWADDR[ADDR_BITS-1:0];
end
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++axi read+++++++++++++++++++++++
assign ARREADY = (rstate == RDIDLE);
assign RDATA = rdata;
assign RRESP = 2'b00; // OKAY
assign RVALID = (rstate == RDDATA);
assign ar_hs = ARVALID & ARREADY;
assign raddr = ARADDR[ADDR_BITS-1:0];
// rstate
always @(posedge ACLK) begin
if (~ARESETN)
rstate <= RDIDLE;
else
rstate <= rnext;
end
// rnext
always @(*) begin
case (rstate)
RDIDLE:
if (ARVALID)
rnext = RDDATA;
else
rnext = RDIDLE;
RDDATA:
if (RREADY)
rnext = RDIDLE;
else
rnext = RDDATA;
default:
rnext = RDIDLE;
endcase
end
// rdata
always @(posedge ACLK) begin
if (ar_hs) begin
rdata <= 1'b0;
case (raddr)
ADDR_AP_CTRL: begin
rdata[0] <= ap_start;
rdata[1] <= ap_done;
rdata[2] <= ap_idle;
rdata[3] <= ap_ready;
rdata[7] <= auto_restart;
end
ADDR_GIE: begin
rdata <= gie;
end
ADDR_IER: begin
rdata <= ier;
end
ADDR_ISR: begin
rdata <= isr;
end
ADDR_CAM_ADDR_CTRL: begin
rdata[0] <= _cam_addr_ap_vld;
rdata[1] <= _cam_addr_ap_ack;
end
ADDR_CAM_ADDR_DATA_0: begin
rdata <= _cam_addr[31:0];
end
ADDR_LAP_ADDR_CTRL: begin
rdata[0] <= _lap_addr_ap_vld;
end
ADDR_LAP_ADDR_DATA_0: begin
rdata <= _lap_addr[31:0];
end
ADDR_AP_RETURN_0: begin
rdata <= ap_return[31:0];
end
endcase
end
end
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++internal registers+++++++++++++
assign interrupt = gie & (|isr);
assign I_ap_start = ap_start;
assign ap_idle = O_ap_idle;
assign ap_ready = O_ap_ready;
assign I_cam_addr_ap_vld = _cam_addr_ap_vld;
assign _cam_addr_ap_ack = I_cam_addr_ap_ack;
assign I_cam_addr = _cam_addr;
assign I_lap_addr_ap_vld = _lap_addr_ap_vld;
assign I_lap_addr = _lap_addr;
assign ap_return = O_ap_return;
// ap_start
always @(posedge ACLK) begin
if (~ARESETN)
ap_start <= 1'b0;
else if (w_hs && waddr == ADDR_AP_CTRL && WSTRB[0] && WDATA[0])
ap_start <= 1'b1;
else if (O_ap_ready)
ap_start <= auto_restart; // clear on handshake/auto restart
end
// ap_done
always @(posedge ACLK) begin
if (~ARESETN)
ap_done <= 1'b0;
else if (O_ap_done)
ap_done <= 1'b1;
else if (ar_hs && raddr == ADDR_AP_CTRL)
ap_done <= 1'b0; // clear on read
end
// auto_restart
always @(posedge ACLK) begin
if (~ARESETN)
auto_restart <= 1'b0;
else if (w_hs && waddr == ADDR_AP_CTRL && WSTRB[0])
auto_restart <= WDATA[7];
end
// gie
always @(posedge ACLK) begin
if (~ARESETN)
gie <= 1'b0;
else if (w_hs && waddr == ADDR_GIE && WSTRB[0])
gie <= WDATA[0];
end
// ier
always @(posedge ACLK) begin
if (~ARESETN)
ier <= 1'b0;
else if (w_hs && waddr == ADDR_IER && WSTRB[0])
ier <= WDATA[1:0];
end
// isr[0]
always @(posedge ACLK) begin
if (~ARESETN)
isr[0] <= 1'b0;
else if (ier[0] & O_ap_done)
isr[0] <= 1'b1;
else if (w_hs && waddr == ADDR_ISR && WSTRB[0])
isr[0] <= isr[0] ^ WDATA[0]; // toggle on write
end
// isr[1]
always @(posedge ACLK) begin
if (~ARESETN)
isr[1] <= 1'b0;
else if (ier[1] & O_ap_ready)
isr[1] <= 1'b1;
else if (w_hs && waddr == ADDR_ISR && WSTRB[0])
isr[1] <= isr[1] ^ WDATA[1]; // toggle on write
end
// _cam_addr_ap_vld
always @(posedge ACLK) begin
if (~ARESETN)
_cam_addr_ap_vld <= 1'b0;
else if (w_hs && waddr == ADDR_CAM_ADDR_CTRL && WSTRB[0] && WDATA[0])
_cam_addr_ap_vld <= 1'b1;
else if (I_cam_addr_ap_ack)
_cam_addr_ap_vld <= 1'b0; // clear on handshake
end
// _cam_addr[31:0]
always @(posedge ACLK) begin
if (w_hs && waddr == ADDR_CAM_ADDR_DATA_0)
_cam_addr[31:0] <= (WDATA[31:0] & wmask) | (_cam_addr[31:0] & ~wmask);
end
// _lap_addr_ap_vld
always @(posedge ACLK) begin
if (~ARESETN)
_lap_addr_ap_vld <= 1'b0;
else if (w_hs && waddr == ADDR_LAP_ADDR_CTRL && WSTRB[0] && WDATA[0])
_lap_addr_ap_vld <= 1'b1;
else
_lap_addr_ap_vld <= 1'b0; // self clear
end
// _lap_addr[31:0]
always @(posedge ACLK) begin
if (w_hs && waddr == ADDR_LAP_ADDR_DATA_0)
_lap_addr[31:0] <= (WDATA[31:0] & wmask) | (_lap_addr[31:0] & ~wmask);
end
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
endmodule
1.画像データのDDR3メモリのアドレスと、ラプラシアン・フィルタ後の画像データのDDR3メモリのアドレスを内部レジスタに AXI4 Lite Slave アクセスでARMプロセッサからレジスタにWriteしてもらう。この行為に依って、ラプラシアン・フィルタ回路が動作する。
2.DDR3 メモリから画像データを1ライン分、AXI4 Master Read Transaction でRead する。
3.ラプラシアン・フィルタを掛けた後に、異なるDDR3 メモリのアドレスに、AXI4 Master Write Transaction でフィルタ後の1ライン分の画像データをWriteする。
3.2.から3.を1フレーム分行う。
4.レジスタのap_done ビットをセットする。
`default_nettype none
//
// lap_filter_axim.v
// 2013/11/13 by marsee
//
module lap_filter_axim #(/*autoport*/
// AXI4 Lite Slave Interface
parameter integer C_S_AXI_LITE_ADDR_WIDTH = 9,
parameter integer C_S_AXI_LITE_DATA_WIDTH = 32,
// AXI Master Interface
parameter integer C_INTERCONNECT_M_AXI_WRITE_ISSUING = 8,
parameter integer C_M_AXI_THREAD_ID_WIDTH = 1,
parameter integer C_M_AXI_ADDR_WIDTH = 32,
parameter integer C_M_AXI_DATA_WIDTH = 32,
parameter integer C_M_AXI_AWUSER_WIDTH = 1,
parameter integer C_M_AXI_ARUSER_WIDTH = 1,
parameter integer C_M_AXI_WUSER_WIDTH = 1,
parameter integer C_M_AXI_RUSER_WIDTH = 1,
parameter integer C_M_AXI_BUSER_WIDTH = 1,
parameter [31:0] C_M_AXI_TARGET = 32'h00000000,
parameter integer C_M_AXI_BURST_LEN = 256,
parameter integer C_OFFSET_WIDTH = 32,
/* Disabling these parameters will remove any throttling.
The resulting ERROR flag will not be useful */
parameter integer C_M_AXI_SUPPORTS_WRITE = 1,
parameter integer C_M_AXI_SUPPORTS_READ = 1,
parameter integer HORIZONTAL_PIXELS = 800,
parameter integer VERTICAL_LINES = 600
)
(
// Clocks and Reset
input wire s_axi_lite_aclk,
input wire M_AXI_ACLK,
input wire ARESETN,
///////////////////////////////
// AXI4 Lite Slave Interface //
///////////////////////////////
// AXI Lite Write Address Channel
input wire s_axi_lite_awvalid,
output wire s_axi_lite_awready,
input wire [C_S_AXI_LITE_ADDR_WIDTH-1:0] s_axi_lite_awaddr,
// AXI Lite Write Data Channel
input wire s_axi_lite_wvalid,
output wire s_axi_lite_wready,
input wire [C_S_AXI_LITE_DATA_WIDTH-1:0] s_axi_lite_wdata,
input wire [C_S_AXI_LITE_DATA_WIDTH/8-1:0] s_axi_lite_wstrb,
// AXI Lite Write Response Channel
output wire [1:0] s_axi_lite_bresp,
output wire s_axi_lite_bvalid,
input wire s_axi_lite_bready,
// AXI Lite Read Address Channel
input wire s_axi_lite_arvalid,
output wire s_axi_lite_arready,
input wire [C_S_AXI_LITE_ADDR_WIDTH-1:0] s_axi_lite_araddr,
// AXI Lite Read Data Channel
output wire s_axi_lite_rvalid,
input wire s_axi_lite_rready,
output wire [C_S_AXI_LITE_DATA_WIDTH-1:0] s_axi_lite_rdata,
output wire [1:0] s_axi_lite_rresp,
///////////////////////////////
// AXI4 Master Interface //
///////////////////////////////
// Master Interface Write Address
output wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_AWID,
output wire [C_M_AXI_ADDR_WIDTH-1:0] M_AXI_AWADDR,
output wire [8-1:0] M_AXI_AWLEN,
output wire [3-1:0] M_AXI_AWSIZE,
output wire [2-1:0] M_AXI_AWBURST,
output wire M_AXI_AWLOCK,
output wire [4-1:0] M_AXI_AWCACHE,
output wire [3-1:0] M_AXI_AWPROT,
// AXI3 output wire [4-1:0] M_AXI_AWREGION,
output wire [4-1:0] M_AXI_AWQOS,
output wire [C_M_AXI_AWUSER_WIDTH-1:0] M_AXI_AWUSER,
output wire M_AXI_AWVALID,
input wire M_AXI_AWREADY,
// Master Interface Write Data
// AXI3 output wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_WID,
output wire [C_M_AXI_DATA_WIDTH-1:0] M_AXI_WDATA,
output wire [C_M_AXI_DATA_WIDTH/8-1:0] M_AXI_WSTRB,
output wire M_AXI_WLAST,
output wire [C_M_AXI_WUSER_WIDTH-1:0] M_AXI_WUSER,
output wire M_AXI_WVALID,
input wire M_AXI_WREADY,
// Master Interface Write Response
input wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_BID,
input wire [2-1:0] M_AXI_BRESP,
input wire [C_M_AXI_BUSER_WIDTH-1:0] M_AXI_BUSER,
input wire M_AXI_BVALID,
output wire M_AXI_BREADY,
// Master Interface Read Address
output wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_ARID,
output wire [C_M_AXI_ADDR_WIDTH-1:0] M_AXI_ARADDR,
output wire [8-1:0] M_AXI_ARLEN,
output wire [3-1:0] M_AXI_ARSIZE,
output wire [2-1:0] M_AXI_ARBURST,
output wire [2-1:0] M_AXI_ARLOCK,
output wire [4-1:0] M_AXI_ARCACHE,
output wire [3-1:0] M_AXI_ARPROT,
// AXI3 output wire [4-1:0] M_AXI_ARREGION,
output wire [4-1:0] M_AXI_ARQOS,
output wire [C_M_AXI_ARUSER_WIDTH-1:0] M_AXI_ARUSER,
output wire M_AXI_ARVALID,
input wire M_AXI_ARREADY,
// Master Interface Read Data
input wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_RID,
input wire [C_M_AXI_DATA_WIDTH-1:0] M_AXI_RDATA,
input wire [2-1:0] M_AXI_RRESP,
input wire M_AXI_RLAST,
input wire [C_M_AXI_RUSER_WIDTH-1:0] M_AXI_RUSER,
input wire M_AXI_RVALID,
output wire M_AXI_RREADY,
// User Signals
output wire interrupt,
// Error Signal
output reg write_fifo_overflow
);
// Beyond Circuts, Constant Function in Verilog 2001
// http://www.beyond-circuits.com/wordpress/2008/11/constant-functions/
function integer log2;
input integer addr;
begin
addr = addr - 1;
for (log2=0; addr>0; log2=log2+1)
addr = addr >> 1;
end
endfunction
wire [31:0] I_cam_addr;
wire I_cam_addr_ap_vld;
reg I_cam_addr_ap_ack;
wire [31:0] I_lap_addr;
wire I_lap_addr_ap_vld;
wire I_ap_start;
wire O_ap_ready;
wire O_ap_done;
wire O_ap_idle;
wire [31:0] O_ap_return;
reg lap_addr_ap_vld_hold;
reg write_adfifo_wr_ena;
reg [C_M_AXI_ADDR_WIDTH-1:0] write_adfifo_addr;
reg [7:0] write_adfifo_awlen;
reg write_fifo_wr_ena;
wire [31:0] write_fifo_write_data;
wire [3:0] write_fifo_wstrb;
wire read_adfifo_wr_ena;
wire [31:0] read_adfifo_addr;
wire [7:0] read_adfifo_arlen;
wire read_fifo_rd_ena;
reg init_done;
wire write_adfifo_full;
wire write_fifo_full;
wire write_fifo_almost_full;
wire read_adfifo_full;
wire [31:0] read_fifo_read_data;
wire read_fifo_empty_n;
wire read_fifo_almost_empty_n;
wire wr_resp_err;
parameter [2:0] IDLE_MAIN = 3'b000,
LINE_READ_AND_Y_1ST = 3'b001,
LINE_READ_AND_Y_2ND = 3'b011,
LINE_READ_AND_Y = 3'b010,
LAP_FILTER_AND_WRITE = 3'b110,
WAIT_AXI_WRITE_TRANSACTION = 3'b111,
AP_DONE_ACTIVE = 3'b101;
reg [2:0] main_cs;
parameter [1:0] IDLE_LINE_READ_AND_Y = 2'b00,
LINE_READ_AND_Y_START = 2'b01,
LINE_READ_AND_Y_ACTIVE = 2'b11;
reg [1:0] line_read_y_cs;
reg line_read_y_start;
reg [C_M_AXI_ADDR_WIDTH-1:0] start_addr;
wire line_read_y_done;
wire [7:0] y_data;
wire y_data_valid;
reg [1:0] line_buffer_wcount, line_buffer_rcount;
wire line_buf0_we, line_buf1_we, line_buf2_we;
wire [7:0] line_buf_dout0, line_buf_dout1, line_buf_dout2;
reg [9:0] line_buf_waddr, line_buf_raddr;
reg [7:0] Xp1Ym1, Xp1Yn, Xp1Yp1;
reg [7:0] XnYm1, XnYn, XnYp1, Xm1Ym1, Xm1Yn, Xm1Yp1;
reg [7:0] lap_filter_out;
reg [log2(HORIZONTAL_PIXELS)-1:0] lap_pixel_count;
reg [log2(VERTICAL_LINES)-1:0] lap_line_count;
parameter IDLE_WRITE_ADDR = 1'b0,
WRITE_ADDR_ISSUE = 1'b1;
reg write_addr_cs;
reg [log2(HORIZONTAL_PIXELS)-1:0] write_addr_count;
wire ACLK;
wire lap_line_end;
wire lap_frame_end;
wire write_fifo_empty;
assign ACLK = M_AXI_ACLK;
// AXI4 Lite Slave Module
lap_filter_axim_LiteS_if #(
.C_ADDR_WIDTH(C_S_AXI_LITE_ADDR_WIDTH),
.C_DATA_WIDTH(C_S_AXI_LITE_DATA_WIDTH)
) lap_filter_axim_LiteS_if_U(
.ACLK(s_axi_lite_aclk),
.ARESETN(ARESETN),
.AWADDR(s_axi_lite_awaddr),
.AWVALID(s_axi_lite_awvalid),
.AWREADY(s_axi_lite_awready),
.WDATA(s_axi_lite_wdata),
.WSTRB(s_axi_lite_wstrb),
.WVALID(s_axi_lite_wvalid),
.WREADY(s_axi_lite_wready),
.BRESP(s_axi_lite_bresp),
.BVALID(s_axi_lite_bvalid),
.BREADY(s_axi_lite_bready),
.ARADDR(s_axi_lite_araddr),
.ARVALID(s_axi_lite_arvalid),
.ARREADY(s_axi_lite_arready),
.RDATA(s_axi_lite_rdata),
.RRESP(s_axi_lite_rresp),
.RVALID(s_axi_lite_rvalid),
.RREADY(s_axi_lite_rready),
.interrupt(interrupt),
.I_cam_addr(I_cam_addr),
.I_cam_addr_ap_vld(I_cam_addr_ap_vld),
.I_cam_addr_ap_ack(I_cam_addr_ap_ack),
.I_lap_addr(I_lap_addr),
.I_lap_addr_ap_vld(I_lap_addr_ap_vld),
.I_ap_start(I_ap_start),
.O_ap_ready(O_ap_ready),
.O_ap_done(O_ap_done),
.O_ap_idle(O_ap_idle),
.O_ap_return(O_ap_return)
);
// I_lap_addr_ap_vld
always @(posedge ACLK) begin : proc_lap_addr_ap_valid_hold
if(~ARESETN) begin
lap_addr_ap_vld_hold <= 1'b0;
end else begin
if (I_lap_addr_ap_vld)
lap_addr_ap_vld_hold <= 1'b1;
end
end
// cam_addr_ap_vld, lap_addr_ap_vld init_done
always @(posedge s_axi_lite_aclk) begin : proc_init_done
if(~ARESETN) begin
init_done <= 1'b0;
I_cam_addr_ap_ack <= 1'b0;
end else begin
if (lap_addr_ap_vld_hold & I_cam_addr_ap_vld) begin
init_done <= 1'b1;
I_cam_addr_ap_ack <= 1'b1;
end
end
end
assign O_ap_return = 32'd1;
// axi4_master_inf instance
axi4_master_inf #(
.C_M_AXI_DATA_WIDTH(32)
) axi4_master_inf_U (
.ACLK(ACLK),
.ARESETN(ARESETN),
.M_AXI_AWID(M_AXI_AWID),
.M_AXI_AWADDR(M_AXI_AWADDR),
.M_AXI_AWLEN(M_AXI_AWLEN),
.M_AXI_AWSIZE(M_AXI_AWSIZE),
.M_AXI_AWBURST(M_AXI_AWBURST),
.M_AXI_AWLOCK(M_AXI_AWLOCK),
.M_AXI_AWCACHE(M_AXI_AWCACHE),
.M_AXI_AWPROT(M_AXI_AWPROT),
.M_AXI_AWQOS(M_AXI_AWQOS),
.M_AXI_AWUSER(M_AXI_AWUSER),
.M_AXI_AWVALID(M_AXI_AWVALID),
.M_AXI_AWREADY(M_AXI_AWREADY),
.M_AXI_WDATA(M_AXI_WDATA),
.M_AXI_WSTRB(M_AXI_WSTRB),
.M_AXI_WLAST(M_AXI_WLAST),
.M_AXI_WUSER(M_AXI_WUSER),
.M_AXI_WVALID(M_AXI_WVALID),
.M_AXI_WREADY(M_AXI_WREADY),
.M_AXI_BID(M_AXI_BID),
.M_AXI_BRESP(M_AXI_BRESP),
.M_AXI_BUSER(M_AXI_BUSER),
.M_AXI_BVALID(M_AXI_BVALID),
.M_AXI_BREADY(M_AXI_BREADY),
.M_AXI_ARID(M_AXI_ARID),
.M_AXI_ARADDR(M_AXI_ARADDR),
.M_AXI_ARLEN(M_AXI_ARLEN),
.M_AXI_ARSIZE(M_AXI_ARSIZE),
.M_AXI_ARBURST(M_AXI_ARBURST),
.M_AXI_ARLOCK(M_AXI_ARLOCK),
.M_AXI_ARCACHE(M_AXI_ARCACHE),
.M_AXI_ARPROT(M_AXI_ARPROT),
.M_AXI_ARQOS(M_AXI_ARQOS),
.M_AXI_ARUSER(M_AXI_ARUSER),
.M_AXI_ARVALID(M_AXI_ARVALID),
.M_AXI_ARREADY(M_AXI_ARREADY),
.M_AXI_RID(M_AXI_RID),
.M_AXI_RDATA(M_AXI_RDATA),
.M_AXI_RRESP(M_AXI_RRESP),
.M_AXI_RLAST(M_AXI_RLAST),
.M_AXI_RUSER(M_AXI_RUSER),
.M_AXI_RVALID(M_AXI_RVALID),
.M_AXI_RREADY(M_AXI_RREADY),
.write_clk(ACLK),
.write_rst(~ARESETN),
.write_adfifo_wr_ena(write_adfifo_wr_ena),
.write_adfifo_addr(write_adfifo_addr),
.write_adfifo_awlen(write_adfifo_awlen),
.write_adfifo_full(write_adfifo_full),
.write_fifo_wr_ena(write_fifo_wr_ena),
.write_fifo_write_data(write_fifo_write_data),
.write_fifo_wstrb(write_fifo_wstrb),
.write_fifo_full(write_fifo_full),
.write_fifo_almost_full(write_fifo_almost_full),
.write_fifo_empty(write_fifo_empty),
.read_clk(ACLK),
.read_rst(~ARESETN),
.read_adfifo_wr_ena(read_adfifo_wr_ena),
.read_adfifo_addr(read_adfifo_addr),
.read_adfifo_arlen(read_adfifo_arlen),
.read_adfifo_full(read_adfifo_full),
.read_fifo_rd_ena(read_fifo_rd_ena),
.read_fifo_read_data(read_fifo_read_data),
.read_fifo_empty_n(read_fifo_empty_n),
.read_fifo_almost_empty_n(read_fifo_almost_empty_n),
.wr_resp_err(wr_resp_err),
.init_done(init_done)
);
// write_fifo_overflow
always @(posedge ACLK) begin : proc_write_fifo_overflow
if(~ARESETN) begin
write_fifo_overflow <= 1'b0;
end else begin
if (write_fifo_full & write_adfifo_wr_ena)
write_fifo_overflow <= 1'b1;
end
end
// Main State Machine
always @(posedge ACLK) begin : proc_main_sm
if(~ARESETN) begin
main_cs <= IDLE_MAIN;
end else begin
case (main_cs)
IDLE_MAIN :
if (init_done & I_ap_start) begin
main_cs <= LINE_READ_AND_Y_1ST;
end
LINE_READ_AND_Y_1ST :
if (line_read_y_done) begin
main_cs <= LINE_READ_AND_Y;
end
LINE_READ_AND_Y :
if (line_read_y_done) begin
main_cs <= LAP_FILTER_AND_WRITE;
end
LAP_FILTER_AND_WRITE :
if (lap_frame_end) begin
main_cs <= AP_DONE_ACTIVE;
end else if (lap_line_end) begin
main_cs <= WAIT_AXI_WRITE_TRANSACTION;
end
WAIT_AXI_WRITE_TRANSACTION : // Write Transaction が完了するまでWait
if (write_fifo_empty)
main_cs <= LINE_READ_AND_Y;
AP_DONE_ACTIVE : begin
main_cs <= IDLE_MAIN;
end
default : /* default */;
endcase
end
end
assign O_ap_done = (main_cs==AP_DONE_ACTIVE) ? 1'b1 : 1'b0;
assign O_ap_ready = (main_cs==AP_DONE_ACTIVE) ? 1'b1 : 1'b0;
assign O_ap_idle = (main_cs==IDLE_MAIN) ? 1'b1 : 1'b0;
// 1 line Read State Machine
always @(posedge ACLK) begin : proc_line_read_and_y_SM
if(~ARESETN) begin
line_read_y_cs <= IDLE_LINE_READ_AND_Y;
line_read_y_start <= 1'b0;
end else begin
case (line_read_y_cs)
IDLE_LINE_READ_AND_Y :
if (main_cs==LINE_READ_AND_Y_1ST || main_cs==LINE_READ_AND_Y_2ND || main_cs==LINE_READ_AND_Y) begin
line_read_y_cs <= LINE_READ_AND_Y_START;
line_read_y_start <= 1'b1;
end
LINE_READ_AND_Y_START : begin
line_read_y_cs <= LINE_READ_AND_Y_ACTIVE;
line_read_y_start <= 1'b0;
end
LINE_READ_AND_Y_ACTIVE :
if (line_read_y_done)
line_read_y_cs <= IDLE_LINE_READ_AND_Y;
default : /* default */;
endcase
end
end
line_read_and_y #(
.C_M_AXI_ADDR_WIDTH(32),
.C_M_AXI_DATA_WIDTH(32),
.HORIZONTAL_PIXELS(800)
) line_read_and_y_U (/*autoinst*/
.clk(ACLK),
.reset(~ARESETN),
.start_addr(start_addr[C_M_AXI_ADDR_WIDTH-1:0]),
.start(line_read_y_start),
.done(line_read_y_done),
.y_data(y_data[7:0]),
.y_data_valid(y_data_valid),
.read_adfifo_wr_ena(read_adfifo_wr_ena),
.read_adfifo_addr(read_adfifo_addr[C_M_AXI_ADDR_WIDTH-1:0]),
.read_adfifo_arlen(read_adfifo_arlen[8-1:0]),
.read_fifo_rd_ena(read_fifo_rd_ena),
.read_adfifo_full(read_adfifo_full),
.read_fifo_read_data(read_fifo_read_data[C_M_AXI_DATA_WIDTH-1:0]),
.read_fifo_empty_n(read_fifo_empty_n),
.read_fifo_almost_empty_n(read_fifo_almost_empty_n)
);
// line_read_and_y の start_addr の処理
always @(posedge ACLK) begin : proc_start_addr
if(~ARESETN) begin
start_addr <= 0;
end else begin
if (I_cam_addr_ap_vld)
start_addr <= I_cam_addr;
else if (line_read_y_start) begin
start_addr <= start_addr + HORIZONTAL_PIXELS*(C_M_AXI_DATA_WIDTH/8);
end
end
end
// line buffer として使用するDual Port Memory を決定する
always @(posedge ACLK) begin : proc_line_buffer_wcount
if(~ARESETN) begin
line_buffer_wcount <= 2'd0;
end else begin
if (line_read_y_done) begin
if (line_buffer_wcount == 2'd2)
line_buffer_wcount <= 2'd0;
else
line_buffer_wcount <= line_buffer_wcount + 2'd1;
end
end
end
assign line_buf0_we = (line_buffer_wcount==2'd0 && y_data_valid==1'b1) ? 1'b1 : 1'b0;
assign line_buf1_we = (line_buffer_wcount==2'd1 && y_data_valid==1'b1) ? 1'b1 : 1'b0;
assign line_buf2_we = (line_buffer_wcount==2'd2 && y_data_valid==1'b1) ? 1'b1 : 1'b0;
// line buffer 0
Dual_Port_Memory #(
.C_MEMORY_SIZE(1024),
.DATA_BUS_WIDTH(8)
) line_buffer_0 (/*autoinst*/
.dout(line_buf_dout0),
.clk(ACLK),
.we(line_buf0_we),
.waddr(line_buf_waddr),
.raddr(line_buf_raddr),
.din(y_data)
);
// line buffer 1
Dual_Port_Memory #(
.C_MEMORY_SIZE(1024),
.DATA_BUS_WIDTH(8)
) line_buffer_1 (/*autoinst*/
.dout(line_buf_dout1),
.clk(ACLK),
.we(line_buf1_we),
.waddr(line_buf_waddr),
.raddr(line_buf_raddr),
.din(y_data)
);
// line buffer 2
Dual_Port_Memory #(
.C_MEMORY_SIZE(1024),
.DATA_BUS_WIDTH(8)
) line_buffer_2 (/*autoinst*/
.dout(line_buf_dout2),
.clk(ACLK),
.we(line_buf2_we),
.waddr(line_buf_waddr),
.raddr(line_buf_raddr),
.din(y_data)
);
// line_buf_waddr
always @(posedge ACLK) begin : proc_line_buf_waddr
if(~ARESETN) begin
line_buf_waddr <= 10'd0;
end else begin
if (line_read_y_start)
line_buf_waddr <= 10'd0;
else if (y_data_valid)
line_buf_waddr <= line_buf_waddr + 10'd1;
end
end
// line_buf_raddr
always @(posedge ACLK) begin : proc_line_buf_raddr
if(~ARESETN) begin
line_buf_raddr <= 10'd0;
end else begin
if (main_cs == LAP_FILTER_AND_WRITE)
line_buf_raddr <= line_buf_raddr + 10'd1;
else
line_buf_raddr <= 10'd0;
end
end
// line_buffer_rcount
always @(posedge ACLK) begin : proc_line_buffer_rcount
if(~ARESETN) begin
line_buffer_rcount <= 2'd0;
end else begin
if (lap_line_end) begin
if (line_buffer_rcount==2'd2)
line_buffer_rcount <= 2'd0;
else
line_buffer_rcount <= line_buffer_rcount + 2'd1;
end
end
end
// Xp1Ym1, Xp1Yn, Xp1Yp1
// 最初のラインは3ライン揃っていない状態でオール0の値を出力するので、3ライン揃うのはline_buffer_rcount==1の時からなので、1つずれている
always @(posedge ACLK) begin : proc_XY_first_input
if(~ARESETN) begin
Xp1Ym1 <= 8'd0;
Xp1Yn <= 8'd0;
Xp1Yp1 <= 8'd0;
end else begin
if (main_cs == LAP_FILTER_AND_WRITE) begin
case (line_buffer_rcount)
2'd0 : begin
Xp1Ym1 <= line_buf_dout2;
Xp1Yn <= line_buf_dout0;
Xp1Yp1 <= line_buf_dout1;
end
2'd1 : begin
Xp1Ym1 <= line_buf_dout0;
Xp1Yn <= line_buf_dout1;
Xp1Yp1 <= line_buf_dout2;
end
2'd2 : begin
Xp1Ym1 <= line_buf_dout1;
Xp1Yn <= line_buf_dout2;
Xp1Yp1 <= line_buf_dout0;
end
default : /* default */;
endcase
end
end
end
// XnYm1, XnYn, XnYp1, Xm1Ym1, Xm1Yn, Xm1Yp1
always @(posedge ACLK) begin : proc_XY_2_3_stage
if(~ARESETN) begin
XnYm1 <= 8'd0;
XnYn <= 8'd0;
XnYp1 <= 8'd0;
Xm1Ym1 <= 8'd0;
Xm1Yn <= 8'd0;
Xm1Yp1 <= 8'd0;
end else begin
XnYm1 <= Xp1Ym1;
XnYn <= Xp1Yn;
XnYp1 <= Xp1Yp1;
Xm1Ym1 <= XnYm1;
Xm1Yn <= XnYn;
Xm1Yp1 <= XnYp1;
end
end
// laplacian filter
// DPMで1クロック、ラプラシアン・フィルタ用FFで3クロック遅延している
always @(posedge ACLK) begin : proc_laplacian_filter
reg [12:0] laplacian_filter;
if(~ARESETN) begin
lap_filter_out <= 8'd0;
end else begin
laplacian_filter = {1'b0, XnYn, 3'b000} - {4'b0000, Xp1Ym1} - {4'b0000, Xp1Yn} - {4'b0000, Xp1Yp1} - {4'b0000, XnYm1} - {4'b0000, XnYm1} - {4'b0000, Xm1Ym1} - {4'b0000, Xm1Yn} - {4'b0000, Xm1Yp1};
// 1line のうちの最初と最後は0
// DPMで1クロック、ラプラシアン・フィルタ用FFで3クロック遅延している。つまりデータが出てくるのは、lap_pixel_count=4 の時
if (main_cs==LAP_FILTER_AND_WRITE && lap_pixel_count>=4 && lap_pixel_count<HORIZONTAL_PIXELS+2 && lap_line_count>=1 && lap_line_count<VERTICAL_LINES-1) begin
if (laplacian_filter[11]) // minus
lap_filter_out <= 8'd0;
else if (laplacian_filter[10]==1'b1 || laplacian_filter[9]==1'b1 || laplacian_filter[8]==1'b1)
lap_filter_out <= 8'd255;
else
lap_filter_out <= laplacian_filter[7:0];
end else
lap_filter_out <= 8'd0;
end
end
assign write_fifo_write_data = {8'b0000_0000, lap_filter_out, lap_filter_out, lap_filter_out}; // 8'd0, R, G, B
assign write_fifo_wstrb = 4'b1111;
// lap_pixel_count
// ラプラシアン/フィルタの1 line = lap_pixel_count>=3 && lap_pixel_count<HORIZONTAL_PIXELS+3
always @(posedge ACLK) begin : proc_lap_pixel_count
if(~ARESETN) begin
lap_pixel_count <= 0;
end else begin
if (main_cs==LAP_FILTER_AND_WRITE) begin
if (lap_pixel_count == HORIZONTAL_PIXELS+2)
lap_pixel_count <= 0;
else
lap_pixel_count <= lap_pixel_count + 1;
end else
lap_pixel_count <= 0;
end
end
assign lap_line_end = (lap_pixel_count==HORIZONTAL_PIXELS+2) ? 1'b1 : 1'b0;
// lap_line_count
always @(posedge ACLK) begin : proc_lap_line_count
if(~ARESETN) begin
lap_line_count <= 0;
end else begin
if (main_cs==LAP_FILTER_AND_WRITE) begin
if (lap_pixel_count==HORIZONTAL_PIXELS+2) begin
if (lap_line_count==VERTICAL_LINES-1)
lap_line_count <= 0;
else
lap_line_count <= lap_line_count + 1;
end
end
end
end
assign lap_frame_end = (lap_pixel_count==HORIZONTAL_PIXELS+2 && lap_line_count==VERTICAL_LINES-1) ? 1'b1 : 1'b0;
// wirte_fifo_wr_ena
// ラプラシアン/フィルタの1 line = lap_pixel_count>=3 && lap_pixel_count<HORIZONTAL_PIXELS+3
// write_adfifo_wr_ena の enable は、1クロック早く、ap_pixel_count==2 でenableし、ap_pixel_count==HORIZONTAL_PIXELS+2でディスエーブル
always @(posedge ACLK) begin : proc_wirte_fifo_wr_ena
if(~ARESETN) begin
write_fifo_wr_ena <= 1'b0;
end else begin
if (write_fifo_almost_full)
write_fifo_wr_ena <= 1'b0;
else if (lap_pixel_count==2)
write_fifo_wr_ena <= 1'b1;
else if (lap_pixel_count==HORIZONTAL_PIXELS+2)
write_fifo_wr_ena <= 1'b0;
end
end
// write_adfifo_wr_ena, write_adfifo_wr_ena State Machine
always @(posedge ACLK) begin : proc_write_addr_SM
if(~ARESETN) begin
write_addr_cs <= IDLE_WRITE_ADDR;
write_adfifo_wr_ena <= 1'b0;
end else begin
case (write_addr_cs)
IDLE_WRITE_ADDR :
if (main_cs==LAP_FILTER_AND_WRITE && write_addr_count!=0) begin
write_addr_cs <= WRITE_ADDR_ISSUE;
write_adfifo_wr_ena <= 1'b1;
end
WRITE_ADDR_ISSUE :
begin
write_addr_cs <= IDLE_WRITE_ADDR;
write_adfifo_wr_ena <= 1'b0;
end
default : /* default */;
endcase
end
end
// write_addr_count, write_adfifo_awlen
always @(posedge ACLK) begin : proc_write_addr_count
if(~ARESETN) begin
write_addr_count <= HORIZONTAL_PIXELS;
write_adfifo_awlen <= 8'd255;
end else begin
if (write_addr_cs==IDLE_WRITE_ADDR && main_cs==LAP_FILTER_AND_WRITE && write_addr_count!=0) begin
if (write_addr_count >= 256) begin
write_addr_count <= write_addr_count - 10'd256;
write_adfifo_awlen <= 8'd255;
end else begin // less than 256
write_addr_count <= 10'd0;
write_adfifo_awlen <= write_addr_count[7:0]-8'd1;
end
end else if (main_cs == LINE_READ_AND_Y)
write_addr_count <= HORIZONTAL_PIXELS;
end
end
// write_adfifo_addr
always @(posedge ACLK) begin : proc_write_addr
if(~ARESETN) begin
write_adfifo_addr <= I_lap_addr;
end else begin
if (I_lap_addr_ap_vld)
write_adfifo_addr <= I_lap_addr;
else if (write_adfifo_wr_ena)
write_adfifo_addr <= write_adfifo_addr + (write_adfifo_awlen + 8'd1)*(C_M_AXI_DATA_WIDTH/8);
end
end
endmodule
`default_nettype wire
// Main State Machine
always @(posedge ACLK) begin : proc_main_sm
if(~ARESETN) begin
main_cs <= IDLE_MAIN;
end else begin
case (main_cs)
IDLE_MAIN :
if (init_done & I_ap_start) begin
main_cs <= LINE_READ_AND_Y_1ST;
end
LINE_READ_AND_Y_1ST :
if (line_read_y_done) begin
main_cs <= LINE_READ_AND_Y;
end
LINE_READ_AND_Y :
if (line_read_y_done) begin
main_cs <= LAP_FILTER_AND_WRITE;
end
LAP_FILTER_AND_WRITE :
if (lap_frame_end) begin
main_cs <= AP_DONE_ACTIVE;
end else if (lap_line_end) begin
main_cs <= WAIT_AXI_WRITE_TRANSACTION;
end
WAIT_AXI_WRITE_TRANSACTION : // Write Transaction が完了するまでWait
if (write_fifo_empty)
main_cs <= LINE_READ_AND_Y;
AP_DONE_ACTIVE : begin
main_cs <= IDLE_MAIN;
end
default : /* default */;
endcase
end
end
`default_nettype none
`timescale 100ps / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 18:18:43 11/22/2013
// Design Name: lap_filter_axim
// Module Name: D:/HDL/FndtnISEWork/Zynq-7000/ZedBoard/Zed_OOB_Design2_HLS/hw/xps_proj/pcores/lap_filter_axim_v1_00_a/lap_filter_axim/lap_filter_axim_tb.v
// Project Name: lap_filter_axim
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: lap_filter_axim
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
module lap_filter_axim_tb;
parameter integer C_S_AXI_LITE_ADDR_WIDTH = 9; // Address width of the AXI Lite Interface
parameter integer C_S_AXI_LITE_DATA_WIDTH = 32; // Data width of the AXI Lite Interface
parameter DELAY = 1;
// Inputs
wire s_axi_lite_aclk;
wire ACLK;
wire ARESETN;
reg s_axi_lite_awvalid;
reg [8:0] s_axi_lite_awaddr;
reg s_axi_lite_wvalid;
reg [31:0] s_axi_lite_wdata;
reg [3:0] s_axi_lite_wstrb;
reg s_axi_lite_bready;
reg s_axi_lite_arvalid;
reg [8:0] s_axi_lite_araddr;
reg s_axi_lite_rready;
wire M_AXI_AWREADY;
wire M_AXI_WREADY;
wire [0:0] M_AXI_BID;
wire [1:0] M_AXI_BRESP;
wire [0:0] M_AXI_BUSER;
wire M_AXI_BVALID;
wire M_AXI_ARREADY;
wire [0:0] M_AXI_RID;
wire [31:0] M_AXI_RDATA;
wire [1:0] M_AXI_RRESP;
wire M_AXI_RLAST;
wire [0:0] M_AXI_RUSER;
wire M_AXI_RVALID;
// Outputs
wire s_axi_lite_awready;
wire s_axi_lite_wready;
wire [1:0] s_axi_lite_bresp;
wire s_axi_lite_bvalid;
wire s_axi_lite_arready;
wire s_axi_lite_rvalid;
wire [31:0] s_axi_lite_rdata;
wire [1:0] s_axi_lite_rresp;
wire [0:0] M_AXI_AWID;
wire [31:0] M_AXI_AWADDR;
wire [7:0] M_AXI_AWLEN;
wire [2:0] M_AXI_AWSIZE;
wire [1:0] M_AXI_AWBURST;
wire M_AXI_AWLOCK;
wire [3:0] M_AXI_AWCACHE;
wire [2:0] M_AXI_AWPROT;
wire [3:0] M_AXI_AWQOS;
wire [0:0] M_AXI_AWUSER;
wire M_AXI_AWVALID;
wire [31:0] M_AXI_WDATA;
wire [3:0] M_AXI_WSTRB;
wire M_AXI_WLAST;
wire [0:0] M_AXI_WUSER;
wire M_AXI_WVALID;
wire M_AXI_BREADY;
wire [0:0] M_AXI_ARID;
wire [31:0] M_AXI_ARADDR;
wire [7:0] M_AXI_ARLEN;
wire [2:0] M_AXI_ARSIZE;
wire [1:0] M_AXI_ARBURST;
wire [1:0] M_AXI_ARLOCK;
wire [3:0] M_AXI_ARCACHE;
wire [2:0] M_AXI_ARPROT;
wire [3:0] M_AXI_ARQOS;
wire [0:0] M_AXI_ARUSER;
wire M_AXI_ARVALID;
wire M_AXI_RREADY;
wire interrupt;
wire write_fifo_overflow;
// Instantiate the Unit Under Test (UUT)
lap_filter_axim # (
.C_S_AXI_LITE_ADDR_WIDTH(C_S_AXI_LITE_ADDR_WIDTH),
.C_S_AXI_LITE_DATA_WIDTH(C_S_AXI_LITE_DATA_WIDTH)
) uut (
.s_axi_lite_aclk(s_axi_lite_aclk),
.M_AXI_ACLK(ACLK),
.ARESETN(ARESETN),
.s_axi_lite_awvalid(s_axi_lite_awvalid),
.s_axi_lite_awready(s_axi_lite_awready),
.s_axi_lite_awaddr(s_axi_lite_awaddr),
.s_axi_lite_wvalid(s_axi_lite_wvalid),
.s_axi_lite_wready(s_axi_lite_wready),
.s_axi_lite_wdata(s_axi_lite_wdata),
.s_axi_lite_wstrb(s_axi_lite_wstrb),
.s_axi_lite_bresp(s_axi_lite_bresp),
.s_axi_lite_bvalid(s_axi_lite_bvalid),
.s_axi_lite_bready(s_axi_lite_bready),
.s_axi_lite_arvalid(s_axi_lite_arvalid),
.s_axi_lite_arready(s_axi_lite_arready),
.s_axi_lite_araddr(s_axi_lite_araddr),
.s_axi_lite_rvalid(s_axi_lite_rvalid),
.s_axi_lite_rready(s_axi_lite_rready),
.s_axi_lite_rdata(s_axi_lite_rdata),
.s_axi_lite_rresp(s_axi_lite_rresp),
.M_AXI_AWID(M_AXI_AWID),
.M_AXI_AWADDR(M_AXI_AWADDR),
.M_AXI_AWLEN(M_AXI_AWLEN),
.M_AXI_AWSIZE(M_AXI_AWSIZE),
.M_AXI_AWBURST(M_AXI_AWBURST),
.M_AXI_AWLOCK(M_AXI_AWLOCK),
.M_AXI_AWCACHE(M_AXI_AWCACHE),
.M_AXI_AWPROT(M_AXI_AWPROT),
.M_AXI_AWQOS(M_AXI_AWQOS),
.M_AXI_AWUSER(M_AXI_AWUSER),
.M_AXI_AWVALID(M_AXI_AWVALID),
.M_AXI_AWREADY(M_AXI_AWREADY),
.M_AXI_WDATA(M_AXI_WDATA),
.M_AXI_WSTRB(M_AXI_WSTRB),
.M_AXI_WLAST(M_AXI_WLAST),
.M_AXI_WUSER(M_AXI_WUSER),
.M_AXI_WVALID(M_AXI_WVALID),
.M_AXI_WREADY(M_AXI_WREADY),
.M_AXI_BID(M_AXI_BID),
.M_AXI_BRESP(M_AXI_BRESP),
.M_AXI_BUSER(M_AXI_BUSER),
.M_AXI_BVALID(M_AXI_BVALID),
.M_AXI_BREADY(M_AXI_BREADY),
.M_AXI_ARID(M_AXI_ARID),
.M_AXI_ARADDR(M_AXI_ARADDR),
.M_AXI_ARLEN(M_AXI_ARLEN),
.M_AXI_ARSIZE(M_AXI_ARSIZE),
.M_AXI_ARBURST(M_AXI_ARBURST),
.M_AXI_ARLOCK(M_AXI_ARLOCK),
.M_AXI_ARCACHE(M_AXI_ARCACHE),
.M_AXI_ARPROT(M_AXI_ARPROT),
.M_AXI_ARQOS(M_AXI_ARQOS),
.M_AXI_ARUSER(M_AXI_ARUSER),
.M_AXI_ARVALID(M_AXI_ARVALID),
.M_AXI_ARREADY(M_AXI_ARREADY),
.M_AXI_RID(M_AXI_RID),
.M_AXI_RDATA(M_AXI_RDATA),
.M_AXI_RRESP(M_AXI_RRESP),
.M_AXI_RLAST(M_AXI_RLAST),
.M_AXI_RUSER(M_AXI_RUSER),
.M_AXI_RVALID(M_AXI_RVALID),
.M_AXI_RREADY(M_AXI_RREADY),
.interrupt(interrupt),
.write_fifo_overflow(write_fifo_overflow)
);
initial begin : initial_state
integer i;
// Initialize Inputs
s_axi_lite_awaddr = 0;
s_axi_lite_awvalid = 0;
s_axi_lite_wvalid = 0;
s_axi_lite_wdata = 0;
s_axi_lite_wvalid = 0;
s_axi_lite_bready = 0;
s_axi_lite_araddr = 0;
s_axi_lite_arvalid = 0;
s_axi_lite_rready = 0;
s_axi_lite_wstrb = 0;
// Wait Reset rising edge
@(posedge ARESETN);
for (i=0; i<10; i=i+1) begin
@(posedge ACLK); // 次のクロックへ
#DELAY;
end
s_axi_lite_wstrb = 4'b1111;
// Add stimulus here
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_WADC1(32'h0000_0014, 32'h1000_0000); // cam_addr write
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_WADC1(32'h0000_0010, 32'h0000_0001); // cam_addr_ap_vld = 1
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_WADC1(32'h0000_001C, 32'h2000_0000); // lap_addr write
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_WADC1(32'h0000_0018, 32'h0000_0001); // lap_addr_ap_vld = 1
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_WADC1(32'h0000_0008, 32'h0000_0001); // IP Interrupt Enable Registe(ap_done=1)
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_WADC1(32'h0000_0000, 32'h0000_0001); // ap_start = 1
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_RADC1(32'h0000_0000);
forever begin
@(posedge ACLK); // 次のクロックへ
#DELAY;
AXI_MASTER_RADC1(32'h0000_0000);
end
end
// Write Transcation 1
task AXI_MASTER_WADC1;
input [C_S_AXI_LITE_ADDR_WIDTH-1:0] awaddr;
input [C_S_AXI_LITE_DATA_WIDTH-1:0] wdata;
begin
s_axi_lite_awaddr = awaddr;
s_axi_lite_awvalid = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_awvalid <= 1'b0;
s_axi_lite_wdata = wdata;
s_axi_lite_wvalid = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_wvalid = 1'b0;
s_axi_lite_bready = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_bready = 1'b0;
end
endtask
// Read Transcation 1
task AXI_MASTER_RADC1;
input [31:0] araddr;
begin
s_axi_lite_araddr = araddr;
s_axi_lite_arvalid = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_araddr = 0;
s_axi_lite_arvalid = 1'b0;
s_axi_lite_rready = 1'b1;
@(posedge ACLK); // 次のクロックへ
#DELAY;
s_axi_lite_rready = 1'b0;
end
endtask
// clk_gen のインスタンス(ACLK)
clk_gen #(
.CLK_PERIOD(100), // 10nsec, 100MHz
.CLK_DUTY_CYCLE(0.5),
.CLK_OFFSET(0),
.START_STATE(1'b0)
) ACLKi (
.clk_out(ACLK)
);
assign s_axi_lite_aclk = ACLK;
// reset_gen のインスタンス
reset_gen #(
.RESET_STATE(1'b0),
.RESET_TIME(1000) // 100nsec
) RESETi (
.reset_out(ARESETN),
.init_done()
);
// Instantiate the Unit Under Test (UUT_slave)
axi_slave_bfm # (
.C_M_AXI_DATA_WIDTH(32),
.WRITE_RANDOM_WAIT(1), // Write Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
.READ_RANDOM_WAIT(0), // Read Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
.READ_DATA_IS_INCREMENT(1), // ReadトランザクションでRAMの内容をReadする = 0(RAMにWriteしたものをReadする)、Readデータを+1する = 1(データは+1したデータをReadデータとして使用する
.RUNDAM_BVALID_WAIT(0)
) uut_slave (
.ACLK(ACLK),
.ARESETN(ARESETN),
.M_AXI_AWID(M_AXI_AWID),
.M_AXI_AWADDR(M_AXI_AWADDR),
.M_AXI_AWLEN(M_AXI_AWLEN),
.M_AXI_AWSIZE(M_AXI_AWSIZE),
.M_AXI_AWBURST(M_AXI_AWBURST),
.M_AXI_AWLOCK({1'b0, M_AXI_AWLOCK}),
.M_AXI_AWCACHE(M_AXI_AWCACHE),
.M_AXI_AWPROT(M_AXI_AWPROT),
.M_AXI_AWQOS(M_AXI_AWQOS),
.M_AXI_AWUSER(M_AXI_AWUSER),
.M_AXI_AWVALID(M_AXI_AWVALID),
.M_AXI_AWREADY(M_AXI_AWREADY),
.M_AXI_WDATA(M_AXI_WDATA),
.M_AXI_WSTRB(M_AXI_WSTRB),
.M_AXI_WLAST(M_AXI_WLAST),
.M_AXI_WUSER(M_AXI_WUSER),
.M_AXI_WVALID(M_AXI_WVALID),
.M_AXI_WREADY(M_AXI_WREADY),
.M_AXI_BID(M_AXI_BID),
.M_AXI_BRESP(M_AXI_BRESP),
.M_AXI_BUSER(M_AXI_BUSER),
.M_AXI_BVALID(M_AXI_BVALID),
.M_AXI_BREADY(M_AXI_BREADY),
.M_AXI_ARID(M_AXI_ARID),
.M_AXI_ARADDR(M_AXI_ARADDR),
.M_AXI_ARLEN(M_AXI_ARLEN),
.M_AXI_ARSIZE(M_AXI_ARSIZE),
.M_AXI_ARBURST(M_AXI_ARBURST),
.M_AXI_ARLOCK(M_AXI_ARLOCK),
.M_AXI_ARCACHE(M_AXI_ARCACHE),
.M_AXI_ARPROT(M_AXI_ARPROT),
.M_AXI_ARQOS(M_AXI_ARQOS),
.M_AXI_ARUSER(M_AXI_ARUSER),
.M_AXI_ARVALID(M_AXI_ARVALID),
.M_AXI_ARREADY(M_AXI_ARREADY),
.M_AXI_RID(M_AXI_RID),
.M_AXI_RDATA(M_AXI_RDATA),
.M_AXI_RRESP(M_AXI_RRESP),
.M_AXI_RLAST(M_AXI_RLAST),
.M_AXI_RUSER(M_AXI_RUSER),
.M_AXI_RVALID(M_AXI_RVALID),
.M_AXI_RREADY(M_AXI_RREADY)
);
endmodule
module clk_gen #(
parameter CLK_PERIOD = 100,
parameter real CLK_DUTY_CYCLE = 0.5,
parameter CLK_OFFSET = 0,
parameter START_STATE = 1'b0 )
(
output reg clk_out
);
begin
initial begin
#CLK_OFFSET;
forever
begin
clk_out = START_STATE;
#(CLK_PERIOD-(CLK_PERIOD*CLK_DUTY_CYCLE)) clk_out = ~START_STATE;
#(CLK_PERIOD*CLK_DUTY_CYCLE);
end
end
end
endmodule
module reset_gen #(
parameter RESET_STATE = 1'b1,
parameter RESET_TIME = 100 )
(
output reg reset_out,
output reg init_done
);
begin
initial begin
reset_out = RESET_STATE;
init_done = 1'b0;
#RESET_TIME;
reset_out = ~RESET_STATE;
init_done = 1'b1;
end
end
endmodule
`default_nettype wire
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | - | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | - | - | - | - | - | - |