Xilinx FPGA MIPI CSI-2 Transmitter Subsystem 仿真笔记

MIPI——Mobile Industry Processor Interface

DSI用于显示屏,CSI用于摄像头。在某些场合想用FPGA模拟摄像头,可以用Xilinx FPGA MIPI CSI-2 Transmitter Subsystem0。

MIPI协议,网上资料很多,此处不做赘述,此处仅对Xilinx FPGA MIPI CSI-2 Transmitter Subsystem做主要说明。


配置

MIPI CSI-2 Transmitter Subsystem这个IP核,内部包括MIPI D-PHY和MIPI CSI-2 TX Controller。

 此处配置接口为AXI4S,CSI lane选择1,输入像素数目为1,Line buffer深度为2048。

如果整个工程仅用一个接口,那么此处选择inlcude shared logic in core。

管脚根据你的硬件设计进行指定,此处数据管脚和时钟管脚,仅HP BANK可以用,绘制原理图之前需要提前看一下某些管脚是否可以用。


仿真验证

由于IP不自动example工程,所以自己搭建测试。

里面有个DATA_TYPE特别恶心,Xilinx的文档没提各个对应关系,让查MIPI官方文档,MIPI官方又要注册账号。

我这里产生图像是128*32的RGB888图像数据,用于仿真。

它的s_axis_tuser对应的Line number和Frame number可以设置为0,内核会自动匹配检测,但是后级MIPI接收端可能不知道图像的行场大小。

module tb_mipi_core  ; 
//------------------------------------------------------------ 
parameter C_M_AXI_ADDR_WIDTH = 8;


  reg    dphy_clk_200M   ; 
//s_axi
  wire    s_axi_awready   ; 
  wire    s_axi_awvalid   ; 
  wire  [C_M_AXI_ADDR_WIDTH-1:0]  s_axi_awaddr   ;  
  wire    s_axi_arready   ; 
  wire    s_axi_arvalid   ; 
  wire  [C_M_AXI_ADDR_WIDTH-1:0]  s_axi_araddr   ; 
  wire    s_axi_wready   ; 
  wire    s_axi_wvalid   ; 
  wire  [31:0]  s_axi_wdata   ; 
  wire  [3:0]  s_axi_wstrb   ; 
  wire    s_axi_rready   ; 
  wire    s_axi_rvalid   ; 
  wire  [31:0]  s_axi_rdata   ; 
  wire  [1:0]  s_axi_rresp   ; 
  wire    s_axi_bready   ; 
  wire    s_axi_bvalid   ; 
  wire  [1:0]  s_axi_bresp   ; 
  
  
//s_axis  
  reg    s_axis_aclk   ; 
  reg    s_axis_aresetn   ; 
  // reg    s_axis_tvalid   ; 
  wire    s_axis_tvalid   ; 
  wire    s_axis_tready   ; 
  reg  [47:0]  s_axis_tdata   ; 
  // reg    s_axis_tlast   ; 
  wire    s_axis_tlast   ; 
  // reg  [95:0]  s_axis_tuser   ; 
  wire  [95:0]  s_axis_tuser   ; 
  reg  [5:0]  s_axis_tkeep   ; 
  reg  [1:0]  s_axis_tdest   ; 
  
  wire    txclkesc_out   ; 
  wire    mmcm_lock_out   ; 
  wire    clkoutphy_out   ; 
  wire  [0:0]  mipi_phy_if_data_p   ; 
  wire  [0:0]  mipi_phy_if_data_n   ; 
  wire    mipi_phy_if_clk_p   ; 
  wire    mipi_phy_if_clk_n   ; 
  wire    txbyteclkhs   ; 
  wire    interrupt   ; 
  wire    system_rst_out   ;
  wire    pll_lock_out   ; 
  
  wire  s_axi_init_rdy;
  
//------------------------------------------------------------ 
initial  begin
dphy_clk_200M = 0;

s_axis_aresetn = 0;
s_axis_tdest = 0;

// s_axi_awvalid = 0;
// s_axi_wdata = 0;
// s_axi_arvalid = 0;
// s_axi_araddr = 0;
// s_axi_rready = 0  ; 
// s_axi_bready = 0  ; 
// s_axi_wstrb  = 0  ; 
// s_axi_awaddr = 0;
// s_axi_wvalid = 0  ; 

s_axis_aclk = 0;
s_axis_tdata = 0;
// s_axis_tlast = 0;
// s_axis_tuser = 0;
// s_axis_tvalid = 0;
s_axis_tkeep = 5'h1f;

#200;
s_axis_aresetn = 1;


end 

always #2.5   dphy_clk_200M = ~dphy_clk_200M;
always #5  s_axis_aclk = ~s_axis_aclk;

reg [10:0]  cnt_h = 0;
reg [10:0]  cnt_v = 0;

// 128*32
always @(posedge s_axis_aclk)
	if(s_axis_aresetn && s_axi_init_rdy==1)
	begin
		if(s_axis_tready)
			if(cnt_h==200)
				cnt_h <= 40;
			else
				cnt_h <= cnt_h + 1;
			
		if(cnt_h==200)
			if(cnt_v >= 31)
				cnt_v <= 0;
			else
				cnt_v <= cnt_v + 1;
	end
//----------------------------------------------------------------------------------

// assign s_axis_tvalid = 0;
assign s_axis_tvalid = (cnt_h >= 73) ? 1:0;
assign s_axis_tuser[0] = (cnt_v==0 && cnt_h==73)? 1 : 0 ;
assign s_axis_tlast = (cnt_h==200)? 1 : 0 ;
//-------------------------------------------------------
assign s_axis_tuser[95:64] = 0;  //reserved
assign s_axis_tuser[15:7] = 0;  //reserved

assign s_axis_tuser[63:48] = 128;  //Word count  ---- 128*32
assign s_axis_tuser[47:32] = 0;  //Line number
assign s_axis_tuser[31:16] = 0;  //Frame number
assign s_axis_tuser[6:1] = 6'h24;  //Data type  ---  RGB888
// s_axis_tuser[0] = 0;  //Frame start

always @(posedge s_axis_aclk)
	if(s_axis_tvalid && s_axis_tready) begin
		s_axis_tdata[41:34] <= s_axis_tdata[41:34] + 1;
		s_axis_tdata[27:20] <= s_axis_tdata[27:20] + 1;
		s_axis_tdata[13:6]  <= s_axis_tdata[13:6]  + 1;
	end
		
//------------------------------------------------------------
  mipi_csi2_tx_subsystem_0  
   DUT  ( 
       .s_axi_awready (s_axi_awready ) ,
      .s_axis_aresetn (s_axis_aresetn ) ,
      .txclkesc_out (txclkesc_out ) ,
      .mmcm_lock_out (mmcm_lock_out ) ,
      .s_axis_tdest (s_axis_tdest ) ,
      .clkoutphy_out (clkoutphy_out ) ,
      .mipi_phy_if_data_n (mipi_phy_if_data_n ) ,
      .mipi_phy_if_clk_n (mipi_phy_if_clk_n ) ,
      .s_axi_arready (s_axi_arready ) ,
//      .s_axi_arprot (0 ) ,
      .s_axi_awvalid (s_axi_awvalid ) ,
      .s_axis_tdata (s_axis_tdata ) ,
      .s_axi_wdata (s_axi_wdata ) ,
      .dphy_clk_200M (dphy_clk_200M ) ,
      .mipi_phy_if_data_p (mipi_phy_if_data_p ) ,
      .mipi_phy_if_clk_p (mipi_phy_if_clk_p ) ,
      .txbyteclkhs (txbyteclkhs ) ,
      .interrupt (interrupt ) ,
      .s_axis_tlast (s_axis_tlast ) ,
      .s_axi_arvalid (s_axi_arvalid ) ,
      .s_axis_tready (s_axis_tready ) ,
      .s_axi_rresp (s_axi_rresp ) ,
      .s_axi_bresp (s_axi_bresp ) ,
      .s_axi_wready (s_axi_wready ) ,
//      .s_axi_awprot (0 ) ,
      .s_axis_tuser (s_axis_tuser ) ,
      .s_axi_araddr (s_axi_araddr ) ,
      .s_axis_aclk (s_axis_aclk ) ,
      .s_axis_tvalid (s_axis_tvalid ) ,
      .s_axi_rready (s_axi_rready ) ,
      .s_axi_bready (s_axi_bready ) ,
      .s_axi_wvalid (s_axi_wvalid ) ,
      .system_rst_out (system_rst_out ) ,
      .s_axi_rvalid (s_axi_rvalid ) ,
      .s_axi_bvalid (s_axi_bvalid ) ,
      .s_axi_wstrb (s_axi_wstrb ) ,
      .s_axi_awaddr (s_axi_awaddr ) ,
      .s_axis_tkeep (s_axis_tkeep ) ,
      .s_axi_rdata (s_axi_rdata ) ,
      .pll_lock_out (pll_lock_out ) ); 
//-------------------------------------------------------------	  
//-------------------------------------------------------------	  
//-------------------------------------------------------------	   
axi_lite_sm  
	#(
	.C_M_AXI_ADDR_WIDTH (C_M_AXI_ADDR_WIDTH)
	)
lite_sm_u
   (
    // -- System Signals
    .s_axi_aclk (s_axis_aclk),
    .aresetn (s_axis_aresetn),

    // -- Master Interface Write Address
    .s_axi_awaddr (s_axi_awaddr),
    .s_axi_awvalid (s_axi_awvalid),
    .s_axi_awready (s_axi_awready),

    // -- Master Interface Write Data
    .s_axi_wdata (s_axi_wdata),
    .s_axi_wstrb (s_axi_wstrb),
    .s_axi_wvalid (s_axi_wvalid),
    .s_axi_wready (s_axi_wready),

    // -- Master Interface Write Response
    .s_axi_bresp (s_axi_bresp),
    .s_axi_bvalid (s_axi_bvalid),
    .s_axi_bready (s_axi_bready),

    // -- Master Interface Read Address
    .s_axi_araddr (s_axi_araddr),
    .s_axi_arvalid (s_axi_arvalid),
    .s_axi_arready (s_axi_arready),

    // -- Master Interface Read Data 
    .s_axi_rdata (s_axi_rdata),
    .s_axi_rresp (s_axi_rresp),
    .s_axi_rvalid (s_axi_rvalid),
    .s_axi_rready (s_axi_rready),
	
	.s_axi_init_rdy(s_axi_init_rdy)
    );

endmodule

原来以为不对其做任何配置,直接输入AXIS的数据,这个IP应该就能够正常运行,但是仿真发现其根本没有反应。所以后面通过AXI-LITE总线对其做寄存器配置。

根据手册说明,仅对配置寄存器(Core Configuration options)做配置就可以了。

register_write(0,32'h12);  //reset Controller
register_write(0,32'h11);  // Enables the core to receive and process packets

// wait Controller ready
		while(s_axi_rdata_r[2]==0)
		begin
			register_read(32'h0);
			repeat(10) @(posedge s_axi_aclk);
		end

//----
send AXIS stream data to core

根据手册说明,物理层默认初始化时间是1ms,等内核就绪后,发送AXIS数据流,它就应该能正常工作,但是观察输出的时钟和数据,始终不变化。并且内核AXIS接口在接收几包数据后,内核的ready信号一直为0,不能再继续接收数据。

并且输出的差分时钟和数据信号一直不变。

后面折腾半天,最终找到问题原因。

register_write(0,32'h12);  //reset Controller

// wait Controller ready
		while(s_axi_rdata_r[2]==0)
		begin
			register_read(32'h0);
			repeat(10) @(posedge s_axi_aclk);
		end

register_write(0,32'h11);  // Enables the core to receive and process packets

//----
send AXIS stream data to core

将之前代码顺序进行调整,仿真竟然通过。也就是在使能内核之前,必须先等内核就绪。

要在IDEA中安装Codeium插件,你可以按照以下步骤进行操作: 1. 打开IDEA,并进入Plugins页面。你可以在IDEA的设置(Settings)中找到Plugins选项。 2. 在Plugins页面中,选择Marketplace,并搜索Codeium插件。 3. 找到Codeium插件后,点击"install"进行安装。请确保选择个人用户版本,而不是企业版。 4. 安装完成后,在IDEA的右下角会出现Codeium的小图标,表示插件已经安装成功。 然而,安装过程中可能会遇到一些问题: - 坑1: 一直提示downloading language server。这是因为插件需要下载language server,但由于网络问题,下载速度可能很慢。在遇到这个问题时,你可以放置插件继续下载,等待下载完成即可。 -2: 提示需要登录(log in),但点击没有反应。在Jetbrains的问答中有一个解决方法。在注册Codeium账号后,你可以点击显示的链接获取Token,并将其复制到登录界面中,然后点击OK进行登录。 - 坑3: 提示中文乱码,但按下tab键后显示正常。这是一个字体问题,你可以在IDEA的设置(Settings)中的Editor->Font选项中将字体更改为"Microsoft YaHei UI"来解决这个问题。 总的来说,Codeium是一款免费的个人AI代码自动提示工具,可以提供最佳的代码补全和搜索功能。它支持40多种编程语言,并与你喜爱的IDE集成,具有快速和高质量的建议。安装Codeium插件需要先注册账户并授权,然后通过在IDEA中安装插件来使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Codeium在IDEA里的3个坑:无法log in,downloading language server和中文乱码](https://blog.csdn.net/zhtisi/article/details/130790718)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Codeium的使用](https://blog.csdn.net/weixin_44536462/article/details/130293462)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [idea - 插件之 codeium(安装篇)](https://blog.csdn.net/qq_38800175/article/details/131457912)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值