・XPSでChipScope Proコアを追加してデバック1
・XPSでChipScope Proコアを追加してデバック2
make -k all
libgen -hw ../system_hw_platform/system.xml\
\
-pe ps7_cortexa9_0 \
-log libgen.log \
system.mss
libgen
Xilinx EDK 14.4 Build EDK_P.49d
Copyright (c) 1995-2012 Xilinx, Inc. All rights reserved.
Command Line: libgen -hw ../system_hw_platform/system.xml -pe ps7_cortexa9_0
-log libgen.log system.mss
Staging source files.
Running DRCs.
Running generate.
Running post_generate.
Running include - 'make -s include "COMPILER=arm-xilinx-eabi-gcc"
"ARCHIVER=arm-xilinx-eabi-ar" "COMPILER_FLAGS= -O2 -c"
"EXTRA_COMPILER_FLAGS=-g"'.
Running libs - 'make -s libs "COMPILER=arm-xilinx-eabi-gcc"
"ARCHIVER=arm-xilinx-eabi-ar" "COMPILER_FLAGS= -O2 -c"
"EXTRA_COMPILER_FLAGS=-g"'.
"Compiling common"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling xadc"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling standalone"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -march=armv7-a -mfloat-abi=soft -mfpu=neon -I./. -I../../../include _exit.c _open.c _sbrk.c abort.c close.c errno.c fcntl.c fstat.c getpid.c inbyte.c isatty.c kill.c lseek.c open.c outbyte.c print.c putnum.c read.c sbrk.c sleep.c smc.c uart.c unlink.c usleep.c vectors.c write.c xil_assert.c xil_cache.c xil_exception.c xil_io.c xil_mmu.c xil_printf.c xil_testcache.c xil_testio.c xil_testmem.c xl2cc_counter.c xpm_counter.c xtime_l.c asm_vectors.S boot.S cpu_init.S translation_table.s xil-crt0.S, ...) failed.
"Compiling gpio"
"Compiling iic"
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [standalone_libs] エラー 2
make[1]: ターゲット `libs' はエラーにより再 make できませんでした.
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling tmrctr"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling devcfg"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling dmaps"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling emacps"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling gpiops"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling qspips"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling scugic"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling scutimer"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling scuwdt"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling ttcps"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling uartps"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling usbps"
process_begin: CreateProcess(NULL, arm-xilinx-eabi-gcc -O2 -c -g -I./. -I../../../include *.c, ...) failed.
make (e=2): 指定されたファイルが見つかりません。
make[1]: *** [libs] エラー 2
"Compiling cpu_cortexa9"
ERROR:EDK:369 - make failed for target "libs"
ERROR:EDK:3418 - Error(s) while running make.
make: *** [ps7_cortexa9_0/lib/libxil.a] エラー 2
make: ターゲット `all' はエラーにより再 make できませんでした.
1.Last In First Out (つまりスタックですね!)を付ける。(結構面倒そう)
2.AXIバスの動作周波数を200MHz(アナデバのHDMIサンプルのAXIバスの動作周波数は 200MHz です)にして、シングル転送限定とする。
if wrt_wv_cs=idle_wvalid then という行があるが、wrt_wv_cs は、Writeデータを扱うステートマシンなので、awlen のタイミングが遅延してしまう。これを awvalid と同期して変化するように Verilog HDL ソースを変更する。(ZedBoard用CMOSカメラ回路の作製2(HDLソースの公開1)を後ほど修正します)-- write_count の処理 (pfifo_rd_data_count は当てにならない。使わないほうが良い)
pfifo_rd_dcount_dec <= unsigned(pfifo_rd_data_count) - 1;
process(ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
write_count <= (others => '0');
awlen <= (others => '0');
else
if wrt_wv_cs=idle_wvalid then
if pfifo_rd_data_count/=std_logic_vector(to_unsigned(0, 9)) then
write_count <= std_logic_vector(pfifo_rd_dcount_dec(7 downto 0));
awlen <= std_logic_vector(pfifo_rd_dcount_dec(7 downto 0));
end if;
elsif wrt_wv_cs=wvalid_assert and M_AXI_WREADY='1' and unsigned(write_count)/=0 then
write_count <= std_logic_vector(unsigned(write_count) - 1);
end if;
end if;
end if;
end process;
// SVGA 解像度 pixel clock = 40MHz
parameter H_ACTIVE_VIDEO= 800;
parameter H_FRONT_PORCH = 40;
parameter H_SYNC_PULSE = 128;
parameter H_BACK_PORCH = 88;
parameter H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;
parameter V_ACTIVE_VIDEO = 600;
parameter V_FRONT_PORCH = 1;
parameter V_SYNC_PULSE = 4;
parameter V_BACK_PORCH = 23;
parameter V_SUM = V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;
IO_INTERFACE IO_IF = mt9d111_inf
#Example IO port
PORT init_done = "", DIR = I, IO_IF = mt9d111_inf, IO_IS = init_done
PORT wr_error = "", DIR = O, IO_IF = mt9d111_inf, IO_IS = wr_error
PORT pclk_from_pll = "", DIR = I, SIGIS = CLK, IO_IF = mt9d111_inf, IO_IS = pclk_from_pll
PORT pclk = "", DIR = I, SIGIS = CLK, IO_IF = mt9d111_inf, IO_IS = pclk
PORT xck = "", DIR =O, SIGIS = CLK, IO_IF = mt9d111_inf, IO_IS = xck
PORT href = "", DIR = I, IO_IF = mt9d111_inf, IO_IS = href
PORT vsync = "", DIR = I, IO_IF = mt9d111_inf, IO_IS = vsync
PORT cam_data = "", DIR = I, VEC = [7:0], IO_IF = mt9d111_inf, IO_IS = cam_data
PORT standby = "", DIR = O, IO_IF = mt9d111_inf, IO_IS = standby
PORT pfifo_overflow, DIR = O, IO_IF = mt9d111_inf, IO_IS = pfifo_overflow
PORT pfifo_underflow, DIR = O, IO_IF = mt9d111_inf, IO_IS = pfifo_underflow
PARAMETER C_DISPLAY_START_ADDRESS = 0x10000000, DT = std_logic_vector(31 downto 0)
# Number of address bits to test before wrapping
PARAMETER C_OFFSET_WIDTH = 9, DT = integer
PARAMETER C_DISPLAY_START_ADDRESS = 0x10000000, DT = std_logic_vector(31 downto 0)
## Ports
PORT ACLK = "", BUS = M_AXI, DIR = I, SIGIS = CLK
PORT ARESETN = ARESETN, BUS = M_AXI, DIR = I, SIGIS = RST
<!ENTITY C_OFFSET_WIDTH '
<widget id="C_OFFSET_WIDTH">
<key>C_OFFSET_WIDTH</key>
<label>C_OFFSET_WIDTH</label>
<tip></tip>
</widget>
'>
<!ENTITY C_DISPLAY_START_ADDRESS '
<widget id="C_DISPLAY_START_ADDRESS">
<key>C_DISPLAY_START_ADDRESS</key>
<label>C_DISPLAY_START_ADDRESS</label>
<tip></tip>
</widget>
'>
]>
`default_nettype none
`timescale 100ps / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 09:51:18 12/31/2012
// Design Name: mt9d111_inf_axi_master
// Module Name: K:/HDL/FndtnISEWork/Zynq-7000/ZedBoard/ZedBoard_CamDisp_wHDMI_144/mt9d111_inf_axi_master/mt9d111_inf_axi_master_tb.v
// Project Name: mt9d111_inf_axi_master
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: mt9d111_inf_axi_master
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
module mt9d111_inf_axi_master_tb;
// Inputs
wire ACLK;
wire ARESETN;
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 [63:0] M_AXI_RDATA;
wire [1:0] M_AXI_RRESP;
wire M_AXI_RLAST;
wire [0:0] M_AXI_RUSER;
wire M_AXI_RVALID;
wire init_done;
wire pclk_from_pll;
wire pclk;
wire href;
wire vsync;
wire [7:0] cam_data;
// Outputs
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 [63:0] M_AXI_WDATA;
wire [7: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 wr_error;
wire xck;
wire standby;
wire pfifo_overflow;
wire pfifo_underflow;
// Instantiate the Unit Under Test (UUT)
mt9d111_inf_axi_master uut (
.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),
.init_done(init_done),
.wr_error(wr_error),
.pclk_from_pll(pclk_from_pll),
.pclk(pclk),
.xck(xck),
.href(href),
.vsync(vsync),
.cam_data(cam_data),
.standby(standby),
.pfifo_overflow(pfifo_overflow),
.pfifo_underflow(pfifo_underflow)
);
assign init_done = 1'b1;
// ACLK のインスタンス
clk_gen #(
.CLK_PERIOD(100), // 10nsec, 100MHz
.CLK_DUTY_CYCLE(0.5),
.CLK_OFFSET(0),
.START_STATE(1'b0)
) ACLKi (
.clk_out(ACLK)
);
// pclk_from_pll のインスタンス
clk_gen #(
.CLK_PERIOD(278), // 27.8nsec, 約36MHz
.CLK_DUTY_CYCLE(0.5),
.CLK_OFFSET(0),
.START_STATE(1'b0)
) pclk_from_pll_i (
.clk_out(pclk_from_pll)
);
// reset_gen のインスタンス
reset_gen #(
.RESET_STATE(1'b0),
.RESET_TIME(1000) // 100nsec
) RESETi (
.reset_out(ARESETN)
);
// MT9D111 モデル
mt9d111_model #(
.HORIZONTAL_PIXELS(800),
.VERTICAL_LINES(600),
.HBLANK_REG(174),
.VBLANK_REG(16),
.PCLK_DELAY(1)
) mt9d111_model_i (
.xck(xck),
.pclk(pclk),
.href(href),
.vsync(vsync),
.d(cam_data),
.scl(1'b1),
.sda(),
.standby(standby)
);
// Instantiate the Unit Under Test (UUT_slave)
axi_slave_bfm #(
.C_M_AXI_DATA_WIDTH(64)
) 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(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
);
begin
initial begin
reset_out = RESET_STATE;
#RESET_TIME;
reset_out = ~RESET_STATE;
end
end
endmodule
`default_nettype wire
// mt9d111_model.v
// mt9d111 の動作モデル
// RGB565 を出力
`default_nettype none
`timescale 1ns / 1ps
module mt9d111_model # (
parameter integer HORIZONTAL_PIXELS = 800,
parameter integer VERTICAL_LINES = 600,
parameter integer HBLANK_REG = 174, // pixels
parameter integer VBLANK_REG = 16, // rows
parameter integer PCLK_DELAY = 1
)(
input wire xck,
output reg pclk = 1'b1,
output reg href = 1'b0,
output reg vsync = 1'b1,
output reg [7:0] d = 8'd0,
input wire scl,
inout wire sda,
input wire standby
);
parameter [2:0] FRAME_START_BLANKING = 3'b000,
ACTIVE_DATA_TIME = 3'b001,
HORIZONTAL_BLANKING = 3'b011,
FRAME_END_BLANKING = 3'b010,
VERTICAL_BLANKING = 3'b110;
reg [2:0] mt9d111_cs = FRAME_START_BLANKING;
reg [2:0] fseb_count = 3'd5;
reg [15:0] adt_count = (HORIZONTAL_PIXELS * 2) - 1;
reg [15:0] hb_count = HBLANK_REG - 1;
reg [15:0] fvt_count = VERTICAL_LINES - 1;
reg [31:0] vb_count = VBLANK_REG * (HORIZONTAL_PIXELS + HBLANK_REG) - 1;
reg href_node = 1'b0;
reg vsync_node = 1'b1;
reg dout_is_even = 1'b0;
// R, G, B 毎に違った生成多項式のM系列を用意した
function [7:0] mseqf8_R (input [7:0] din);
reg xor_result;
begin
xor_result = din[7] ^ din[3] ^ din[2] ^ din[1];
mseqf8_R = {din[6:0], xor_result};
end
endfunction
function [7:0] mseqf8_G (input [7:0] din);
reg xor_result;
begin
xor_result = din[7] ^ din[4] ^ din[2] ^ din[0];
mseqf8_G = {din[6:0], xor_result};
end
endfunction
function [7:0] mseqf8_B (input [7:0] din);
reg xor_result;
begin
xor_result = din[7] ^ din[5] ^ din[2] ^ din[1];
mseqf8_B = {din[6:0], xor_result};
end
endfunction
reg [7:0] mseq8r = 8'd1;
reg [7:0] mseq8g = 8'd1;
reg [7:0] mseq8b = 8'd1;
// pclk の出力
always @*
pclk <= #PCLK_DELAY xck;
// MT9D111 のステート
always @(posedge pclk) begin
case (mt9d111_cs)
FRAME_START_BLANKING : begin
if (fseb_count==0) begin
mt9d111_cs <= ACTIVE_DATA_TIME;
href_node <= 1'b1;
end
end
ACTIVE_DATA_TIME : begin
if (adt_count==0) begin
if (fvt_count==0) // frame end
mt9d111_cs <= FRAME_END_BLANKING;
else
mt9d111_cs <= HORIZONTAL_BLANKING;
href_node <= 1'b0;
end
end
HORIZONTAL_BLANKING : begin
if (hb_count==0) begin
mt9d111_cs <= ACTIVE_DATA_TIME;
href_node <= 1'b1;
end
end
FRAME_END_BLANKING : begin
if (fseb_count==0) begin
mt9d111_cs <= VERTICAL_BLANKING;
vsync_node <= 1'b0;
end
end
VERTICAL_BLANKING : begin
if (vb_count==0) begin
mt9d111_cs <= FRAME_START_BLANKING;
vsync_node <= 1'b1;
end
end
endcase
end
// vsync, href 出力、レーシングを防ぐためにpclk よりも出力を遅らせる
always @* begin
vsync <= #1 vsync_node;
href <= #1 href_node;
end
// Frame Start/End Blanking Counter (6 pixel clocks)
always @(posedge pclk) begin
if (mt9d111_cs==FRAME_START_BLANKING || mt9d111_cs==FRAME_END_BLANKING) begin
if (fseb_count > 0)
fseb_count <= fseb_count - 3'd1;
end else
fseb_count <= 3'd5;
end
// Active Data Time Counter
always @(posedge pclk) begin
if (mt9d111_cs==ACTIVE_DATA_TIME) begin
if (adt_count > 0)
adt_count <= adt_count - 16'd1;
end else
adt_count <= (HORIZONTAL_PIXELS * 2) - 1;
end
// Horizontal Blanking Counter
always @(posedge pclk) begin
if (mt9d111_cs==HORIZONTAL_BLANKING) begin
if (hb_count > 0)
hb_count <= hb_count - 16'd1;
end else
hb_count <= HBLANK_REG - 1;
end
// Frame Valid Time Counter
always @(posedge pclk) begin
if (mt9d111_cs==ACTIVE_DATA_TIME && adt_count==0) begin
if (fvt_count > 0)
fvt_count <= fvt_count - 16'd1;
end if (mt9d111_cs == VERTICAL_BLANKING)
fvt_count <= VERTICAL_LINES - 1;
end
// Vertical Blanking Counter
always @(posedge pclk) begin
if (mt9d111_cs==VERTICAL_BLANKING) begin
if (vb_count > 0)
vb_count <= vb_count - 32'd1;
end else
vb_count <= VBLANK_REG * (HORIZONTAL_PIXELS + HBLANK_REG) - 1;
end
// Red のM系列符号生成
always @(posedge pclk) begin
// if (mt9d111_cs==ACTIVE_DATA_TIME)
mseq8r <= mseqf8_R(mseq8r);
end
// Green のM系列符号生成
always @(posedge pclk) begin
// if (mt9d111_cs==ACTIVE_DATA_TIME)
mseq8g <= mseqf8_G(mseq8g);
end
// Blue のM系列符号生成
always @(posedge pclk) begin
// if (mt9d111_cs==ACTIVE_DATA_TIME)
mseq8b <= mseqf8_B(mseq8b);
end
// d 出力のODD とEVEN を示す
always @(posedge pclk) begin
if (mt9d111_cs==ACTIVE_DATA_TIME)
dout_is_even <= ~dout_is_even;
else
dout_is_even <= 1'b0;
end
// d 出力、レーシングを防ぐためにpclk よりも出力を遅らせる
always @(posedge pclk) begin
if (mt9d111_cs==ACTIVE_DATA_TIME) begin
if (dout_is_even)
d <= #1 {mseq8g[4:2], mseq8b[7:3]};
else
d <= #1 {mseq8r[7:3], mseq8g[7:5]};
end
end
endmodule
`default_nettype wire
-----------------------------------------------------------------------------
--
-- AXI Master用 AXI Slave Bus Function Mode (BFM)
--
-----------------------------------------------------------------------------
-- 2012/02/25 : M_AXI_AWBURST=1 (INCR) にのみ対応、AWSIZE, ARSIZE = 000 (1byte), 001 (2bytes), 010 (4bytes) のみ対応。
-- 2012/01/15 : BVALID が1になる間隔をランダム変更できるようにした。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
package m_seq_bfm_pack is
function M_SEQ16_BFM_F(mseq16in : std_logic_vector
)return std_logic_vector;
end package m_seq_bfm_pack;
package body m_seq_bfm_pack is
function M_SEQ16_BFM_F(mseq16in : std_logic_vector
)return std_logic_vector is
variable mseq16 : std_logic_vector(15 downto 0);
variable xor_result : std_logic;
begin
xor_result := mseq16in(15) xor mseq16in(12) xor mseq16in(10) xor mseq16in(8) xor mseq16in(7) xor mseq16in(6) xor mseq16in(3) xor mseq16in(2);
mseq16 := mseq16in(14 downto 0) & xor_result;
return mseq16;
end M_SEQ16_BFM_F;
end m_seq_bfm_pack;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use IEEE.math_real.all;
library work;
use work.m_seq_bfm_pack.all;
--library unisim;
--use unisim.vcomponents.all;
entity axi_slave_bfm is
generic (
C_M_AXI_ID_WIDTH : integer := 1;
C_M_AXI_ADDR_WIDTH : integer := 32;
C_M_AXI_DATA_WIDTH : integer := 32;
C_M_AXI_AWUSER_WIDTH : integer := 1;
C_M_AXI_ARUSER_WIDTH : integer := 1;
C_M_AXI_WUSER_WIDTH : integer := 1;
C_M_AXI_RUSER_WIDTH : integer := 1;
C_M_AXI_BUSER_WIDTH : integer := 1;
C_M_AXI_TARGET : integer := 0;
C_OFFSET_WIDTH : integer := 10; -- 割り当てるRAMのアドレスのビット幅
C_M_AXI_BURST_LEN : integer := 256;
WRITE_RANDOM_WAIT : integer := 1; -- Write Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
WR_BVALID_RANDOM_WAIT : integer := 1; -- Write Transaction の時のM_AXI_BVALID をランダムにWaitする=1, Waitしない=0
READ_RANDOM_WAIT : integer := 0 -- Read Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
);
port(
-- System Signals
ACLK : in std_logic;
ARESETN : in std_logic;
-- Master Interface Write Address Ports
M_AXI_AWID : in std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
M_AXI_AWADDR : in std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0);
M_AXI_AWLEN : in std_logic_vector(8-1 downto 0);
M_AXI_AWSIZE : in std_logic_vector(3-1 downto 0);
M_AXI_AWBURST : in std_logic_vector(2-1 downto 0);
-- M_AXI_AWLOCK : in std_logic_vector(2-1 downto 0);
M_AXI_AWLOCK : in std_logic;
M_AXI_AWCACHE : in std_logic_vector(4-1 downto 0);
M_AXI_AWPROT : in std_logic_vector(3-1 downto 0);
M_AXI_AWQOS : in std_logic_vector(4-1 downto 0);
M_AXI_AWUSER : in std_logic_vector(C_M_AXI_AWUSER_WIDTH-1 downto 0);
M_AXI_AWVALID : in std_logic;
M_AXI_AWREADY : out std_logic;
-- Master Interface Write Data Ports
M_AXI_WDATA : in std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
M_AXI_WSTRB : in std_logic_vector(C_M_AXI_DATA_WIDTH/8-1 downto 0);
M_AXI_WLAST : in std_logic;
M_AXI_WUSER : in std_logic_vector(C_M_AXI_WUSER_WIDTH-1 downto 0);
M_AXI_WVALID : in std_logic;
M_AXI_WREADY : out std_logic;
-- Master Interface Write Response Ports
M_AXI_BID : out std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
M_AXI_BRESP : out std_logic_vector(2-1 downto 0);
M_AXI_BUSER : out std_logic_vector(C_M_AXI_BUSER_WIDTH-1 downto 0);
M_AXI_BVALID : out std_logic;
M_AXI_BREADY : in std_logic;
-- Master Interface Read Address Ports
M_AXI_ARID : in std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
M_AXI_ARADDR : in std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0);
M_AXI_ARLEN : in std_logic_vector(8-1 downto 0);
M_AXI_ARSIZE : in std_logic_vector(3-1 downto 0);
M_AXI_ARBURST : in std_logic_vector(2-1 downto 0);
M_AXI_ARLOCK : in std_logic_vector(2-1 downto 0);
M_AXI_ARCACHE : in std_logic_vector(4-1 downto 0);
M_AXI_ARPROT : in std_logic_vector(3-1 downto 0);
M_AXI_ARQOS : in std_logic_vector(4-1 downto 0);
M_AXI_ARUSER : in std_logic_vector(C_M_AXI_ARUSER_WIDTH-1 downto 0);
M_AXI_ARVALID : in std_logic;
M_AXI_ARREADY : out std_logic;
-- Master Interface Read Data Ports
M_AXI_RID : out std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
M_AXI_RDATA : out std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
M_AXI_RRESP : out std_logic_vector(2-1 downto 0);
M_AXI_RLAST : out std_logic;
M_AXI_RUSER : out std_logic_vector(C_M_AXI_RUSER_WIDTH-1 downto 0);
M_AXI_RVALID : out std_logic;
M_AXI_RREADY : in std_logic
);
end axi_slave_bfm;
architecture implementation of axi_slave_bfm is
constant AxBURST_FIXED : std_logic_vector := "00";
constant AxBURST_INCR : std_logic_vector := "01";
constant AxBURST_WRAP : std_logic_vector := "10";
constant RESP_OKAY : std_logic_vector := "00";
constant RESP_EXOKAY : std_logic_vector := "01";
constant RESP_SLVERR : std_logic_vector := "10";
constant RESP_DECERR : std_logic_vector := "11";
constant DATA_BUS_BYTES : natural := C_M_AXI_DATA_WIDTH/8; -- データバスのビット幅
constant ADD_INC_OFFSET : natural := natural(log(real(DATA_BUS_BYTES), 2.0));
-- RAMの生成
constant SLAVE_ADDR_NUMBER : integer := 2**(C_OFFSET_WIDTH - ADD_INC_OFFSET);
type ram_array_def is array (SLAVE_ADDR_NUMBER-1 downto 0) of std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
signal ram_array : ram_array_def := (others => (others => '0'));
-- for write transaction
type write_transaction_state is (idle_wr, awr_wait, awr_accept, wr_burst, wr_bvalid_assert);
type write_response_state is (idle_wres, bvalid_assert);
type write_wready_state is (idle_wrdy, wready_assert);
signal wrt_cs : write_transaction_state;
signal wrres : write_response_state;
signal wrwr : write_wready_state;
signal addr_inc_step_wr : integer := 1;
signal awready : std_logic;
signal wr_addr : std_logic_vector(C_OFFSET_WIDTH-1 downto 0);
signal wr_bid : std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
signal wr_bresp : std_logic_vector(1 downto 0);
signal wr_bvalid : std_logic;
signal m_seq16_wr : std_logic_vector(15 downto 0);
signal wready : std_logic;
type wready_state is (idle_wready, assert_wready, deassert_wready);
signal cs_wready : wready_state;
signal cdc_we : std_logic;
-- for read transaction
type read_transaction_state is (idle_rd, arr_wait, arr_accept, rd_burst);
type read_last_state is (idle_rlast, rlast_assert);
signal rdt_cs : read_transaction_state;
signal rdlast : read_last_state;
signal addr_inc_step_rd : integer := 1;
signal arready : std_logic;
signal rd_addr : std_logic_vector(C_OFFSET_WIDTH-1 downto 0);
signal rd_axi_count : std_logic_vector(7 downto 0);
signal rvalid : std_logic;
signal rlast : std_logic;
signal m_seq16_rd : std_logic_vector(15 downto 0);
type rvalid_state is (idle_rvalid, assert_rvalid, deassert_rvalid);
signal cs_rvalid : rvalid_state;
signal reset_1d, reset_2d, reset : std_logic := '1';
signal bvalid_cnt : std_logic_vector(3 downto 0);
begin
-- ARESETN をACLK で同期化
process (ACLK) begin
if ACLK'event and ACLK='1' then
reset_1d <= not ARESETN;
reset_2d <= reset_1d;
end if;
end process;
reset <= reset_2d;
-- AXI4バス Write Transaction State Machine
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
wrt_cs <= idle_wr;
awready <= '0';
else
case (wrt_cs) is
when idle_wr =>
if M_AXI_AWVALID='1' then -- M_AXI_AWVALID が1にアサートされた
if rdt_cs=idle_rd then -- Read Transaction が終了している(Writeの方が優先順位が高い)
wrt_cs <= awr_accept;
awready <= '1';
else -- Read Transaction が終了していないのでWait
wrt_cs <= awr_wait;
end if;
end if;
when awr_wait => -- Read Transaction の終了待ち
if rdt_cs=idle_rd or rdt_cs=arr_wait then -- Read Transaction が終了
wrt_cs <= awr_accept;
awready <= '1';
end if;
when awr_accept => -- M_AXI_AWREADY をアサート
wrt_cs <= wr_burst;
awready <= '0';
when wr_burst => -- Writeデータの転送
if M_AXI_WLAST='1' and M_AXI_WVALID='1' and wready='1' then -- Write Transaction 終了
wrt_cs <= wr_bvalid_assert;
end if;
when wr_bvalid_assert => -- M_AXI_BVALID アサート
if wr_bvalid='1' and M_AXI_BREADY='1' then -- wr_bvalid が1でMaster側のReadyも1ならばWrite resonse channel の転送も終了
wrt_cs <= idle_wr;
end if;
end case;
end if;
end if;
end process;
M_AXI_AWREADY <= awready;
-- m_seq_wr、16ビットのM系列を計算する
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
m_seq16_wr <= (0 => '1', others => '0');
else
if WRITE_RANDOM_WAIT=1 then -- Write Transaction 時にランダムなWaitを挿入する
if wrt_cs=wr_burst and M_AXI_WVALID='1' then
m_seq16_wr <= M_SEQ16_BFM_F(m_seq16_wr);
end if;
else -- Wait無し
m_seq16_wr <= (others => '0');
end if;
end if;
end if;
end process;
-- wready の処理、M系列を計算して128以上だったらWaitする。
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
cs_wready <= idle_wready;
wready <= '0';
else
case (cs_wready) is
when idle_wready =>
if wrt_cs=awr_accept then -- 次はwr_burst
if m_seq16_wr(7)='0' then -- wready='1'
cs_wready <= assert_wready;
wready <= '1';
else -- m_seq16_wr(7)='1' then -- wready='0'
cs_wready <= deassert_wready;
wready <= '0';
end if;
end if;
when assert_wready => -- 一度wreadyがアサートされたら、1つのトランザクションが終了するまでwready='1'
if wrt_cs=wr_burst and M_AXI_WLAST='1' and M_AXI_WVALID='1' then -- 終了
cs_wready <= idle_wready;
wready <= '0';
elsif wrt_cs=wr_burst and M_AXI_WVALID='1' then -- 1つのトランザクション終了。
if m_seq16_wr(7)='1' then
cs_wready <= deassert_wready;
wready <= '0';
end if;
end if;
when deassert_wready =>
if m_seq16_wr(7)='0' then -- wready='1'
cs_wready <= assert_wready;
wready <= '1';
end if;
end case;
end if;
end if;
end process;
M_AXI_WREADY <= wready;
cdc_we <= '1' when wrt_cs=wr_burst and wready='1' and M_AXI_WVALID='1' else '0';
-- addr_inc_step_wr の処理
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
addr_inc_step_wr <= 1;
else
if wrt_cs=awr_accept then
case (M_AXI_AWSIZE) is
when "000" => -- 8ビット転送
addr_inc_step_wr <= 1;
when "001" => -- 16ビット転送
addr_inc_step_wr <= 2;
when "010" => -- 32ビット転送
addr_inc_step_wr <= 4;
when "011" => -- 64ビット転送
addr_inc_step_wr <= 8;
when "100" => -- 128ビット転送
addr_inc_step_wr <= 16;
when "101" => -- 256ビット転送
addr_inc_step_wr <= 32;
when "110" => -- 512ビット転送
addr_inc_step_wr <= 64;
when others => --"111" => -- 1024ビット転送
addr_inc_step_wr <= 128;
end case;
end if;
end if;
end if;
end process;
-- wr_addr の処理
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
wr_addr <= (others => '0');
else
if wrt_cs=awr_accept then
wr_addr <= M_AXI_AWADDR(C_OFFSET_WIDTH-1 downto 0);
elsif wrt_cs=wr_burst and M_AXI_WVALID='1' and wready='1' then -- アドレスを進める
wr_addr <= wr_addr + addr_inc_step_wr;
end if;
end if;
end if;
end process;
-- wr_bid の処理
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
wr_bid <= "0";
else
if wrt_cs=awr_accept then
wr_bid <= M_AXI_AWID;
end if;
end if;
end if;
end process;
M_AXI_BID <= wr_bid;
-- wr_bresp の処理
-- M_AXI_AWBURSTがINCRの時はOKAYを返す。それ以外はSLVERRを返す。
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
wr_bresp <= (others => '0');
else
if wrt_cs=awr_accept then
if M_AXI_AWBURST=AxBURST_INCR then -- バーストタイプがアドレス・インクリメントタイプ
wr_bresp <= RESP_OKAY; -- Write Transaction は成功
else
wr_bresp <= RESP_SLVERR; -- エラー
end if;
end if;
end if;
end if;
end process;
M_AXI_BRESP <= wr_bresp;
-- wr_bvalid の処理
-- WR_BVALID_RANDOM_WAIT が1の時にランダムにWait、0の時は1クロックWait
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
bvalid_cnt <= (others => '0');
else
if WR_BVALID_RANDOM_WAIT=1 then -- ランダムWait
if M_AXI_WLAST='1' and M_AXI_WVALID='1' and wready='1' then -- Write Transaction 終了
bvalid_cnt <= m_seq16_wr(3 downto 0); -- 0 ~ 15 wait
elsif bvalid_cnt /= 0 then
bvalid_cnt <= bvalid_cnt - 1;
end if;
else
bvalid_cnt <= (others => '0');
end if;
end if;
end if;
end process;
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
wr_bvalid <= '0';
else
if wr_bvalid='1' and M_AXI_BREADY='1' then -- wr_bvalid が1でMaster側のReadyも1ならばWrite resonse channel の転送も終了
wr_bvalid <= '0';
elsif wrt_cs=wr_bvalid_assert and bvalid_cnt=0 then -- Write Transaction 終了
wr_bvalid <= '1';
end if;
end if;
end if;
end process;
M_AXI_BVALID <= wr_bvalid;
M_AXI_BUSER <= (others => '0');
-- AXI4バス Read Transaction State Machine
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
rdt_cs <= idle_rd;
arready <= '0';
else
case (rdt_cs) is
when idle_rd =>
if M_AXI_ARVALID='1' then -- Read Transaction 要求
if wrt_cs=idle_wr and M_AXI_AWVALID='0' then -- Write Transaction State Machine がidle でWrite要求もない
rdt_cs <= arr_accept;
arready <= '1';
else -- Write Transaction が終了していないのでWait
rdt_cs <= arr_wait;
end if;
end if;
when arr_wait => -- Write Transaction の終了待ち
if wrt_cs=idle_wr and M_AXI_AWVALID='0' then -- Write Transaction State Machine がidle でWrite要求もない
rdt_cs <= arr_accept;
arready <= '1';
end if;
when arr_accept => -- M_AXI_ARREADY をアサート
rdt_cs <= rd_burst;
arready <= '0';
when rd_burst => -- Readデータの転送
if rd_axi_count=0 and rvalid='1' and M_AXI_RREADY='1' then -- Read Transaction 終了
rdt_cs <= idle_rd;
end if;
end case;
end if;
end if;
end process;
M_AXI_ARREADY <= arready;
-- m_seq_rd、16ビットのM系列を計算する
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
m_seq16_rd <= (others => '1'); -- Writeとシードを変更する
else
if READ_RANDOM_WAIT=1 then -- Read Transaciton のデータ転送でランダムなWaitを挿入する場合
if rdt_cs=rd_burst and M_AXI_RREADY='1' then
m_seq16_rd <= M_SEQ16_BFM_F(m_seq16_rd);
end if;
else -- Wati無し
m_seq16_rd <= (others => '0');
end if;
end if;
end if;
end process;
-- rvalid の処理、M系列を計算して128以上だったらWaitする。
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
cs_rvalid <= idle_rvalid;
rvalid <= '0';
else
case (cs_rvalid) is
when idle_rvalid =>
if rdt_cs=arr_accept then -- 次はrd_burst
if m_seq16_rd(7)='0' then -- rvalid='1'
cs_rvalid <= assert_rvalid;
rvalid <= '1';
else -- m_seq16_rd(7)='1' then -- rvalid='0'
cs_rvalid <= deassert_rvalid;
rvalid <= '0';
end if;
end if;
when assert_rvalid => -- 一度rvalidがアサートされたら、1つのトランザクションが終了するまでrvalid='1'
if rdt_cs=rd_burst and rlast='1' and M_AXI_RREADY='1' then -- 終了
cs_rvalid <= idle_rvalid;
rvalid <= '0';
elsif rdt_cs=rd_burst and M_AXI_RREADY='1' then -- 1つのトランザクション終了。
if m_seq16_rd(7)='1' then
cs_rvalid <= deassert_rvalid;
rvalid <= '0';
end if;
end if;
when deassert_rvalid =>
if m_seq16_rd(7)='0' then -- rvalid='1'
cs_rvalid <= assert_rvalid;
rvalid <= '1';
end if;
end case;
end if;
end if;
end process;
M_AXI_RVALID <= rvalid;
-- addr_inc_step_rd の処理
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
addr_inc_step_rd <= 1;
else
if rdt_cs=arr_accept then
case (M_AXI_ARSIZE) is
when "000" => -- 8ビット転送
addr_inc_step_rd <= 1;
when "001" => -- 16ビット転送
addr_inc_step_rd <= 2;
when "010" => -- 32ビット転送
addr_inc_step_rd <= 4;
when "011" => -- 64ビット転送
addr_inc_step_rd <= 8;
when "100" => -- 128ビット転送
addr_inc_step_rd <= 16;
when "101" => -- 256ビット転送
addr_inc_step_rd <= 32;
when "110" => -- 512ビット転送
addr_inc_step_rd <= 64;
when others => -- "111" => -- 1024ビット転送
addr_inc_step_rd <= 128;
end case;
end if;
end if;
end if;
end process;
-- rd_addr の処理
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
rd_addr <= (others => '0');
else
if rdt_cs=arr_accept then
rd_addr <= M_AXI_ARADDR(C_OFFSET_WIDTH-1 downto 0);
elsif rdt_cs=rd_burst and M_AXI_RREADY='1' and rvalid='1' then
rd_addr <= rd_addr + addr_inc_step_rd;
end if;
end if;
end if;
end process;
-- rd_axi_count の処理(AXIバス側のデータカウント)
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
rd_axi_count <= (others => '0');
else
if rdt_cs=arr_accept then -- rd_axi_count のロード
rd_axi_count <= M_AXI_ARLEN;
elsif rdt_cs=rd_burst and rvalid='1' and M_AXI_RREADY='1' then -- Read Transaction が1つ終了
rd_axi_count <= rd_axi_count - 1;
end if;
end if;
end if;
end process;
-- rdlast State Machine
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
rdlast <= idle_rlast;
rlast <= '0';
else
case (rdlast) is
when idle_rlast =>
if rd_axi_count=1 and rvalid='1' and M_AXI_RREADY='1' then -- バーストする場合
rdlast <= rlast_assert;
rlast <= '1';
elsif rdt_cs=arr_accept and M_AXI_ARLEN=0 then -- 転送数が1の場合
rdlast <= rlast_assert;
rlast <= '1';
end if;
when rlast_assert =>
if rvalid='1' and M_AXI_RREADY='1' then -- Read Transaction 終了(rd_axi_count=0は決定)
rdlast <= idle_rlast;
rlast <= '0';
end if;
end case;
end if;
end if;
end process;
M_AXI_RLAST <= rlast;
-- M_AXI_RID, M_AXI_RUSER の処理
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
M_AXI_RID <= (others => '0');
else
if rdt_cs=arr_accept then
M_AXI_RID <= M_AXI_ARID;
end if;
end if;
end if;
end process;
M_AXI_RUSER <= (others => '0');
-- M_AXI_RRESP は、M_AXI_ARBURST がINCR の場合はOKAYを返す。それ以外はSLVERRを返す。
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
M_AXI_RRESP <= (others => '0');
else
if rdt_cs=arr_accept then
if M_AXI_ARBURST=AxBURST_INCR then
M_AXI_RRESP <= RESP_OKAY;
else
M_AXI_RRESP <= RESP_SLVERR;
end if;
end if;
end if;
end if;
end process;
-- RAM
process (ACLK) begin
if ACLK'event and ACLK='1' then
if cdc_we='1' then
for i in 0 to C_M_AXI_DATA_WIDTH/8-1 loop
if M_AXI_WSTRB(i)='1' then -- Byte Enable
ram_array(CONV_INTEGER(wr_addr(C_OFFSET_WIDTH-1 downto ADD_INC_OFFSET)))(i*8+7 downto i*8) <= M_AXI_WDATA(i*8+7 downto i*8);
end if;
end loop;
end if;
end if;
end process;
M_AXI_RDATA <= ram_array(CONV_INTEGER(rd_addr(C_OFFSET_WIDTH-1 downto ADD_INC_OFFSET)));
end implementation;
-------------------------------------------------------------------------------
--
-- AXI Master
--
-- VHDL-Standard: VHDL'93
----------------------------------------------------------------------------
--
-- Structure:
-- mt9d111_inf_axi_master
--
----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
--library unisim;
--use unisim.vcomponents.all;
entity mt9d111_inf_axi_master is
generic(
C_M_AXI_SUPPORTS_THREADS : integer := 0;
C_M_AXI_THREAD_ID_WIDTH : integer := 1;
C_M_AXI_ADDR_WIDTH : integer := 32;
C_M_AXI_DATA_WIDTH : integer := 64;
C_INTERCONNECT_M_AXI_WRITE_ISSUING : integer := 8;
C_INTERCONNECT_M_AXI_READ_ISSUING : integer := 8;
C_M_AXI_SUPPORTS_READ : integer := 0;
C_M_AXI_SUPPORTS_WRITE : integer := 1;
C_M_AXI_SUPPORTS_USER_SIGNALS : integer := 0;
C_M_AXI_AWUSER_WIDTH : integer := 1;
C_M_AXI_ARUSER_WIDTH : integer := 1;
C_M_AXI_WUSER_WIDTH : integer := 1;
C_M_AXI_RUSER_WIDTH : integer := 1;
C_M_AXI_BUSER_WIDTH : integer := 1;
C_M_AXI_SUPPORTS_NARROW_BURST : integer := 0;
C_M_AXI_TARGET : std_logic_vector(31 downto 0) := x"00000000";
C_M_AXI_BURST_LEN : integer := 16;
C_OFFSET_WIDTH : integer := 9;
C_DISPLAY_START_ADDRESS : std_logic_vector(31 downto 0) := x"10000000";
C_UPSIDE_DOWN : integer := 0 -- 1 = 上下反転、0 = 正常
);
port(
-- System Signals
ACLK : in std_logic;
ARESETN : in std_logic;
-- Master Interface Write Address
M_AXI_AWID : out std_logic_vector(C_M_AXI_THREAD_ID_WIDTH-1 downto 0);
M_AXI_AWADDR : out std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0);
M_AXI_AWLEN : out std_logic_vector(8-1 downto 0);
M_AXI_AWSIZE : out std_logic_vector(3-1 downto 0);
M_AXI_AWBURST : out std_logic_vector(2-1 downto 0);
M_AXI_AWLOCK : out std_logic;
M_AXI_AWCACHE : out std_logic_vector(4-1 downto 0);
M_AXI_AWPROT : out std_logic_vector(3-1 downto 0);
-- AXI3 M_AXI_AWREGION:out std_logic_vector(4-1 downto 0);
M_AXI_AWQOS : out std_logic_vector(4-1 downto 0);
M_AXI_AWUSER : out std_logic_vector(C_M_AXI_AWUSER_WIDTH-1 downto 0);
M_AXI_AWVALID : out std_logic;
M_AXI_AWREADY : in std_logic;
-- Master Interface Write Data
-- AXI3 M_AXI_WID(C_M_AXI_THREAD_ID_WIDTH-1 downto 0);
M_AXI_WDATA : out std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
M_AXI_WSTRB : out std_logic_vector(C_M_AXI_DATA_WIDTH/8-1 downto 0);
M_AXI_WLAST : out std_logic;
M_AXI_WUSER : out std_logic_vector(C_M_AXI_WUSER_WIDTH-1 downto 0);
M_AXI_WVALID : out std_logic;
M_AXI_WREADY : in std_logic;
-- Master Interface Write Response
M_AXI_BID : in std_logic_vector(C_M_AXI_THREAD_ID_WIDTH-1 downto 0);
M_AXI_BRESP : in std_logic_vector(2-1 downto 0);
M_AXI_BUSER : in std_logic_vector(C_M_AXI_BUSER_WIDTH-1 downto 0);
M_AXI_BVALID : in std_logic;
M_AXI_BREADY : out std_logic;
-- Master Interface Read Address
M_AXI_ARID : out std_logic_vector(C_M_AXI_THREAD_ID_WIDTH-1 downto 0);
M_AXI_ARADDR : out std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0);
M_AXI_ARLEN : out std_logic_vector(8-1 downto 0);
M_AXI_ARSIZE : out std_logic_vector(3-1 downto 0);
M_AXI_ARBURST : out std_logic_vector(2-1 downto 0);
M_AXI_ARLOCK : out std_logic_vector(2-1 downto 0);
M_AXI_ARCACHE : out std_logic_vector(4-1 downto 0);
M_AXI_ARPROT : out std_logic_vector(3-1 downto 0);
-- AXI3 M_AXI_ARREGION:out std_logic_vector(4-1 downto 0);
M_AXI_ARQOS : out std_logic_vector(4-1 downto 0);
M_AXI_ARUSER : out std_logic_vector(C_M_AXI_ARUSER_WIDTH-1 downto 0);
M_AXI_ARVALID : out std_logic;
M_AXI_ARREADY : in std_logic;
-- Master Interface Read Data
M_AXI_RID : in std_logic_vector(C_M_AXI_THREAD_ID_WIDTH-1 downto 0);
M_AXI_RDATA : in std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
M_AXI_RRESP : in std_logic_vector(2-1 downto 0);
M_AXI_RLAST : in std_logic;
M_AXI_RUSER : in std_logic_vector(C_M_AXI_RUSER_WIDTH-1 downto 0);
M_AXI_RVALID : in std_logic;
M_AXI_RREADY : out std_logic;
init_done : in std_logic;
wr_error : out std_logic; -- AXI4 Write 時のエラー(M_AXI_BRESP/=RESP_OKAY)
-- MT9D111 Camera Interface
pclk_from_pll : in std_logic; -- PLLからMT9D111のxck に出力するクロック
pclk : in std_logic; -- MT9D111からのピクセルクロック入力
xck : out std_logic; -- MT9D111へのピクセルクロック出力
href : in std_logic;
vsync : in std_logic;
cam_data : in std_logic_vector(7 downto 0);
standby : out std_logic; -- STANDBY出力(ディスエーブル、0固定)
pfifo_overflow : out std_logic; -- pfifo overflow
pfifo_underflow : out std_logic -- pfifo underflow
);
end mt9d111_inf_axi_master;
-------------------------------------------------------------------------------
-- Architecture
-------------------------------------------------------------------------------
architecture implementation of mt9d111_inf_axi_master is
constant RESP_OKAY : std_logic_vector := "00";
constant RESP_EXOKAY : std_logic_vector := "01";
constant RESP_SLVERR : std_logic_vector := "10";
constant RESP_DECERR : std_logic_vector := "11";
constant DDR3_START_ADDR : std_logic_vector := x"10000000";
constant ROW_ALL_PIXELS : integer := 640;
constant COULMN_ALL_PIXELS : integer := 480;
constant SVGA_ADDR_LIMIT : integer := ROW_ALL_PIXELS*COULMN_ALL_PIXELS*4; -- SVGAのアドレスリミット(横ピクセル数 * 縦ピクセル数 * 1ピクセルを表すバイト数)
signal reset_1d, reset_2d, reset : std_logic;
type wr_main_transaction_state is (idle_wr_main, write_state);
signal wr_main_cs, wr_main_1d : wr_main_transaction_state;
type write_transaction_state is (idle_wr, awvalid_assert, data_write_hold, bready_assert, wr_tran_end);
signal wrt_cs : write_transaction_state;
type write_wvalid_state is (idle_wvalid, wvalid_assert, wvalid_hold);
signal wrt_wv_cs : write_wvalid_state;
signal awvalid, wvalid, bready : std_logic;
signal awlen, write_count : std_logic_vector(7 downto 0);
signal wlast : std_logic;
signal preset_1d, preset_2d, preset : std_logic;
signal pfifo_empty : std_logic;
signal pfifo_almost_empty : std_logic;
signal pfifo_rd_data_count : std_logic_vector(9 downto 0);
signal pfifo_rd_dcount_dec : unsigned(9 downto 0);
signal pfifo_rd_en : std_logic;
component mt9d111_cam_cont generic (
DISPLAY_START_ADDRESS : std_logic_vector(31 downto 0) := x"10000000";
UPSIDE_DOWN : integer := 0
);
port(
aclk : in std_logic;
areset : in std_logic;
pclk : in std_logic;
preset : in std_logic;
pclk_from_pll : in std_logic;
xclk : out std_logic;
line_valid : in std_logic;
frame_valid : in std_logic;
cam_data : in std_logic_vector(7 downto 0);
standby : out std_logic;
paddr : out std_logic_vector(31 downto 0);
pfifo_rd_en : in std_logic;
pfifo_dout : out std_logic_vector(63 downto 0);
pfifo_empty : out std_logic;
pfifo_almost_empty : out std_logic;
pfifo_rd_data_count : out std_logic_vector(9 downto 0);
pfifo_overflow : out std_logic;
pfifo_underflow : out std_logic
);
end component;
begin
-- ARESETN をACLK で同期化
process (ACLK) begin
if ACLK'event and ACLK='1' then
reset_1d <= not ARESETN or not init_done;
reset_2d <= reset_1d;
end if;
end process;
reset <= reset_2d;
-- ARESETN をpclk で同期化
process(pclk) begin
if pclk'event and pclk='1' then
preset_1d <= not ARESETN or not init_done;
preset_2d <= preset_1d;
end if;
end process;
preset <= preset_2d;
-- Write Transaction State Machine
-- ピクセルデータが存在する時(pfifo_empty=0)の時に、 Writeを行う。Readは無し
process(ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
wr_main_cs <= idle_wr_main;
else
case (wr_main_cs) is
when idle_wr_main =>
if pfifo_rd_data_count/=std_logic_vector(to_unsigned(0, pfifo_rd_data_count'length)) then
wr_main_cs <= write_state;
end if;
when write_state =>
if wrt_cs = wr_tran_end then -- pfifo のピクセルデータをAXI4バス経由で転送終了
wr_main_cs <= idle_wr_main;
end if;
end case;
end if;
end if;
end process;
pfifo_rd_en <= M_AXI_WREADY and wvalid;
mt9d111_cam_cont_i : mt9d111_cam_cont generic map(
DISPLAY_START_ADDRESS => C_DISPLAY_START_ADDRESS,
UPSIDE_DOWN => C_UPSIDE_DOWN
)port map(
aclk => ACLK,
areset => reset,
pclk => pclk,
preset => preset,
pclk_from_pll => pclk_from_pll,
xclk => xck,
line_valid => href,
frame_valid => vsync,
cam_data => cam_data,
standby => standby,
paddr => M_AXI_AWADDR,
pfifo_rd_en => pfifo_rd_en,
pfifo_dout => M_AXI_WDATA,
pfifo_empty => pfifo_empty,
pfifo_almost_empty => pfifo_almost_empty,
pfifo_rd_data_count => pfifo_rd_data_count,
pfifo_overflow => pfifo_overflow,
pfifo_underflow => pfifo_underflow
);
-- Write
M_AXI_AWID <= "0";
M_AXI_AWSIZE <= "011"; -- 8 bytes fixed
M_AXI_AWBURST <= "01"; -- INCR
M_AXI_AWLOCK <= '0'; -- Normal Access
M_AXI_AWCACHE <= "0010"; -- Normal Non-cacheable Non-bufferable
-- M_AXI_AWCACHE <= "0011"; -- Normal Non-cacheable Bufferable, Zynq-7020ではBRESPが10でSLVERRになってしまい設定してはならない。
M_AXI_AWPROT <= "000"; -- Data access, Secure access, Unprivileged access
M_AXI_AWQOS <= "0000"; -- default
M_AXI_AWUSER <= "0";
M_AXI_WSTRB <= (others => '1');
M_AXI_WUSER <= "0";
M_AXI_AWLEN <= awlen;
-- AXI4バス Write Transaction State Machine
process(ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
wrt_cs <= idle_wr;
awvalid <= '0';
bready <= '0';
else
case(wrt_cs) is
when idle_wr =>
if wr_main_cs = write_state then
wrt_cs <= awvalid_assert;
awvalid <= '1';
end if;
when awvalid_assert =>
if M_AXI_AWREADY='1' then
if wrt_wv_cs=wvalid_hold or (wrt_wv_cs=wvalid_assert and unsigned(write_count)=0 and M_AXI_WREADY='1') then
wrt_cs <= bready_assert;
bready <= '1';
else
wrt_cs <= data_write_hold;
end if;
awvalid <= '0';
end if;
when data_write_hold =>
if wrt_wv_cs=wvalid_hold or (wrt_wv_cs=wvalid_assert and unsigned(write_count)=0 and M_AXI_WREADY='1') then
wrt_cs <= bready_assert;
bready <= '1';
end if;
when bready_assert =>
if M_AXI_BVALID='1' then
wrt_cs <= wr_tran_end;
bready <= '0';
end if;
when wr_tran_end =>
wrt_cs <= idle_wr;
end case;
end if;
end if;
end process;
-- AXI4 バス Write Transaction WVALID State Machine
process(ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
wrt_wv_cs <= idle_wvalid;
wvalid <= '0';
else
case(wrt_wv_cs) is
when idle_wvalid =>
if wrt_cs=awvalid_assert then
wrt_wv_cs <= wvalid_assert;
wvalid <= '1';
end if;
when wvalid_assert =>
if unsigned(write_count)=0 and M_AXI_WREADY='1' then -- 終了
wrt_wv_cs <= wvalid_hold;
wvalid <= '0';
end if;
when wvalid_hold =>
if wrt_cs=bready_assert then
wrt_wv_cs <= idle_wvalid;
end if;
end case;
end if;
end if;
end process;
M_AXI_AWVALID <= awvalid;
M_AXI_WVALID <= wvalid;
M_AXI_BREADY <= bready;
-- write_count の処理
pfifo_rd_dcount_dec <= unsigned(pfifo_rd_data_count) - 1;
process(ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
write_count <= (others => '0');
awlen <= (others => '0');
else
if wr_main_cs = write_state and wrt_cs=idle_wr then -- wr_main_cs がwrite_state になった最初の1クロック
if C_UPSIDE_DOWN = 0 then -- 正常表示の場合
write_count <= std_logic_vector(pfifo_rd_dcount_dec(7 downto 0));
awlen <= std_logic_vector(pfifo_rd_dcount_dec(7 downto 0));
else -- 上下反転する場合はシングル転送
write_count <= std_logic_vector(to_unsigned(0, write_count'length));
awlen <= std_logic_vector(to_unsigned(0, awlen'length));
end if;
elsif wrt_wv_cs=wvalid_assert and M_AXI_WREADY='1' and unsigned(write_count)/=0 then -- 1つデータ転送出来た
write_count <= std_logic_vector(unsigned(write_count) - 1);
end if;
end if;
end if;
end process;
-- wlastの処理
process(ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
wlast <= '0';
else
if wr_main_cs = write_state and wrt_cs=idle_wr then -- Wrire Transaction を開始する際に、
if C_UPSIDE_DOWN = 0 then -- 正常表示の場合
if unsigned(pfifo_rd_data_count)=1 then -- pfifo_rd_data_count が1の時はデータ転送の最初からwlast をアサートする
wlast <= '1';
end if;
else -- 上下反転する場合はシングル転送
wlast <= '1';
end if;
elsif wrt_wv_cs=wvalid_assert and unsigned(write_count)=1 and M_AXI_WREADY='1' then -- awlen が0で無い時はwrite_count が1でM_AXI_WREADY='1'の時、つまりwrite_count が0の時にwlastをアサートする
wlast <= '1';
elsif wrt_wv_cs=wvalid_assert and unsigned(write_count)=0 and M_AXI_WREADY='1' then -- データ転送が終了なのでwlast を0にする
wlast <= '0';
end if;
end if;
end if;
end process;
M_AXI_WLAST <= wlast;
-- wr_error の処理、M_AXI_BRESPがRESP_OKAY以外の時にwr_errorを点灯する
process(ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
wr_error <= '0';
else
if wrt_cs=bready_assert and M_AXI_BVALID='1' and M_AXI_BRESP/=RESP_OKAY then
wr_error <= '1';
end if;
end if;
end if;
end process;
-- Readは無し
M_AXI_ARID <= "0";
M_AXI_ARLEN <= (others => '0');
M_AXI_ARSIZE <= "010"; -- 4bytes
M_AXI_ARBURST <= "01"; -- INCR
M_AXI_ARLOCK <= "00"; -- Normal Access
M_AXI_ARCACHE <= "0010"; -- Normal Non-cacheable Non-bufferable
M_AXI_ARPROT <= "000"; -- Data access, Secure access, Unprivileged access
M_AXI_ARQOS <= "0000"; -- default
M_AXI_ARUSER <= "0";
M_AXI_ARADDR <= (others => '0');
M_AXI_ARVALID <= '0';
M_AXI_RREADY <= '0';
end implementation;
// MT9D111カメラコントローラ
// MT9D111_cam_cont.v
// 2012/12/26
//
`default_nettype none
module mt9d111_cam_cont # (
parameter DISPLAY_START_ADDRESS = 32'h10000000, // Frame Buffer Start Address
parameter integer UPSIDE_DOWN = 0 // 1 = 上下反転、0 = 正常
)(
input wire aclk,
input wire areset,
input wire pclk,
input wire preset,
input wire pclk_from_pll,
output wire xclk,
input wire line_valid,
input wire frame_valid,
input wire [7:0] cam_data,
output wire standby,
output wire [31:0] paddr,
input wire pfifo_rd_en,
output wire [63:0] pfifo_dout,
output wire pfifo_empty,
output wire pfifo_almost_empty,
output wire [9:0] pfifo_rd_data_count,
output wire pfifo_overflow,
output wire pfifo_underflow
);
`include "./disp_timing_parameters.vh"
// Frame Buffer End Address
localparam DISPLAY_END_ADDRESS = DISPLAY_START_ADDRESS + (H_ACTIVE_VIDEO * V_ACTIVE_VIDEO)*4 - 8; // 最後のピクセル、1ピクセル = 4バイトで、64ビットバス幅なので、8バイトごと
reg line_valid_1d;
reg frame_valid_1d;
reg [7:0] cam_data_1d;
reg line_valid_1d_odd;
reg line_v_1d_odd_1d;
reg [63:0] rgb565;
wire pfifo_full, pfifo_almost_full;
reg frame_valid_1d_aclk_1d, frame_valid_1d_aclk_2d;
parameter [1:0] IDLE_ADDR_RST = 2'b00,
ADDR_RST = 2'b01,
ADDR_RST_HOLD = 2'b11;
reg [1:0] addr_rst_cs;
reg [31:0] paddr_reg;
reg rgb565_2nd;
assign standby = 1'b0;
// MT9D111 へのクロックを出力 (xclk)
ODDR #(
.DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE"
.INIT(1'b0), // Initial value of Q: 1'b0 or 1'b1
.SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
) ODDR_inst (
.Q(xclk), // 1-bit DDR output
.C(pclk_from_pll), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D1(1'b1), // 1-bit data input (positive edge)
.D2(1'b0), // 1-bit data input (negative edge)
.R(1'b0), // 1-bit reset
.S(1'b0) // 1-bit set
);
// 入力信号を一旦ラッチする
always @(posedge pclk) begin
if (preset) begin
line_valid_1d <= 1'b0;
frame_valid_1d <= 1'b0;
cam_data_1d <= 8'd0;
end else begin
line_valid_1d <= line_valid;
frame_valid_1d <= frame_valid;
cam_data_1d <= cam_data;
end
end
// frame_valid_1d をaclk でラッチする
always @(posedge aclk) begin
if (areset) begin
frame_valid_1d_aclk_1d <= 1'b0;
frame_valid_1d_aclk_2d <= 1'b0;
end else begin
frame_valid_1d_aclk_1d <= frame_valid_1d;
frame_valid_1d_aclk_2d <= frame_valid_1d_aclk_1d;
end
end
// line_valid_1d が偶数か奇数かをカウント
always @(posedge pclk) begin
if (preset)
line_valid_1d_odd <= 1'b0;
else begin
if (line_valid_1d)
line_valid_1d_odd <= ~line_valid_1d_odd;
else
line_valid_1d_odd <= 1'b0;
end
end
// rgb565でラッチしているので、line_valid_1d_odd を1クロック遅延する
always @(posedge pclk) begin
if (preset)
line_v_1d_odd_1d <= 1'b0;
else
line_v_1d_odd_1d <= line_valid_1d_odd;
end
// 2番めのRGB565を示す。64ビット長のFIFOに入れるのに2ピクセル集めてから非同期FIFOにWriteする
always @(posedge pclk) begin
if (preset)
rgb565_2nd <= 1'b0;
else begin
if (line_valid_1d_odd)
rgb565_2nd <= ~rgb565_2nd;
end
end
// addressの生成
always @(posedge aclk) begin
if (areset) begin
if (UPSIDE_DOWN==0) // 正常、それ以外は上下反転
paddr_reg <= DISPLAY_START_ADDRESS;
else // 上下反転
paddr_reg <= DISPLAY_END_ADDRESS;
end else begin
if (pfifo_rd_en) begin
if (UPSIDE_DOWN==0) // 正常
paddr_reg <= paddr_reg + 32'd8;
else // 上下反転
paddr_reg <= paddr_reg - 32'd8;
end else if (addr_rst_cs==ADDR_RST) begin // frame_valid が0になって、pfifoにデータが無くなった時にアドレスをクリア
if (UPSIDE_DOWN==0) // 正常、それ以外は上下反転
paddr_reg <= DISPLAY_START_ADDRESS;
else // 上下反転
paddr_reg <= DISPLAY_END_ADDRESS;
end
end
end
assign paddr = paddr_reg;
// address をリセットするためのステートマシン
always @(posedge aclk) begin
if (areset)
addr_rst_cs <= IDLE_ADDR_RST;
else begin
case (addr_rst_cs)
IDLE_ADDR_RST :
if (~frame_valid_1d_aclk_2d & pfifo_empty)
addr_rst_cs <= ADDR_RST;
ADDR_RST :
addr_rst_cs <= ADDR_RST_HOLD;
ADDR_RST_HOLD :
if (frame_valid_1d_aclk_2d)
addr_rst_cs <= IDLE_ADDR_RST;
endcase
end
end
// RGB565 のデータを保存する。正常と上下反転ではバイト配列が異なる
always @(posedge pclk) begin
if (preset)
rgb565 <= 32'd0;
else begin
if (UPSIDE_DOWN==0) begin // 正常、それ以外は上下反転
case ({rgb565_2nd, line_valid_1d_odd})
2'b00 : // 1番目
rgb565[63:45] <= {8'd0, cam_data_1d[7:3], 3'b000, cam_data_1d[2:0]}; // cam_data_1d = R7 R6 R5 R4 R3 G7 G6 G5
2'b01 : // 2番目
rgb565[44:32] <= {cam_data_1d[7:5], 2'b00, cam_data_1d[4:0], 3'b000}; // cam_data_1d = G4 G3 G2 B7 B6 B5 B4 B3
2'b10 : // 3番目
rgb565[31:13] <= {8'd0, cam_data_1d[7:3], 3'b000, cam_data_1d[2:0]}; // cam_data_1d = R7 R6 R5 R4 R3 G7 G6 G5
2'b11 : // 4番目
rgb565[12:0] <= {cam_data_1d[7:5], 2'b00, cam_data_1d[4:0], 3'b000}; // cam_data_1d = G4 G3 G2 B7 B6 B5 B4 B3
endcase
end else begin // 上下反転
case ({rgb565_2nd, line_valid_1d_odd})
2'b00 : // 1番目
rgb565[31:13] <= {8'd0, cam_data_1d[7:3], 3'b000, cam_data_1d[2:0]}; // cam_data_1d = R7 R6 R5 R4 R3 G7 G6 G5
2'b01 : // 2番目
rgb565[12:0] <= {cam_data_1d[7:5], 2'b00, cam_data_1d[4:0], 3'b000}; // cam_data_1d = G4 G3 G2 B7 B6 B5 B4 B3
2'b10 : // 3番目
rgb565[63:45] <= {8'd0, cam_data_1d[7:3], 3'b000, cam_data_1d[2:0]}; // cam_data_1d = R7 R6 R5 R4 R3 G7 G6 G5
2'b11 : // 4番目
rgb565[44:32] <= {cam_data_1d[7:5], 2'b00, cam_data_1d[4:0], 3'b000}; // cam_data_1d = G4 G3 G2 B7 B6 B5 B4 B3
endcase
end
end
end
// pixel FIFO をインスタンスする
pixel_fifo pfifo (
.rst(areset), // input rst
.wr_clk(pclk), // input wr_clk
.rd_clk(aclk), // input rd_clk
.din(rgb565), // input [63 : 0] din
.wr_en(line_v_1d_odd_1d & ~rgb565_2nd), // input wr_en, 2つのピクセルが揃うには4クロック掛かる
.rd_en(pfifo_rd_en), // input rd_en
.dout(pfifo_dout), // output [63 : 0] dout
.full(pfifo_full), // output full
.almost_full(pfifo_almost_full), // output almost_full
.overflow(pfifo_overflow), // output overflow
.empty(pfifo_empty), // output empty
.almost_empty(pfifo_almost_empty), // output almost_empty
.underflow(pfifo_underflow), // output underflow
.rd_data_count(pfifo_rd_data_count) // output [9 : 0] rd_data_count
);
endmodule
`default_nettype wire
##############################################################
#
# Xilinx Core Generator version 14.4
# Date: Wed Jan 16 12:27:21 2013
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# Generated from component: xilinx.com:ip:fifo_generator:9.3
#
##############################################################
#
# BEGIN Project Options
SET addpads = false
SET asysymbol = true
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = false
SET designentry = Verilog
SET device = xc7z020
SET devicefamily = zynq
SET flowvendor = Other
SET formalverification = false
SET foundationsym = false
SET implementationfiletype = Ngc
SET package = clg484
SET removerpms = false
SET simulationfiles = Behavioral
SET speedgrade = -1
SET verilogsim = true
SET vhdlsim = false
# END Project Options
# BEGIN Select
SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3
# END Select
# BEGIN Parameters
CSET add_ngc_constraint_axi=false
CSET almost_empty_flag=true
CSET almost_full_flag=true
CSET aruser_width=1
CSET awuser_width=1
CSET axi_address_width=32
CSET axi_data_width=64
CSET axi_type=AXI4_Stream
CSET axis_type=FIFO
CSET buser_width=1
CSET clock_enable_type=Slave_Interface_Clock_Enable
CSET clock_type_axi=Common_Clock
CSET component_name=pixel_fifo
CSET data_count=false
CSET data_count_width=9
CSET disable_timing_violations=false
CSET disable_timing_violations_axi=false
CSET dout_reset_value=0
CSET empty_threshold_assert_value=4
CSET empty_threshold_assert_value_axis=1022
CSET empty_threshold_assert_value_rach=1022
CSET empty_threshold_assert_value_rdch=1022
CSET empty_threshold_assert_value_wach=1022
CSET empty_threshold_assert_value_wdch=1022
CSET empty_threshold_assert_value_wrch=1022
CSET empty_threshold_negate_value=5
CSET enable_aruser=false
CSET enable_awuser=false
CSET enable_buser=false
CSET enable_common_overflow=false
CSET enable_common_underflow=false
CSET enable_data_counts_axis=false
CSET enable_data_counts_rach=false
CSET enable_data_counts_rdch=false
CSET enable_data_counts_wach=false
CSET enable_data_counts_wdch=false
CSET enable_data_counts_wrch=false
CSET enable_ecc=false
CSET enable_ecc_axis=false
CSET enable_ecc_rach=false
CSET enable_ecc_rdch=false
CSET enable_ecc_wach=false
CSET enable_ecc_wdch=false
CSET enable_ecc_wrch=false
CSET enable_read_channel=false
CSET enable_read_pointer_increment_by2=false
CSET enable_reset_synchronization=true
CSET enable_ruser=false
CSET enable_tdata=false
CSET enable_tdest=false
CSET enable_tid=false
CSET enable_tkeep=false
CSET enable_tlast=false
CSET enable_tready=true
CSET enable_tstrobe=false
CSET enable_tuser=false
CSET enable_write_channel=false
CSET enable_wuser=false
CSET fifo_application_type_axis=Data_FIFO
CSET fifo_application_type_rach=Data_FIFO
CSET fifo_application_type_rdch=Data_FIFO
CSET fifo_application_type_wach=Data_FIFO
CSET fifo_application_type_wdch=Data_FIFO
CSET fifo_application_type_wrch=Data_FIFO
CSET fifo_implementation=Independent_Clocks_Block_RAM
CSET fifo_implementation_axis=Common_Clock_Block_RAM
CSET fifo_implementation_rach=Common_Clock_Distributed_RAM
CSET fifo_implementation_rdch=Common_Clock_Block_RAM
CSET fifo_implementation_wach=Common_Clock_Distributed_RAM
CSET fifo_implementation_wdch=Common_Clock_Block_RAM
CSET fifo_implementation_wrch=Common_Clock_Distributed_RAM
CSET full_flags_reset_value=1
CSET full_threshold_assert_value=511
CSET full_threshold_assert_value_axis=1023
CSET full_threshold_assert_value_rach=1023
CSET full_threshold_assert_value_rdch=1023
CSET full_threshold_assert_value_wach=1023
CSET full_threshold_assert_value_wdch=1023
CSET full_threshold_assert_value_wrch=1023
CSET full_threshold_negate_value=510
CSET id_width=4
CSET inject_dbit_error=false
CSET inject_dbit_error_axis=false
CSET inject_dbit_error_rach=false
CSET inject_dbit_error_rdch=false
CSET inject_dbit_error_wach=false
CSET inject_dbit_error_wdch=false
CSET inject_dbit_error_wrch=false
CSET inject_sbit_error=false
CSET inject_sbit_error_axis=false
CSET inject_sbit_error_rach=false
CSET inject_sbit_error_rdch=false
CSET inject_sbit_error_wach=false
CSET inject_sbit_error_wdch=false
CSET inject_sbit_error_wrch=false
CSET input_data_width=64
CSET input_depth=512
CSET input_depth_axis=1024
CSET input_depth_rach=16
CSET input_depth_rdch=1024
CSET input_depth_wach=16
CSET input_depth_wdch=1024
CSET input_depth_wrch=16
CSET interface_type=Native
CSET output_data_width=64
CSET output_depth=512
CSET overflow_flag=true
CSET overflow_flag_axi=false
CSET overflow_sense=Active_High
CSET overflow_sense_axi=Active_High
CSET performance_options=First_Word_Fall_Through
CSET programmable_empty_type=No_Programmable_Empty_Threshold
CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold
CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold
CSET programmable_full_type=No_Programmable_Full_Threshold
CSET programmable_full_type_axis=No_Programmable_Full_Threshold
CSET programmable_full_type_rach=No_Programmable_Full_Threshold
CSET programmable_full_type_rdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wach=No_Programmable_Full_Threshold
CSET programmable_full_type_wdch=No_Programmable_Full_Threshold
CSET programmable_full_type_wrch=No_Programmable_Full_Threshold
CSET rach_type=FIFO
CSET rdch_type=FIFO
CSET read_clock_frequency=1
CSET read_data_count=true
CSET read_data_count_width=10
CSET register_slice_mode_axis=Fully_Registered
CSET register_slice_mode_rach=Fully_Registered
CSET register_slice_mode_rdch=Fully_Registered
CSET register_slice_mode_wach=Fully_Registered
CSET register_slice_mode_wdch=Fully_Registered
CSET register_slice_mode_wrch=Fully_Registered
CSET reset_pin=true
CSET reset_type=Asynchronous_Reset
CSET ruser_width=1
CSET synchronization_stages=2
CSET synchronization_stages_axi=2
CSET tdata_width=64
CSET tdest_width=4
CSET tid_width=8
CSET tkeep_width=4
CSET tstrb_width=4
CSET tuser_width=4
CSET underflow_flag=true
CSET underflow_flag_axi=false
CSET underflow_sense=Active_High
CSET underflow_sense_axi=Active_High
CSET use_clock_enable=false
CSET use_dout_reset=true
CSET use_embedded_registers=true
CSET use_extra_logic=true
CSET valid_flag=false
CSET valid_sense=Active_High
CSET wach_type=FIFO
CSET wdch_type=FIFO
CSET wrch_type=FIFO
CSET write_acknowledge_flag=false
CSET write_acknowledge_sense=Active_High
CSET write_clock_frequency=1
CSET write_data_count=false
CSET write_data_count_width=10
CSET wuser_width=1
# END Parameters
# BEGIN Extra information
MISC pkg_timestamp=2012-11-19T12:39:56Z
# END Extra information
GENERATE
# CRC: 73737d3d
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | 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 | - | - |