-----------------------------------------------------------------------------
--
-- AXI Stream Master用 AXI Stream 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 axi4s_slave_bfm is
generic (
-- Master AXI Stream Data Width
C_M_AXIS_DATA_WIDTH : integer range 8 to 1024 := 24; C_M_AXI_ID_WIDTH : integer := 1;
TREADY_RANDOM_WAIT : integer := 1 -- m_axis_treadyにランダムなWaitを発生させる=1, Waitしない=0
);
port(
-- System Signals
ACLK : in std_logic;
ARESETN : in std_logic;
-- Master Stream Ports
-- m_axis_aresetn : out std_logic;
m_axis_tdata : in std_logic_vector(C_M_AXIS_DATA_WIDTH-1 downto 0);
m_axis_tstrb : in std_logic_vector((C_M_AXIS_DATA_WIDTH/8)-1 downto 0);
m_axis_tvalid : in std_logic;
m_axis_tready : out std_logic;
m_axis_tlast : in std_logic
);
end axi4s_slave_bfm;
architecture RTL of axi4s_slave_bfm is
signal m_seq16_wr : std_logic_vector(15 downto 0);
signal reset_1d, reset_2d, reset : std_logic := '1';
signal tready : std_logic;
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;
-- 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 TREADY_RANDOM_WAIT=1 then -- ランダムなWaitを挿入する
m_seq16_wr <= M_SEQ16_BFM_F(m_seq16_wr);
else -- Wait無し
m_seq16_wr <= (others => '0');
end if;
end if;
end if;
end process;
-- tready のアサート、TREADY_RANDOM_WAIT=1のときはランダムにアサートする
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset='1' then
tready <= '0';
else
if TREADY_RANDOM_WAIT=1 then -- tready の処理、M系列を計算して128以上だったらWaitする。
if m_seq16_wr(7)='0' then -- tready='1'
tready <= '1';
else -- m_seq16_wr(7)='1' then -- tready='0'
tready <= '0';
end if;
else -- 常時1
tready <= '1';
end if;
end if;
end if;
end process;
m_axis_tready <= tready;
end RTL;
// 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'b0,
output reg [7:0] d = 8'd0,
input wire scl,
inout wire sda,
input wire standby
);
parameter [2:0] INITIAL_STATE = 3'b000,
FRAME_START_BLANKING = 3'b001,
ACTIVE_DATA_TIME = 3'b011,
HORIZONTAL_BLANKING = 3'b010,
FRAME_END_BLANKING = 3'b110,
VERTICAL_BLANKING = 3'b111;
reg [2:0] mt9d111_cs = INITIAL_STATE;
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 [15:0] init_count = 10; // 初期化時間
reg href_node = 1'b0;
reg vsync_node = 1'b0;
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)
INITIAL_STATE : begin
if (init_count==0) begin
mt9d111_cs <= FRAME_START_BLANKING;
vsync_node <= 1'b1;
end
end
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
// Initial Counter
always @(posedge pclk) begin
if (mt9d111_cs == INITIAL_STATE) begin
if (init_count != 0)
init_count <= init_count - 1;
end
end
// Active Data Time Counter
always @(posedge pclk) begin
if (mt9d111_cs != INITIAL_STATE) 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
end
// Horizontal Blanking Counter
always @(posedge pclk) begin
if (mt9d111_cs != INITIAL_STATE) 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
end
// Frame Valid Time Counter
always @(posedge pclk) begin
if (mt9d111_cs != INITIAL_STATE) 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
end
// Vertical Blanking Counter
always @(posedge pclk) begin
if (mt9d111_cs != INITIAL_STATE) 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
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
`default_nettype none
`timescale 100ps / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 09:51:18 12/31/2012
// Design Name: mt9d111_inf_axi_master
// Module Name: D:\HDL\FndtnISEWork\Zynq-7000\ZedBoard\test\VDMA_test\mt9d111_inf_axi_stream_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_stream_tb;
wire s2mm_aclk;
wire s2mm_prmry_reset;
wire s2mm_fsync;
wire init_done;
wire pclk_from_pll;
wire pclk;
wire href;
wire vsync;
wire [7:0] cam_data;
wire xck;
wire standby;
wire pfifo_overflow;
wire pfifo_underflow;
wire [23:0] m_axis_tdata;
wire [2:0] m_axis_tstrb;
wire m_axis_tvalid;
wire m_axis_tready;
wire m_axis_tlast;
// Instantiate the Unit Under Test (UUT)
mt9d111_inf_axi_stream # (
.C_M_AXIS_DATA_WIDTH(24)
) uut (
.s2mm_aclk(s2mm_aclk),
.s2mm_prmry_reset(s2mm_prmry_reset),
.s2mm_fsync(s2mm_fsync),
.m_axis_tdata(m_axis_tdata),
.m_axis_tstrb(m_axis_tstrb),
.m_axis_tvalid(m_axis_tvalid),
.m_axis_tready(m_axis_tready),
.m_axis_tlast(m_axis_tlast),
.init_done(init_done),
.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;
// 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)
);
// s2mm_prmry_reset のインスタンス
reset_gen #(
.RESET_STATE(1'b1),
.RESET_TIME(1000) // 100nsec
) RESETi (
.reset_out(s2mm_prmry_reset)
);
// 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)
axi4s_slave_bfm #(
.C_M_AXIS_DATA_WIDTH(24),
.TREADY_RANDOM_WAIT(1) // m_axis_treadyにランダムなWaitを発生させる=1, Waitしない=0
) uut_slave (
.ACLK(s2mm_aclk),
.ARESETN(~s2mm_prmry_reset),
.m_axis_tdata(m_axis_tdata),
.m_axis_tstrb(m_axis_tstrb),
.m_axis_tvalid(m_axis_tvalid),
.m_axis_tready(m_axis_tready),
.m_axis_tlast(m_axis_tlast)
);
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
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
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 | - | - | - | - |