This chapter mainly implements the conversion of commands into the encoding method of 1 out of 4 in ISO1569, and realizes the PPM conversion of commands. Here we only briefly introduce the coding rules. 4 takes 1, 2bit encoding, low bit to high bit; b2b1, b4b3, b6b5, b8b7.
Based on this encoding method, 8-bit data PPM conversion is performed first. Observe the above encoding method,
00: first position;
01: The third position;
10: fifth position;
11: The seventh position.
There is a certain relationship between the position of the low level and the encoding. It is the value after adding a “1” after encoding; that is:
00: 001 = 1;
01: 011 = 3;
10: 101 = 5;
11: 111 = 7.
In addition, a start frame needs to be added before the command, and an end frame needs to be added after the command ends. Starting frame:
end frame:
In this way, PPM encoding is easy. What needs to be noted here is the duration of a low pulse (9.44us), and a cycle is the duration of 8 low pulses, that is, 8 pulses constitute a cycle. The entire process is implemented using a state machine. This module encodes in bytes. Each time one byte of data is input, it is updated when the 1byte data encoding is completed. It should be noted that the code involves two clocks, so when implemented using combinational logic, there are many additional flag bits. In fact, the code can be optimized later and one master clock can be used for counting distribution to achieve PPM encoding. The top-level module implementation will be given in the next chapter.
module nfc_tx_ppm #( parameter BYTE_CNT = 4 )( input rstn, //¤? input clk_system, input clk_ppm, //?¨9.44us input [BYTE_CNT:0] cnt, //?°?°é input datavaild, //?° input [7:0] crc, //?CRC?bit?° output reg byte_shift, //- output reg ppm_finish, //¤?é? output reg ppm_out //PPM ); localparam period = 8; //?§?8? parameter idle = 3'd0; //?é parameter start = 3'd1; //§?é? parameter start_cnt = 3'd2; //?é?SOL parameter shift = 3'd3; //?é° parameter finish = 3'd4; //§?é?§ parameter finish_cnt = 3'd5; //?§? reg [2:0]state; //? reg [2:0]next_state; //? reg [7:0]crc_temp; //?-?¨é?byte?° reg [3:0]period_cnt; //§ reg [2:0]pause_insert; // reg [BYTE_CNT:0]byte_cnt; //?-?° reg [BYTE_CNT:0]temp_cnt; reg [1:0]shift_cnt; reg shift_flag; reg flag_state; reg flag_start_cnt; reg flag_finish_cnt; reg data_vaild_temp; always @(posedge clk_system or negedge rstn) begin if(!rstn) data_vaild_temp <= 1'd0; else if(datavaild & amp; state == idle) data_vaild_temp <= 1'd1; else if(ppm_finish) data_vaild_temp <= 1'd0; end // always @(posedge clk_ppm or negedge rstn) begin if (!rstn)begin state <= idle; end else state <= next_state; end //é?° always @(*)begin case (state) idle :if(data_vaild_temp) next_state = start;else next_state = idle; //?° start :if(flag_start_cnt)next_state = start_cnt;else next_state = start; //?é?SOL?é start_cnt:if(flag_state) next_state = shift;else next_state = start_cnt; //?é? shift :if(byte_cnt == temp_cnt) next_state = finish;else next_state = shift; //?é° finish :if(flag_finish_cnt)next_state = finish_cnt;else next_state = finish_cnt; //?é?EOF finish_cnt:if(ppm_finish) next_state = idle;else next_state = finish_cnt; //¤?éé endcase end always @(posedge clk_ppm or negedge rstn) begin if(!rstn)begin ppm_out <= 1'd1; ppm_finish <= 1'd0; crc_temp <= 7'd0; period_cnt <= 4'd0; pause_insert <= 3'd0; byte_shift <= 1'd0; byte_cnt <= 0; shift_cnt <= 2'd0; shift_flag <= 1'd1; flag_state <= 1'd0; temp_cnt <= 0; flag_start_cnt <= 1'd0; flag_finish_cnt <= 1'd0; end else begin case (next_state) idle: begin ppm_out <= 1'd1; ppm_finish <= 1'd0; end //?é?é? start: begin period_cnt <= 4'd0; //?′?°?é° temp_cnt <= cnt; crc_temp <= {2'd0,crc[7:2]}; // pause_insert <= {crc[1:0],1'd1}; // ppm_out <= 1'd0; //SOL flag_start_cnt <= 1'd1; end start_cnt:begin ppm_out <= 1'd1; //SOL if(period_cnt == period/2) ppm_out <= 1'd0; else ppm_out <= 1'd1; if(period_cnt == period-1)begin //SOL period_cnt <= 4'd0; flag_state <= 1'd1; end else period_cnt <= period_cnt + 1; end shift:begin if(period_cnt == pause_insert-1) // ppm_out <= 1'd0; else ppm_out <= 1'd1; if(period_cnt == period-1) if(shift_cnt == 3)begin pause_insert <= {crc[1:0],1'd1}; crc_temp <= {2'd0,crc[7:2]}; byte_cnt <= byte_cnt + 1'd1; shift_cnt <= 2'd0; if(byte_cnt!=cnt-2) shift_flag <= 1'd1; else shift_flag <= 1'd0; period_cnt <= 4'd0; end else begin shift_cnt <= shift_cnt + 1'd1; period_cnt <= 4'd0; pause_insert <= {crc_temp[1:0],1'd1}; crc_temp <= {2'd0,crc_temp[7:2]}; end else period_cnt <= period_cnt + 1'd1; if (shift_flag)begin byte_shift <= 1'd1; shift_flag <= 1'd0; end else byte_shift <= 1'd0; end finish:begin shift_flag <= 1'd1; ppm_out <= 1'd1; period_cnt <= period_cnt + 1'd1; flag_finish_cnt <= 1'd1; end finish_cnt:begin flag_start_cnt <= 1'd0; flag_state <= 1'd0; byte_cnt <= 0; flag_finish_cnt <= 1'd0; period_cnt <= period_cnt + 1'd1; if(period_cnt == 1) ppm_out <= 1'd0; else ppm_out <= 1'd1; if (period_cnt == period/2-1) ppm_finish <= 1'd1; end default: ; endcase end end endmodule