【JokerのZYNQ7020】DNA_PORT。

软件环境:vivado 2017.4        硬件平台:XC7Z020


说起FPGA端最常用、最直接的加密手段,大概就是利用每个芯片独有的ID号 + 加密算法了,所以今天这篇,就来简单提一下如何获取7系列的每个芯片的DNA号。至于为什么说是7系列,是为了与ultrascale的方法区别开,在ultrascale下,这个码是96 bit的,而在7系列及以前,是57 bit的。

第一种方法是利用JTAG。

【JokerのZYNQ7020】DNA_PORT。

 点击左侧的PROGRAM AND DEBUG后,利用JTAG连接板卡,在识别出的PL芯片型号上单击,再在下方点击Properties,属性中找到EFUSE,子项目中比较关心其中两个,一个是DNA_PORT,另一个是FUSE_DNA,接下来说下这两个的关系。

 1.Fuse_DNA 是 7 系列和 Zynq 设备中的 64 位唯一标识符;

2.DNA_PORT 是一个 57 位值,最多可与 32 个设备共享;

3.DNA_PORT [0:56] 与 FUSE_DNA [63:7] 对齐,注意括号里MSB和LSB方向,举例如下。

【JokerのZYNQ7020】DNA_PORT。

 接下来说一下怎么读,读取方法是利用DNA_PORT原语,参考手册UG470。

【JokerのZYNQ7020】DNA_PORT。

读取过程示意如下。

【JokerのZYNQ7020】DNA_PORT。

当READ = 1时,将FUSE 寄存器中的DNA值压入移位寄存器,而后将READ清0将SHIFT置1,DNA的值会依次从DOUT口移出,将DIN的值依次移入,最先从移位寄存器出来的是MSB,需要注意。

上代码。

module DNA_Port_read(
    
    input               sys_clk,
    input 				sys_rst_n
    
    //input dna_read_vio
);   
    wire                dna_read_vio;
	reg     [1:0]       dna_read_en;
	reg     [7:0]       dna_cnt;
	
    wire    [56:0]      dna_data;
    wire                dna_valid;

    reg     [56:0]      dna_reg;
    wire                dna_dout;
    wire                dna_read;
    wire                dna_shift;
    

    vio_0 vio_0_inst (
      .clk(sys_clk),                // input wire clk
      .probe_out0(dna_read_vio)  // output wire [0 : 0] probe_out0
    );
    
   DNA_PORT #(
      .SIM_DNA_VALUE(57'h1234567AABBCCDD)  // Specifies a sample 57-bit DNA value for simulation
   )
   DNA_PORT_inst (
      .DOUT(dna_dout),   // 1-bit output: DNA output data.
      .CLK(sys_clk),     // 1-bit input: Clock input.
      .DIN(1'b0),     // 1-bit input: User data input pin.
      .READ(dna_read),   // 1-bit input: Active high load DNA, active low read input.
      .SHIFT(dna_shift)  // 1-bit input: Active high shift enable input.
   );

    always@(posedge sys_clk)
    begin
		if(!sys_rst_n)
			dna_read_en <= 2'd0;
		else
			dna_read_en <= {dna_read_en[0:0],dna_read_vio};
    end
   
    reg [7:0] dna_cnt_state;
	always@(posedge sys_clk)
	begin
		if(!sys_rst_n)
		begin
			dna_cnt <= 8'd0;
			dna_cnt_state <= 8'd0;
		end	
		else
		begin
			case(dna_cnt_state)
			8'd0:begin
				if(dna_read_en == 2'b10)
					dna_cnt_state <= 8'd1;
			end
			8'd1:begin
				dna_cnt <= dna_cnt + 1'b1;
				if(dna_cnt == 8'd99)
					dna_cnt_state <= 8'd2;
			end
			8'd2:begin
				dna_cnt <= 8'd0;
				dna_cnt_state <= 8'd0;
			end
			endcase
		end
	end
	
    always @ (posedge sys_clk)
    begin
		if(!sys_rst_n)
		begin
			dna_reg[56:0] <= 57'd0;
		end
		else
		begin
			if(dna_shift)
				dna_reg[56:0] <= {dna_reg[55:0],dna_dout};
		end
    end	
		
    assign dna_read = (dna_cnt == 8'd1) ? 1'b1 : 1'b0;
    assign dna_shift = ((dna_cnt >= 8'd10) && (dna_cnt <= (8'd10 + 8'd57 - 8'd1))) ? 1'b1 : 1'b0;
	
	assign dna_data = dna_reg;
    assign dna_valid = (dna_cnt == 8'd99) ? 1'b1 : 1'b0;
    
    
    ila_0 ila_0
    (
        .clk(sys_clk),
        .probe0(dna_data),
        .probe1(dna_valid),
        .probe2(dna_dout),
        .probe3(dna_read),
        .probe4(dna_shift),
        .probe5(dna_reg),
        .probe6(dna_cnt),
        .probe7(dna_read_en)
    );  
   
endmodule

测试中使用vio来触发DNA_PORT的读取,再read信号置位后等待了10个clk,目的是确保DNA_PORT的值加载进了移位寄存器中(当然,这10个clk只是我测试用,不一定非要10个),而后shift拉高,将移位寄存器输出的MSB依次移位进dna_reg中,确保所有数据移出后,最后将valid拉个脉冲,整个读取过程结束。

上板测试结果如下。

【JokerのZYNQ7020】DNA_PORT。

上一篇:QWorld量子计算基础编程培训 10月15日 第一讲:经典系统的基础


下一篇:数位DP 补题