├── .gitignore ├── prng.v ├── crc5.v ├── two_dff_sync.v ├── LICENSE ├── fs_detector.v ├── rom_code.txt ├── crc16.v ├── rx.v ├── tx.v ├── cmd_buf.v ├── mem_if.v ├── README.md ├── miller_enc.v ├── fm0_enc.v ├── frmgen.v ├── bb_proc.v ├── bb_proc_syn.tcl ├── bb_proc_apr.tcl ├── crg.v ├── bb_proc_tb.v └── cmd_proc.v /.gitignore: -------------------------------------------------------------------------------- 1 | *.bak 2 | *.htm 3 | *.log 4 | *.swp 5 | *.vcd 6 | *BAK* 7 | -------------------------------------------------------------------------------- /prng.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Pseudo Random Number Generator 3 | * 4 | * One of the spec requirements is to maintain a 16-bit random number 5 | * PRNG is used for that in my design 6 | * 7 | * In this design, we chose the following polynimial to implement our PRNG 8 | * 1 + x^3 + x^4 + x^5 + x^16 9 | */ 10 | 11 | 12 | `timescale 1us / 1ns 13 | 14 | 15 | module prng 16 | ( 17 | output reg [15:0]prn, // pseudo random number 18 | input clk_prng, 19 | input rst_n 20 | ); 21 | 22 | 23 | always@(posedge clk_prng or negedge rst_n) begin 24 | if(~rst_n) prn <= 16'h2a6c; 25 | else begin 26 | prn[0] <= prn[15]; 27 | prn[1] <= prn[0]; 28 | prn[2] <= prn[1]; 29 | prn[3] <= prn[2] ^ prn[15]; 30 | prn[4] <= prn[3] ^ prn[15]; 31 | prn[5] <= prn[4] ^ prn[15]; 32 | prn[15:6] <= prn[14:5]; 33 | end 34 | end 35 | 36 | 37 | endmodule 38 | -------------------------------------------------------------------------------- /crc5.v: -------------------------------------------------------------------------------- 1 | /* 2 | * CRC-5 Encoder/Decoder 3 | * 4 | * Calculation of 5-bit cyclic redundancy checks 5 | * 6 | * For more detailed information about CRC-5 for EPC Gen2, refer to annex F of the protocol 7 | */ 8 | 9 | 10 | `timescale 1us / 1ns 11 | 12 | 13 | module crc5 14 | ( 15 | output crc5_check_pass, 16 | input clk_crc5, 17 | input rst_for_new_package, 18 | input data, 19 | input sync, 20 | input package_complete 21 | ); 22 | 23 | 24 | reg [4:0]reg_crc; 25 | 26 | 27 | assign crc5_check_pass = ~(|reg_crc); 28 | 29 | 30 | always@(posedge clk_crc5 or negedge rst_for_new_package) begin 31 | if(~rst_for_new_package) reg_crc <= 5'b01001; 32 | else if(sync & ~package_complete) begin 33 | reg_crc[4] <= reg_crc[3]; 34 | reg_crc[3] <= reg_crc[2] ^ (data ^ reg_crc[4]); 35 | reg_crc[2] <= reg_crc[1]; 36 | reg_crc[1] <= reg_crc[0]; 37 | reg_crc[0] <= data ^ reg_crc[4]; 38 | end 39 | end 40 | 41 | 42 | endmodule 43 | -------------------------------------------------------------------------------- /two_dff_sync.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Synchronizer 3 | * 4 | * Architechture of conventional two flip-flop 5 | * 6 | * There are two clock domain in this baseband processor 7 | * one is in backscatter link frequency, another is delayed PIE code for decoding received PIE code 8 | * 9 | * Have synchronizer to avoid metastable 10 | */ 11 | 12 | 13 | `timescale 1us / 1ns 14 | 15 | 16 | module two_dff_sync 17 | ( 18 | output data_out, 19 | input clk_ad, // clock in A domain 20 | input clk_bd, // clock in B domain 21 | input rst_n, 22 | input data_in 23 | ); 24 | 25 | 26 | reg qa; 27 | reg qb_1; 28 | reg qb_2; 29 | 30 | 31 | assign data_out = qb_2; 32 | 33 | always@(posedge clk_ad or negedge rst_n) begin 34 | if(~rst_n) qa <= 1'b0; 35 | else qa <= data_in; 36 | end 37 | 38 | always@(posedge clk_bd or negedge rst_n) begin 39 | if(~rst_n) qb_1 <= 1'b0; 40 | else qb_1 <= qa; 41 | end 42 | 43 | always@(posedge clk_bd or negedge rst_n) begin 44 | if(~rst_n) qb_2 <= 1'b0; 45 | else qb_2 <= qb_1; 46 | end 47 | 48 | 49 | endmodule 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Gurint 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /fs_detector.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Frame-Sync Detector 3 | * 4 | * Every package sent from Reader must have Frame-Sync 5 | * 6 | * This module determine if Tag receive valid Frame-Sync 7 | * and send sync to enable other RX module 8 | */ 9 | 10 | 11 | `timescale 1us / 1ns 12 | 13 | 14 | module fs_detector 15 | ( 16 | output reg sync, // if sync is high, means that receiving the valid Frame-Sync 17 | input pie_code, 18 | input clk_fsd, 19 | input rst_n, 20 | input package_complete 21 | ); 22 | 23 | 24 | parameter idle = 2'b00; 25 | parameter got0 = 2'b01; // got valid Frame-Sync 26 | parameter got1 = 2'b10; 27 | 28 | 29 | reg [1:0]ps; 30 | reg [1:0]ns; 31 | 32 | 33 | always@(posedge clk_fsd or negedge rst_n) begin 34 | if(~rst_n) ps <= idle; 35 | else ps <= ns; 36 | end 37 | 38 | always@(*) begin 39 | case(ps) 40 | idle : if(~pie_code) ns = got0; 41 | else ns = idle; 42 | got0 : if(~pie_code) ns = got0; 43 | else ns = got1; 44 | got1 : if(package_complete) ns = idle; 45 | else ns = got1; 46 | default : ns = idle; 47 | endcase 48 | end 49 | 50 | always@(*) begin 51 | case(ps) 52 | idle : sync = 1'b0; 53 | got0 : sync = 1'b0; 54 | got1 : sync = 1'b1; 55 | default : sync = 1'b0; 56 | endcase 57 | end 58 | 59 | 60 | endmodule 61 | -------------------------------------------------------------------------------- /rom_code.txt: -------------------------------------------------------------------------------- 1 | 1101001101010111 2 | 0000011011001100 3 | 0000000000000000 4 | 0000000000000000 5 | 0101001101001110 6 | 0110000000000000 7 | 1011001001000111 8 | 0001011101010101 9 | 1001010010011110 10 | 1111110001010011 11 | 1011010000011101 12 | 0101010110110101 13 | 1100110011001100 14 | 1000111110100111 15 | 1010101000111100 16 | 0000111101011100 17 | 0111000101001000 18 | 1010100101110011 19 | 0000000000000000 20 | 0000000000000000 21 | 0000000000000000 22 | 0000000000000000 23 | 0000000000000000 24 | 0000000000000000 25 | 0000000000000000 26 | 0000000000000000 27 | 0000000000000000 28 | 0000000000000000 29 | 0000000000000000 30 | 0000000000000000 31 | 0000000000000000 32 | 0000000000000000 33 | 0000000000000000 34 | 0000000000000000 35 | 0000000000000000 36 | 0000000000000000 37 | 0000000000000000 38 | 0000000000000000 39 | 0000000000000000 40 | 1000010101111010 41 | 0111111110100011 42 | 0000000000000000 43 | 0000000000000000 44 | 0000000000000000 45 | 0000000000000000 46 | 0000000000000000 47 | 0000000000000000 48 | 0000000000000000 49 | 0000000000000000 50 | 0000000000000000 51 | 0000000000000000 52 | 0000000000000000 53 | 0000000000000000 54 | 0000000000000000 55 | 0000000000000000 56 | 0000000000000000 57 | 0000000000000000 58 | 0000000000000000 59 | 0000000000000000 60 | 0000000000000000 61 | 0000000000000000 62 | 0000000000000000 63 | 0000000000000000 64 | 0000000000000000 65 | -------------------------------------------------------------------------------- /crc16.v: -------------------------------------------------------------------------------- 1 | /* 2 | * CRC-16 Encoder/Decoder 3 | * 4 | * Calculation of 16-bit cyclic redundancy checks 5 | * 6 | * For more detailed information about CRC-16 for EPC Gen2, refer to annex F of the protocol 7 | */ 8 | 9 | 10 | `timescale 1us / 1ns 11 | 12 | 13 | module crc16 14 | ( 15 | output reg crc16_check_pass_reg, 16 | output [15:0]crc_16, 17 | input clk_crc16, 18 | input rst_crc16, 19 | input data, 20 | input reply_data, 21 | input sync, 22 | input package_complete, 23 | input en_crc16_for_rpy 24 | ); 25 | 26 | 27 | wire d_in; 28 | 29 | reg crc16_check_pass; 30 | reg [15:0]reg_crc; 31 | 32 | 33 | assign d_in = en_crc16_for_rpy? reply_data : data; 34 | 35 | assign crc_16 = ~reg_crc; 36 | 37 | 38 | always@(*) begin 39 | if(reg_crc == 16'h1d0f) crc16_check_pass = 1'b1; 40 | else crc16_check_pass = 1'b0; 41 | end 42 | 43 | 44 | always@(posedge clk_crc16 or negedge rst_crc16) begin 45 | if(~rst_crc16) crc16_check_pass_reg <= 1'b0; 46 | else if(package_complete) crc16_check_pass_reg <= crc16_check_pass; 47 | end 48 | 49 | 50 | always@(posedge clk_crc16 or negedge rst_crc16) begin 51 | if(~rst_crc16) reg_crc <= 16'hffff; 52 | else if(sync | en_crc16_for_rpy) begin 53 | reg_crc[15] <= reg_crc[14]; 54 | reg_crc[14] <= reg_crc[13]; 55 | reg_crc[13] <= reg_crc[12]; 56 | reg_crc[12] <= reg_crc[11] ^ (d_in ^ reg_crc[15]); 57 | reg_crc[11] <= reg_crc[10]; 58 | reg_crc[10] <= reg_crc[9]; 59 | reg_crc[9] <= reg_crc[8]; 60 | reg_crc[8] <= reg_crc[7]; 61 | reg_crc[7] <= reg_crc[6]; 62 | reg_crc[6] <= reg_crc[5]; 63 | reg_crc[5] <= reg_crc[4] ^ (d_in ^ reg_crc[15]); 64 | reg_crc[4] <= reg_crc[3]; 65 | reg_crc[3] <= reg_crc[2]; 66 | reg_crc[2] <= reg_crc[1]; 67 | reg_crc[1] <= reg_crc[0]; 68 | reg_crc[0] <= d_in ^ reg_crc[15]; 69 | end 70 | end 71 | 72 | 73 | endmodule 74 | -------------------------------------------------------------------------------- /rx.v: -------------------------------------------------------------------------------- 1 | /* 2 | * RX (Receive) 3 | * 4 | * Including Frame-Sync Detector, CRC-5, CRC-16, Command Buffer 5 | * 6 | * The clock signal in RX is delayed PIE code from Analog front-end circuit 7 | * so we can directly transfer to binary code by clocking PIE code without decoder 8 | */ 9 | 10 | 11 | `timescale 1us / 1ns 12 | 13 | 14 | module rx 15 | ( 16 | output [7:0]cmd, 17 | output [51:0]param, 18 | output package_complete, 19 | output crc_check_pass, 20 | output [15:0]crc_16, 21 | output en_crc5, 22 | output en_crc16, 23 | input pie_code, 24 | input clk_dpie, 25 | input clk_crc5, 26 | input clk_crc16, 27 | input rst_n, 28 | input rst_for_new_package, 29 | input rst_crc16, 30 | input reply_data, 31 | input en_crc16_for_rpy 32 | ); 33 | 34 | 35 | fs_detector fs_detector_1 36 | ( 37 | .sync(sync), 38 | .pie_code(pie_code), 39 | .clk_fsd(clk_dpie), 40 | .rst_n(rst_n), 41 | .package_complete(package_complete) 42 | ); 43 | 44 | 45 | crc5 crc5_1 46 | ( 47 | .crc5_check_pass(crc5_check_pass), 48 | .clk_crc5(clk_crc5), 49 | .rst_for_new_package(rst_for_new_package), 50 | .data(pie_code), 51 | .sync(sync), 52 | .package_complete(package_complete) 53 | ); 54 | 55 | 56 | crc16 crc16_1 57 | ( 58 | .crc16_check_pass_reg(crc16_check_pass_reg), 59 | .crc_16(crc_16), 60 | .clk_crc16(clk_crc16), 61 | .rst_crc16(rst_crc16), 62 | .data(pie_code), 63 | .reply_data(reply_data), 64 | .sync(sync), 65 | .package_complete(package_complete), 66 | .en_crc16_for_rpy(en_crc16_for_rpy) 67 | ); 68 | 69 | 70 | cmd_buf cmd_buf_1 71 | ( 72 | .cmd(cmd), 73 | .param(param), 74 | .package_complete(package_complete), 75 | .en_crc5(en_crc5), 76 | .en_crc16(en_crc16), 77 | .clk_cmd(clk_dpie), 78 | .rst_for_new_package(rst_for_new_package), 79 | .bits_in(pie_code), 80 | .sync(sync) 81 | ); 82 | 83 | 84 | assign crc_check_pass = crc5_check_pass | crc16_check_pass_reg; 85 | 86 | 87 | endmodule 88 | -------------------------------------------------------------------------------- /tx.v: -------------------------------------------------------------------------------- 1 | /* 2 | * TX (Transmit) 3 | * 4 | * Including Frame Generator, FM0 Encoder, Miller Encoder 5 | * 6 | * bs_data is connected to Gate of NMOS in BACKSCATTER circuit which is the part of Analog front-end circuit 7 | */ 8 | 9 | 10 | `timescale 1us / 1ns 11 | 12 | 13 | module tx 14 | ( 15 | output bs_data, 16 | output pre_p_complete, 17 | output p_complete, 18 | output bs_complete, 19 | input clk_blf, 20 | input clk_frm, 21 | input clk_fm0, 22 | input clk_mil, 23 | input rst_for_new_package, 24 | input reply_data, 25 | input [15:0]crc_16, 26 | input [1:0]m, 27 | input trext, 28 | input reply_complete, 29 | input en_crc16_for_rpy, 30 | input start_working 31 | ); 32 | 33 | 34 | frmgen frmgen_1 35 | ( 36 | .send_data(send_data), 37 | .en_fm0(en_fm0), 38 | .st_enc(st_enc), 39 | .pre_p_complete(pre_p_complete), 40 | .p_complete(p_complete), 41 | .fg_complete(fg_complete), 42 | .clk_frm(clk_frm), 43 | .rst_for_new_package(rst_for_new_package), 44 | .reply_data(reply_data), 45 | .crc_16(crc_16), 46 | .m(m), 47 | .trext(trext), 48 | .reply_complete(reply_complete), 49 | .en_crc16_for_rpy(en_crc16_for_rpy) 50 | ); 51 | 52 | 53 | fm0_enc fm0_enc_1 54 | ( 55 | .fm0_data(fm0_data), 56 | .fm0_complete(fm0_complete), 57 | .clk_fm0(clk_fm0), 58 | .rst_for_new_package(rst_for_new_package), 59 | .send_data(send_data), 60 | .en_fm0(en_fm0), 61 | .trext(trext), 62 | .st_enc(st_enc), 63 | .fg_complete(fg_complete) 64 | ); 65 | 66 | 67 | miller_enc miller_enc_1 68 | ( 69 | .miller_data(miller_data), 70 | .mil_complete(mil_complete), 71 | .clk_mil(clk_mil), 72 | .rst_for_new_package(rst_for_new_package), 73 | .clk_blf(clk_blf), 74 | .send_data(send_data), 75 | .en_fm0(en_fm0), 76 | .trext(trext), 77 | .st_enc(st_enc), 78 | .fg_complete(fg_complete) 79 | ); 80 | 81 | 82 | // --- Backscattered Data --- 83 | assign bs_data = (start_working)? fm0_data | miller_data : 1'b0; 84 | 85 | 86 | assign bs_complete = fm0_complete | mil_complete; 87 | 88 | 89 | endmodule 90 | -------------------------------------------------------------------------------- /cmd_buf.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Command Buffer 3 | * 4 | * Serial input to parallel output 5 | * 6 | * Check correctness of the received command 7 | * 8 | * Enable/Disable CRC-5 and CRC-16 Encoder/Decoder 9 | * 10 | * Enable to processing the command if the received command is valid 11 | * 12 | * This design of baseband processor is improved by TSMC 0.18 um CMOS standard process 13 | * it does not support EEPROM, so we chose ROM to be the baseband processor's memory 14 | * because we use ROM to be the memory, we are not able to verify the Write command 15 | */ 16 | 17 | 18 | `timescale 1us / 1ns 19 | 20 | 21 | module cmd_buf 22 | ( 23 | output reg [7:0]cmd, 24 | output [51:0]param, 25 | output package_complete, 26 | output en_crc5, 27 | output en_crc16, 28 | input clk_cmd, 29 | input rst_for_new_package, 30 | input bits_in, 31 | input sync 32 | ); 33 | 34 | 35 | // --- mandatory command of EPC Gen2 protocol --- 36 | parameter QueryRep = 8'b0000_1100; 37 | parameter ACK = 8'b0000_1101; 38 | parameter Query = 8'b0011_1000; 39 | parameter QueryAdjust = 8'b0011_1001; 40 | parameter Select = 8'b0011_1010; 41 | parameter NAK = 8'b1100_0000; 42 | parameter Req_RN = 8'b1100_0001; 43 | parameter Read = 8'b1100_0010; 44 | //parameter Write = 8'b1100_0011; 45 | parameter Kill = 8'b1100_0100; 46 | parameter Lock = 8'b1100_0101; 47 | 48 | 49 | reg cmd_complete; 50 | reg [52:0]param_tmp; 51 | 52 | 53 | assign param = param_tmp[51:0]; 54 | 55 | assign en_crc5 = (cmd_complete & cmd != Query)? 1'b0 : 1'b1; 56 | 57 | assign en_crc16 = (cmd_complete & cmd != Select & cmd != Req_RN & cmd != Read & cmd != Kill & cmd != Lock)? 1'b0 : 1'b1; 58 | 59 | assign package_complete = (cmd == QueryRep & param_tmp[2])? 1'b1 : 60 | (cmd == ACK & param_tmp[16])? 1'b1 : 61 | (cmd == Query & param_tmp[18])? 1'b1 : 62 | (cmd == QueryAdjust & param_tmp[5])? 1'b1 : 63 | (cmd == Select & param_tmp[52])? 1'b1 : 64 | (cmd == NAK)? 1'b1 : 65 | (cmd == Req_RN & param_tmp[32])? 1'b1 : 66 | (cmd == Read & param_tmp[50])? 1'b1 : 67 | (cmd == Kill & param_tmp[51])? 1'b1 : 68 | (cmd == Lock & param_tmp[52])? 1'b1 : 1'b0; 69 | 70 | 71 | always@(*) begin 72 | if(cmd == QueryRep | cmd == ACK | cmd == Query | 73 | cmd == QueryAdjust | cmd == Select | cmd == NAK | 74 | cmd == Req_RN | cmd == Read | cmd == Kill | cmd == Lock) cmd_complete = 1'b1; 75 | else cmd_complete = 1'b0; 76 | end 77 | 78 | 79 | always@(posedge clk_cmd or negedge rst_for_new_package) begin 80 | if(~rst_for_new_package) cmd <= 8'b0000_0011; 81 | else begin 82 | if(sync & ~cmd_complete) cmd <= {cmd[6:0], bits_in}; 83 | end 84 | end 85 | 86 | 87 | always@(posedge clk_cmd or negedge rst_for_new_package) begin 88 | if(~rst_for_new_package) param_tmp <= 53'b1; 89 | else begin 90 | if(cmd_complete & ~package_complete) param_tmp <= {param_tmp[51:0], bits_in}; 91 | end 92 | end 93 | 94 | 95 | endmodule 96 | -------------------------------------------------------------------------------- /mem_if.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Memory Interface 3 | * 4 | * Our memory is a ROM with 64 words, 16 bits per word 5 | * can satisfy the spec of MemBank in EPC Gen2 Protocol 6 | * 7 | * We can't provide our ROM verilog module 8 | * because it's generated by Artisan Components, Inc. 9 | * and it's CONFIDENTIAL and PROPRIETARY SOFTWARE OF ARTISAN COMPONENTS, INC. 10 | * 11 | * You can design a 64x16 register file to verify this module 12 | */ 13 | 14 | 15 | `timescale 1us / 1ns 16 | 17 | 18 | module mem_if 19 | ( 20 | output reg rd_data, 21 | output reg rd_complete, 22 | output reg [5:0]A, 23 | output CEN, 24 | input [18:0]addr, 25 | input [15:0]Q, 26 | input clk_if, 27 | input rst_for_new_package 28 | ); 29 | 30 | 31 | wire clk_if_n; 32 | 33 | reg d_1clk; 34 | reg d_flag; 35 | reg [3:0]d_cnt; 36 | reg [5:0]A_cnt; 37 | 38 | 39 | assign CEN = (addr == 19'h0)? 1'b1 : 1'b0; 40 | 41 | assign clk_if_n = ~clk_if; 42 | 43 | always@(posedge clk_if or negedge rst_for_new_package) begin 44 | if(~rst_for_new_package) rd_data <= 1'b0; 45 | else rd_data <= Q[d_cnt]; 46 | end 47 | 48 | always@(*) begin 49 | if(~addr[18]) begin 50 | if(addr[15:8] == 8'b0000_0000) A = 6'h5 + A_cnt; 51 | else A = 6'h11 - {2'b0, addr[15:12]} + A_cnt; 52 | end 53 | else begin 54 | case(addr[17:16]) 55 | 2'b00 : A = addr[15:8] + A_cnt; 56 | 2'b01 : A = addr[15:8] + 6'h4 + A_cnt; 57 | 2'b10 : A = addr[15:8] + 6'h27 + A_cnt; 58 | 2'b11 : A = 6'h29; 59 | endcase 60 | end 61 | end 62 | 63 | always@(posedge clk_if_n or negedge rst_for_new_package) begin 64 | if(~rst_for_new_package) A_cnt <= 6'h0; 65 | else if(d_cnt == 4'h0) A_cnt <= A_cnt + 6'h1; 66 | end 67 | 68 | always@(posedge clk_if or negedge rst_for_new_package) begin 69 | if(~rst_for_new_package) d_1clk <= 1'b0; 70 | else d_1clk <= 1'b1; 71 | end 72 | 73 | always@(posedge clk_if or negedge rst_for_new_package) begin 74 | if(~rst_for_new_package) d_flag <= 1'b0; 75 | else if(~addr[18] & addr[15:8] != 8'h0) d_flag <= 1'b1; 76 | end 77 | 78 | always@(posedge clk_if or negedge rst_for_new_package) begin 79 | if(~rst_for_new_package) d_cnt <= 4'hf; 80 | else begin 81 | if(~addr[18] & addr[15:8] != 8'h0 & ~d_flag) d_cnt <= addr[11:8]; 82 | else if(d_1clk) d_cnt <= d_cnt - 4'h1; 83 | end 84 | end 85 | 86 | always@(posedge clk_if or negedge rst_for_new_package) begin 87 | if(~rst_for_new_package) rd_complete <= 1'b0; 88 | else begin 89 | if(~addr[18]) begin 90 | if(A == 6'h12) rd_complete <= 1'b1; 91 | end 92 | else begin 93 | if(addr[17:16] == 2'b00 & addr[7:0] == 8'h0 & addr[15:8] < 8'h4 & A == 6'h4) rd_complete <= 1'b1; 94 | else if(addr[17:16] == 2'b01 & addr[7:0] == 8'h0 & addr[15:8] < 8'he & A == 6'h12) rd_complete <= 1'b1; 95 | else if(addr[17:16] == 2'b01 & addr[7:0] == 8'h0 & addr[15:8] > 8'hd & addr[15:8] < 8'h23 & A == 6'h27) rd_complete <= 1'b1; 96 | else if(addr[17:16] == 2'b10 & addr[7:0] == 8'h0 & addr[15:8] < 8'h2 & A == 6'h29) rd_complete <= 1'b1; 97 | else if(addr[7:0] != 0 & A_cnt == addr[7:0]) rd_complete <= 1'b1; 98 | end 99 | end 100 | end 101 | 102 | 103 | endmodule 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EPC Gen-2 RFID Tag Baseband Processor 2 | 3 | EPC Radio-Frequency Identity Protocols Generation-2 UHF RFID : 4 | http://www.gs1.org/sites/default/files/docs/epc/Gen2_Protocol_Standard.pdf 5 | 6 | GitHub repository : 7 | https://github.com/Gurint/EPC-Gen2-RFID-Tag-Baseband-Processor 8 | 9 | 10 | ## Introduction 11 | A low-cost low-power baseband processor for EPC Gen-2 UHF RFID Tag 12 | - operated in the lowest frequency (see FM0 and Miller Encoder/Decoder) 13 | - clock gating 14 | - operand isolation 15 | - need a memory (in my case, I use a ROM) 16 | - Verilog language 17 | - synthesized by Synopsys Design Compiler 18 | - apr by Synopsys IC Compiler 19 | - implemented by TSMC 0.18 um CMOS standard process 20 | 21 | 22 | ## Modules 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
NAME DESCRIPTION
bb_proc baseband processor, top module
cmd_buf command buffer, serial to parallel
cmd_proc command processor, processes received commands
crc16 CRC-16 encoder/decoder
crc5 CRC-5 encoder/decoder
crg clock/reset generator, timing control
fm0_enc FM0 Encoder, operates in the lowest freq.
frmgen frame generator, generates preamble, backscattered data, end-of-signaling
fs_detector frame-sync detector
mem_if memory interface
miller_enc Miller encoder, operates in the lowest freq.
prng 16-bit Pseudorandom number generator
rx Receive
two_dff_sync Synchronizer, synchronizes signals from clock domain A to B
tx Transmit
73 | 74 | 75 | ## Test Bench 76 | bb_proc_tb : an example of the communication between a Reader and a single Tag 77 | 78 | 79 | ## Scripts 80 | bb_proc_syn : for synthesis 81 | bb_proc_apr : for apr 82 | 83 | 84 | ## ROM Code File 85 | rom_code : 64x16, 64 words and 16 bits per word 86 | 87 | ## Notes 88 | This design is implemented by TSMC 0.18 um CMOS standard process. 89 | It's not able to manufacture EEPROM, so I use a ROM to be processor's memory. 90 | That makes I can't verify Write command. 91 | I am not able to provide ROM's verilog file because of confidentiality. 92 | It's generated by memory compiler of Artisan Components, Inc. 93 | Anyone wanting to use this baseband processor should make your own memory. 94 | For simply test, you can write a register file. 95 | For tapeout, I suggest you generating a EEPROM. 96 | 97 | 98 | ## Author 99 | Ian Chuang 100 | ianchuang0212@gmail.com 101 | https://github.com/Gurint 102 | 103 | 104 | ## License 105 | The EPC-Gen2-RFID-Tag-Baseband-Processor repository source code is licensed under the MIT license. 106 | See [LICENSE](https://github.com/Gurint/EPC-Gen2-RFID-Tag-Baseband-Processor/blob/master/LICENSE) for MIT copyright terms. 107 | -------------------------------------------------------------------------------- /miller_enc.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Miller Encoder 3 | * 4 | * By our algorithm, Miller Encoder can operate in the lowest frequency 5 | * to save the power dissipation 6 | * 7 | * This algorithm is also applied to FMo Encoder 8 | * 9 | * If enable Miller Encoder, disable FM0 Encoder and vice versa 10 | */ 11 | 12 | 13 | `timescale 1us / 1ns 14 | 15 | 16 | module miller_enc 17 | ( 18 | output miller_data, 19 | output mil_complete, 20 | input clk_mil, 21 | input rst_for_new_package, 22 | input clk_blf, 23 | input send_data, 24 | input en_fm0, // if en_fm0 = 0, enable miller encoder 25 | input trext, 26 | input st_enc, 27 | input fg_complete 28 | ); 29 | 30 | 31 | parameter GetData = 2'b00; 32 | parameter DataP = 2'b01; 33 | parameter DataN = 2'b10; 34 | 35 | 36 | reg [1:0]ps; 37 | reg [1:0]ns; 38 | 39 | wire clk_blf_n; 40 | wire en_mil_out; 41 | wire m2o; 42 | wire mp_complete; 43 | wire me_start; 44 | 45 | reg [5:0]mp_end; 46 | reg [5:0]mp_cnt; 47 | reg m_cnt; 48 | reg m1o; 49 | reg [1:0]data_select; 50 | reg [1:0]fg_comp_cnt; 51 | 52 | 53 | assign clk_blf_n = ~clk_blf; 54 | 55 | assign en_mil_out = (mp_cnt > 6'h0)? 1'b1 : 1'b0; 56 | 57 | assign miller_data = (en_mil_out & ~mil_complete)? m2o : 1'b0; 58 | 59 | assign m2o = mp_complete? m1o : clk_blf; 60 | 61 | assign mp_complete = (mp_cnt == mp_end)? 1'b1 : 1'b0; 62 | 63 | assign me_start = (mp_cnt > mp_end - 6'h2)? 1'b1 : 1'b0; 64 | 65 | always@(*) begin 66 | if(~trext) mp_end = 6'h9; 67 | else mp_end = 6'h21; 68 | end 69 | 70 | always@(posedge clk_mil or negedge rst_for_new_package) begin 71 | if(~rst_for_new_package) mp_cnt <= 6'h0; 72 | else begin 73 | if(mp_cnt == mp_end) mp_cnt <= mp_cnt; 74 | else if(~en_fm0 & st_enc) mp_cnt <= mp_cnt + 6'h1; 75 | end 76 | end 77 | 78 | always@(posedge clk_mil or negedge rst_for_new_package) begin 79 | if(~rst_for_new_package) m_cnt <= 1'b0; 80 | else if(me_start) m_cnt <= m_cnt + 1'b1; 81 | end 82 | 83 | always@(posedge clk_mil or negedge rst_for_new_package) begin 84 | if(~rst_for_new_package) ps <= GetData; 85 | else if(st_enc) ps <= ns; 86 | end 87 | 88 | always@(*) begin 89 | case(ps) 90 | GetData : if(~en_fm0 & me_start) ns = DataP; 91 | else ns = GetData; 92 | DataP : if(~send_data) ns = DataP; 93 | else begin 94 | if(~m_cnt) ns = DataP; 95 | else ns = DataN; 96 | end 97 | DataN : if(~send_data) ns = DataN; 98 | else begin 99 | if(~m_cnt) ns = DataN; 100 | else ns = DataP; 101 | end 102 | default : ns = GetData; 103 | endcase 104 | end 105 | 106 | always@(*) begin 107 | case(ps) 108 | GetData : data_select = 2'h0; 109 | DataP : data_select = 2'h1; 110 | DataN : data_select = 2'h2; 111 | default : data_select = 2'h0; 112 | endcase 113 | end 114 | 115 | always@(*) begin 116 | case(data_select) 117 | 2'h0 : m1o = 1'b0; 118 | 2'h1 : m1o = clk_blf; 119 | 2'h2 : m1o = clk_blf_n; 120 | default : m1o = 1'b0; 121 | endcase 122 | end 123 | 124 | always@(posedge clk_mil or negedge rst_for_new_package) begin 125 | if(~rst_for_new_package) fg_comp_cnt <= 2'b0; 126 | else begin 127 | if(fg_comp_cnt == 2'b11) fg_comp_cnt <= fg_comp_cnt; 128 | else if(~en_fm0 & fg_complete) fg_comp_cnt <= fg_comp_cnt + 2'b1; 129 | end 130 | end 131 | 132 | assign mil_complete = (fg_comp_cnt == 2'b11)? 1'b1 : 1'b0; 133 | 134 | 135 | endmodule 136 | -------------------------------------------------------------------------------- /fm0_enc.v: -------------------------------------------------------------------------------- 1 | /* 2 | * FM0 Encoder 3 | * 4 | * By our algorithm, FM0 Encoder can operate in the lowest frequency 5 | * 6 | * The common way to encode FM0 is using clock in double BLF to determine the output sigal of each period 7 | * Our Algorithm does not use the double-BLF clock, it only needs the clock in BLF 8 | * 9 | * The same concept is applied to design Miller Encoder 10 | * The lowest operation frequency makes the Encoding save power dissipation 11 | * 12 | * If enable FM0 Encoder, disable Miller Encoder and vice versa 13 | */ 14 | 15 | 16 | `timescale 1us / 1ns 17 | 18 | 19 | module fm0_enc 20 | ( 21 | output fm0_data, 22 | output fm0_complete, 23 | input clk_fm0, 24 | input rst_for_new_package, 25 | input send_data, 26 | input en_fm0, 27 | input trext, 28 | input st_enc, 29 | input fg_complete 30 | ); 31 | 32 | 33 | parameter GetData = 3'b000; 34 | parameter Data0p = 3'b001; 35 | parameter Data0n = 3'b010; 36 | parameter Data1p = 3'b011; 37 | parameter Data1n = 3'b100; 38 | 39 | 40 | reg [2:0]ps; // present state 41 | reg [2:0]ns; // next state 42 | 43 | wire clk_fm0_n; 44 | wire en_vcnt; // enable V counter 45 | wire start_enc; // start FM0 encoding 46 | wire send_v; // send V 47 | wire m2o; // output of MUX 2 48 | 49 | reg [1:0]data_select; 50 | reg m1o; // output of MUX 1 51 | reg [4:0]v_cnt; // V coumter 52 | reg [1:0]fg_comp_cnt; 53 | 54 | 55 | assign clk_fm0_n = ~clk_fm0; 56 | 57 | assign start_enc = (ps != GetData)? 1'b1 : 1'b0; 58 | 59 | assign en_vcnt = (start_enc & (v_cnt != 5'h11))? 1'b1 : 1'b0; 60 | 61 | assign send_v = (~trext & (v_cnt == 5'h04))? 1'b1 : 62 | (trext & (v_cnt == 5'h10))? 1'b1 : 1'b0; 63 | 64 | assign m2o = send_v? 1'b0 : m1o; 65 | 66 | assign fm0_data = (en_fm0 & ~fm0_complete)? m2o : 1'b0; 67 | 68 | 69 | always@(posedge clk_fm0 or negedge rst_for_new_package) begin 70 | if(~rst_for_new_package) ps <= GetData; 71 | else if(st_enc) ps <= ns; 72 | end 73 | 74 | always@(*) begin 75 | case(ps) 76 | GetData : if(~en_fm0) ns = GetData; 77 | else if(en_fm0 & (~send_data)) ns = Data0p; 78 | else ns = Data1p; 79 | Data0p : if(~send_data) ns = Data0p; 80 | else ns = Data1p; 81 | Data0n : if(~send_data) ns = Data0n; 82 | else ns = Data1n; 83 | Data1p : if(~send_data) ns = Data0n; 84 | else ns = Data1n; 85 | Data1n : if(~send_data) ns = Data0p; 86 | else ns = Data1p; 87 | default : ns = GetData; 88 | endcase 89 | end 90 | 91 | always@(*) begin 92 | case(ps) 93 | GetData : data_select = 2'h0; 94 | Data0p : data_select = 2'h3; 95 | Data0n : data_select = 2'h2; 96 | Data1p : data_select = 2'h1; 97 | Data1n : data_select = 2'h0; 98 | default : data_select = 2'h0; 99 | endcase 100 | end 101 | 102 | always@(*) begin 103 | case(data_select) 104 | 2'h0 : m1o = 1'b0; 105 | 2'h1 : m1o = 1'b1; 106 | 2'h2 : m1o = clk_fm0_n; 107 | 2'h3 : m1o = clk_fm0; 108 | endcase 109 | end 110 | 111 | always@(posedge clk_fm0 or negedge rst_for_new_package) begin 112 | if(~rst_for_new_package) v_cnt <= 5'h00; 113 | else begin 114 | if(st_enc & en_vcnt) v_cnt <= v_cnt + 5'h01; 115 | end 116 | end 117 | 118 | always@(posedge clk_fm0 or negedge rst_for_new_package) begin 119 | if(~rst_for_new_package) fg_comp_cnt <= 2'b0; 120 | else begin 121 | if(fg_comp_cnt == 2'b10) fg_comp_cnt <= fg_comp_cnt; 122 | else if(en_fm0 & fg_complete) fg_comp_cnt <= fg_comp_cnt + 2'b1; 123 | end 124 | end 125 | 126 | assign fm0_complete = (fg_comp_cnt == 2'b10)? 1'b1 : 1'b0; 127 | 128 | 129 | endmodule 130 | -------------------------------------------------------------------------------- /frmgen.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Frame Generator 3 | * 4 | * Generate the replied package from Tag to Reader 5 | * including Preamle, Replied Data, End-of-Signaling 6 | * 7 | * Support FM0 Encoder and Miller Encoder in M = 2, 4, 8 8 | * the forms of encoding is depends on M 9 | * 10 | * Two forms of preamble, which is depends on Trext 11 | */ 12 | 13 | 14 | `timescale 1us / 1ns 15 | 16 | 17 | module frmgen 18 | ( 19 | output reg send_data, 20 | output en_fm0, 21 | output reg st_enc, 22 | output pre_p_complete, 23 | output p_complete, 24 | output reg fg_complete, 25 | input clk_frm, 26 | input rst_for_new_package, 27 | input reply_data, 28 | input [15:0]crc_16, 29 | input [1:0]m, 30 | input trext, 31 | input reply_complete, 32 | input en_crc16_for_rpy 33 | ); 34 | 35 | 36 | reg reply_complete_d; 37 | reg [4:0]cnt_end; 38 | reg [4:0]p_cnt; 39 | reg [3:0]crc_cnt; 40 | reg crc_complete; 41 | 42 | 43 | assign en_fm0 = (m == 2'b00)? 1'b1 : 1'b0; 44 | 45 | assign pre_p_complete = (p_cnt > (cnt_end - 5'h2))? 1'b1 : 1'b0; 46 | 47 | assign p_complete = (p_cnt == cnt_end)? 1'b1 : 1'b0; 48 | 49 | always@(posedge clk_frm or negedge rst_for_new_package) begin 50 | if(~rst_for_new_package) st_enc <= 1'b0; 51 | else st_enc <= 1'b1; 52 | end 53 | 54 | always@(posedge clk_frm or negedge rst_for_new_package) begin 55 | if(~rst_for_new_package) reply_complete_d <= 1'b0; 56 | else reply_complete_d <= reply_complete; 57 | end 58 | 59 | always@(*) begin 60 | case({m, trext}) 61 | 3'b000 : cnt_end = 5'h6; 62 | 3'b001 : cnt_end = 5'h12; 63 | 3'b010 : cnt_end = 5'ha; 64 | 3'b011 : cnt_end = 5'h16; 65 | 3'b100 : cnt_end = 5'ha; 66 | 3'b101 : cnt_end = 5'h16; 67 | 3'b110 : cnt_end = 5'ha; 68 | 3'b111 : cnt_end = 5'h16; 69 | endcase 70 | end 71 | 72 | always@(posedge clk_frm or negedge rst_for_new_package) begin 73 | if(~rst_for_new_package) p_cnt <= 5'h0; 74 | else begin 75 | if(p_cnt == cnt_end) p_cnt <= p_cnt; 76 | else p_cnt <= p_cnt + 5'h1; 77 | end 78 | end 79 | 80 | always@(posedge clk_frm or negedge rst_for_new_package) begin 81 | if(~rst_for_new_package) send_data <= 1'b0; 82 | else if(~en_crc16_for_rpy & reply_complete_d) send_data <= 1'b1; 83 | else if(en_crc16_for_rpy & crc_complete) send_data <= 1'b1; 84 | else if(reply_complete_d & en_crc16_for_rpy & ~crc_complete) send_data <= crc_16[crc_cnt]; 85 | else begin 86 | if(p_cnt != cnt_end) begin 87 | if(m == 2'b00) begin 88 | if(~trext) begin 89 | case(p_cnt) 90 | 5'h0 : send_data <= 1'b1; 91 | 5'h1 : send_data <= 1'b0; 92 | 5'h2 : send_data <= 1'b1; 93 | 5'h3 : send_data <= 1'b0; 94 | 5'h4 : send_data <= 1'b0; 95 | 5'h5 : send_data <= 1'b1; 96 | endcase 97 | end 98 | else begin 99 | case(p_cnt) 100 | 5'h0, 5'h1, 5'h2, 5'h3, 5'h4, 5'h5, 5'h6, 5'h7, 5'h8, 5'h9, 5'ha, 5'hb : send_data <= 1'b0; 101 | 5'hc : send_data <= 1'b1; 102 | 5'hd : send_data <= 1'b0; 103 | 5'he : send_data <= 1'b1; 104 | 5'hf : send_data <= 1'b0; 105 | 5'h10 : send_data <= 1'b0; 106 | 5'h11 : send_data <= 1'b1; 107 | endcase 108 | end 109 | end 110 | else begin 111 | if(~trext) begin 112 | case(p_cnt) 113 | 5'h0, 5'h1, 5'h2, 5'h3 : send_data <= 1'b0; 114 | 5'h4 : send_data <= 1'b0; 115 | 5'h5 : send_data <= 1'b1; 116 | 5'h6 : send_data <= 1'b0; 117 | 5'h7 : send_data <= 1'b1; 118 | 5'h8 : send_data <= 1'b1; 119 | 5'h9 : send_data <= 1'b1; 120 | endcase 121 | end 122 | else begin 123 | case(p_cnt) 124 | 5'h0, 5'h1, 5'h2, 5'h3, 5'h4, 5'h5, 5'h6, 5'h7, 5'h8, 5'h9, 5'ha, 5'hb, 5'hc, 5'hd, 5'he, 5'hf : send_data <= 1'b0; 125 | 5'h10 : send_data <= 1'b0; 126 | 5'h11 : send_data <= 1'b1; 127 | 5'h12 : send_data <= 1'b0; 128 | 5'h13 : send_data <= 1'b1; 129 | 5'h14 : send_data <= 1'b1; 130 | 5'h15 : send_data <= 1'b1; 131 | endcase 132 | end 133 | end 134 | end 135 | else send_data <= reply_data; 136 | end 137 | end 138 | 139 | always@(posedge clk_frm or negedge rst_for_new_package) begin 140 | if(~rst_for_new_package) crc_cnt <= 4'hf; 141 | else begin 142 | if(crc_cnt == 4'h0) crc_cnt <= crc_cnt; 143 | else if(reply_complete_d & en_crc16_for_rpy) crc_cnt <= crc_cnt - 4'h1; 144 | end 145 | end 146 | 147 | always@(posedge clk_frm or negedge rst_for_new_package) begin 148 | if(~rst_for_new_package) crc_complete <= 1'b0; 149 | else if(crc_cnt == 4'h0) crc_complete <= 1'b1; 150 | end 151 | 152 | always@(posedge clk_frm or negedge rst_for_new_package) begin 153 | if(~rst_for_new_package) fg_complete <= 1'b0; 154 | else begin 155 | if(reply_complete_d & ~en_crc16_for_rpy) fg_complete <= 1'b1; 156 | else if(crc_complete & en_crc16_for_rpy) fg_complete <= 1'b1; 157 | end 158 | end 159 | 160 | 161 | endmodule 162 | -------------------------------------------------------------------------------- /bb_proc.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Baseband Processor 3 | * 4 | * Must read EPC Gen2 UHF RFID protocols 5 | * 6 | * All of the input and output signals depend on your whole RFID Tag design 7 | * In this case, we use the delayed PIE code to clock the received PIE code. So we should input PIE code (pie_code) and delayed PIE code (clk_dpie) 8 | * we use the clock signal in 200 KHz generated by Multivinrator to generate the clock signal in BLF. (clk_200K) 9 | * rst is generated by POR circuit in our analog front-end circuit to reset the baseband processor. (rst) 10 | * output the backscattered data after processing and computing to control the Backscatter circuit in our analog front-end circuit. (bs_data) 11 | * 12 | * Output signals package_complete and crc_check_pass are not necessary for our RFID Tag design 13 | * it's just for test 14 | */ 15 | 16 | 17 | `timescale 1us / 1ns 18 | 19 | 20 | module bb_proc 21 | ( 22 | output bs_data, 23 | output package_complete, 24 | output crc_check_pass, 25 | input clk_200K, 26 | input pie_code, 27 | input clk_dpie, 28 | input rst 29 | ); 30 | 31 | 32 | wire clk_crc5; 33 | wire clk_crc16; 34 | wire clk_blf; 35 | wire clk_cp; 36 | wire clk_prng; 37 | wire clk_frm; 38 | wire clk_fm0; 39 | wire clk_mil; 40 | wire clk_mem; 41 | wire rst_n; 42 | wire rst_for_new_package; 43 | wire rst_crc16; 44 | wire start_working; 45 | wire dr; 46 | wire [1:0]m; 47 | wire en_crc5; 48 | wire en_crc16; 49 | wire en_2nd_clk_cp; 50 | wire en_prng_idol; 51 | wire en_prng_act; 52 | wire en_tx; 53 | wire en_if; 54 | wire packet_complete_sync; 55 | wire en_crc16_for_rpy; 56 | wire reply_complete; 57 | wire rd_complete; 58 | wire bs_complete; 59 | wire [7:0]cmd; 60 | wire [51:0]param; 61 | wire [15:0]crc_16; 62 | wire reply_data; 63 | wire trext; 64 | wire [18:0]addr; 65 | wire [15:0]prn; 66 | wire rd_data; 67 | wire pre_p_complete; 68 | wire p_complete; 69 | wire [5:0]A; 70 | wire [15:0]Q; 71 | wire CEN; 72 | 73 | 74 | // --- Clock/Reset Generator --- 75 | crg crg_1 76 | ( 77 | .clk_crc5(clk_crc5), 78 | .clk_crc16(clk_crc16), 79 | .clk_blf(clk_blf), 80 | .clk_cp(clk_cp), 81 | .clk_prng(clk_prng), 82 | .clk_frm(clk_frm), 83 | .clk_fm0(clk_fm0), 84 | .clk_mil(clk_mil), 85 | .clk_if(clk_mem), 86 | .rst_n(rst_n), 87 | .clk_200K(clk_200K), 88 | .clk_dpie(clk_dpie), 89 | .pie_code(pie_code), 90 | .rst(rst), 91 | .rst_for_new_package(rst_for_new_package), 92 | .rst_crc16(rst_crc16), 93 | .start_working(start_working), 94 | .dr(dr), 95 | .m(m), 96 | .en_crc5(en_crc5), 97 | .en_crc16(en_crc16), 98 | .en_2nd_clk_cp(en_2nd_clk_cp), 99 | .en_prng_idol(en_prng_idol), 100 | .en_prng_act(en_prng_act), 101 | .en_tx(en_tx), 102 | .en_if(en_if), 103 | .packet_complete_sync(packet_complete_sync), 104 | .en_crc16_for_rpy(en_crc16_for_rpy), 105 | .reply_complete(reply_complete), 106 | .rd_complete(rd_complete), 107 | .bs_complete(bs_complete) 108 | ); 109 | 110 | 111 | // --- RX (including Frame-Sync Detector, CRC-5, CRC-16 and Command Buffer) --- 112 | rx rx_1 113 | ( 114 | .cmd(cmd), 115 | .param(param), 116 | .package_complete(package_complete), 117 | .crc_check_pass(crc_check_pass), 118 | .crc_16(crc_16), 119 | .en_crc5(en_crc5), 120 | .en_crc16(en_crc16), 121 | .pie_code(pie_code), 122 | .clk_dpie(clk_dpie), 123 | .clk_crc5(clk_crc5), 124 | .clk_crc16(clk_crc16), 125 | .rst_n(rst_n), 126 | .rst_for_new_package(rst_for_new_package), 127 | .rst_crc16(rst_crc16), 128 | .reply_data(reply_data), 129 | .en_crc16_for_rpy(en_crc16_for_rpy) 130 | ); 131 | 132 | 133 | // --- Synchronizer (convential two flip-flop) --- 134 | two_dff_sync two_dff_sync_1 135 | ( 136 | .data_out(packet_complete_sync), 137 | .clk_ad(clk_dpie), 138 | .clk_bd(clk_blf), 139 | .rst_n(rst_n), 140 | .data_in(package_complete) 141 | ); 142 | 143 | 144 | // --- Command Processor --- 145 | cmd_proc cmd_proc_1 146 | ( 147 | .reply_data(reply_data), 148 | .reply_complete(reply_complete), 149 | .dr(dr), 150 | .m(m), 151 | .trext(trext), 152 | .en_2nd_clk_cp(en_2nd_clk_cp), 153 | .en_tx(en_tx), 154 | .en_prng_idol(en_prng_idol), 155 | .en_prng_act(en_prng_act), 156 | .en_crc16_for_rpy(en_crc16_for_rpy), 157 | .en_if(en_if), 158 | .addr(addr), 159 | .clk_cp(clk_cp), 160 | .clk_frm(clk_frm), 161 | .rst_n(rst_n), 162 | .rst_for_new_package(rst_for_new_package), 163 | .cmd(cmd), 164 | .param(param), 165 | .prn(prn), 166 | .crc_check_pass(crc_check_pass), 167 | .rd_data(rd_data), 168 | .pre_p_complete(pre_p_complete), 169 | .p_complete(p_complete), 170 | .rd_complete(rd_complete) 171 | ); 172 | 173 | 174 | // --- Pseudo Ramdon Number Generator --- 175 | prng prng_1 176 | ( 177 | .prn(prn), 178 | .clk_prng(clk_prng), 179 | .rst_n(rst_n) 180 | ); 181 | 182 | 183 | // --- Memory Interface --- 184 | mem_if mem_if_1 185 | ( 186 | .rd_data(rd_data), 187 | .rd_complete(rd_complete), 188 | .A(A), 189 | .CEN(CEN), 190 | .addr(addr), 191 | .Q(Q), 192 | .clk_if(clk_mem), 193 | .rst_for_new_package(rst_for_new_package) 194 | ); 195 | 196 | 197 | // --- ROM (64 words, 16 bits per word) --- 198 | rom_64x16 rom_64x16_1 199 | ( 200 | .Q(Q), 201 | .CLK(clk_mem), 202 | .CEN(CEN), 203 | .A(A) 204 | ); 205 | 206 | 207 | // --- TX (including Frame Generator, FM0 Encoder, Miller Encoder) --- 208 | tx tx_1 209 | ( 210 | .bs_data(bs_data), 211 | .pre_p_complete(pre_p_complete), 212 | .p_complete(p_complete), 213 | .bs_complete(bs_complete), 214 | .clk_blf(clk_blf), 215 | .clk_frm(clk_frm), 216 | .clk_fm0(clk_fm0), 217 | .clk_mil(clk_mil), 218 | .rst_for_new_package(rst_for_new_package), 219 | .reply_data(reply_data), 220 | .crc_16(crc_16), 221 | .m(m), 222 | .trext(trext), 223 | .reply_complete(reply_complete), 224 | .en_crc16_for_rpy(en_crc16_for_rpy), 225 | .start_working(start_working) 226 | ); 227 | 228 | 229 | endmodule 230 | -------------------------------------------------------------------------------- /bb_proc_syn.tcl: -------------------------------------------------------------------------------- 1 | # Clock period 2 | 3 | set cycle_dpie 6250 4 | 5 | set cycle_200K 5000 6 | 7 | 8 | 9 | # Read design file 10 | 11 | read_file -format verilog {./bb_proc.v ./cmd_buf.v ./cmd_proc.v ./crc16.v ./crc5.v ./crg.v ./fm0_enc.v ./frmgen.v ./fs_detector.v ./mem_if.v ./miller_enc.v ./prng.v ./rom_64x16.v ./rx.v ./two_dff_sync.v ./tx.v} 12 | # The file rom_64x16.v is our ROM verilog file 13 | # You should design your memory by writing a module by yourself or generating it by tool 14 | 15 | current_design [get_designs bb_proc] 16 | 17 | link 18 | 19 | 20 | 21 | # Set design environment 22 | 23 | set_operating_conditions -max_library slow -max slow -min_library fast -min fast 24 | 25 | set_wire_load_model -name tsmc18_w110 -library slow 26 | 27 | set_driving_cell -library slow -lib_cell BUFX4 -no_design_rule [all_inputs] 28 | 29 | set_load [load_of "slow/BUFX4/A"] [all_outputs] 30 | 31 | 32 | 33 | # Set clock constraints 34 | 35 | create_clock -name clk_dpie -period $cycle_dpie [get_ports clk_dpie] 36 | 37 | create_clock -name clk_200K -period $cycle_200K [get_ports clk_200K] 38 | 39 | set_dont_touch_network [get_clocks clk_dpie] 40 | 41 | set_dont_touch_network [get_clocks clk_200K] 42 | 43 | set_ideal_network [get_clocks clk_dpie] 44 | 45 | set_ideal_network [get_clocks clk_200K] 46 | 47 | set_fix_hold [get_clocks clk_dpie] 48 | 49 | set_fix_hold [get_clocks clk_200K] 50 | 51 | set_clock_uncertainty 0.1 [get_clocks clk_dpie] 52 | 53 | set_clock_uncertainty 0.2 [get_clocks clk_200K] 54 | 55 | set_clock_latency -source 0.5 [get_clocks clk_dpie] 56 | 57 | set_clock_latency -source 0.5 [get_clocks clk_200K] 58 | 59 | set_clock_latency 0.5 [get_clocks clk_dpie] 60 | 61 | set_clock_latency 0.5 [get_clocks clk_200K] 62 | 63 | set_input_transition 0.5 [all_inputs] 64 | 65 | set_clock_transition 0.1 [get_clocks clk_dpie] 66 | 67 | set_clock_transition 0.1 [get_clocks clk_200K] 68 | 69 | set_input_delay -max 5 -clock clk_dpie [all_inputs] 70 | 71 | set_input_delay -min 0.5 -clock clk_dpie [all_inputs] 72 | 73 | set_output_delay -max 1 -clock clk_200K [all_outputs] 74 | 75 | set_output_delay -min 1 -clock clk_200K [all_outputs] 76 | 77 | remove_input_delay -max clk_200K 78 | 79 | remove_input_delay -min clk_200K 80 | 81 | set_clock_groups -asynchronous -group {clk_dpie} -group {clk_200K} 82 | 83 | 84 | 85 | # Create generated clock 86 | 87 | # Should define the generated clocks to let Synthesis tool know 88 | # The follow commands is an example of specifying the generated clocks in the schematic 89 | # Your generated clocks are possibly not as follows 90 | 91 | create_generated_clock -name clk_blf -source clk_200K -divide_by 2 [get_pins crg_1/C471/A] 92 | set_dont_touch_network [get_clocks clk_blf] 93 | set_ideal_network [get_pins crg_1/C471/A] 94 | 95 | create_generated_clock -name clk_cp -source clk_200K -divide_by 2 -combinational [get_pins crg_1/C473/Z] 96 | set_dont_touch_network [get_clocks clk_cp] 97 | set_ideal_network [get_pins crg_1/C473/Z] 98 | 99 | create_generated_clock -name clk_crc5 -source clk_dpie -combinational [get_pins crg_1/C413/Z] 100 | set_dont_touch_network [get_clocks clk_crc5] 101 | set_ideal_network [get_pins crg_1/C413/Z] 102 | 103 | create_generated_clock -name clk_crc16 -source clk_dpie -combinational [get_pins crg_1/C392/Z_0] 104 | set_dont_touch_network [get_clocks clk_crc16] 105 | set_ideal_network [get_pins crg_1/C392/Z_0] 106 | 107 | create_generated_clock -name clk_fm0 -source clk_200K -divide_by 2 -combinational [get_pins crg_1/C398/Z_0] 108 | set_dont_touch_network [get_clocks clk_fm0] 109 | set_ideal_network [get_pins crg_1/C398/Z_0] 110 | 111 | create_generated_clock -name clk_mem -source clk_200K -divide_by 2 -combinational [get_pins crg_1/C519/Z] 112 | set_dont_touch_network [get_clocks clk_mem] 113 | set_ideal_network [get_pins crg_1/C519/Z] 114 | 115 | create_generated_clock -name clk_mil -source clk_200K -divide_by 2 -combinational [get_pins crg_1/C400/Z_0] 116 | set_dont_touch_network [get_clocks clk_mil] 117 | set_ideal_network [get_pins crg_1/C400/Z_0] 118 | 119 | create_generated_clock -name clk_frm -source clk_200K -divide_by 2 -combinational [get_pins crg_1/C422/B] 120 | set_dont_touch_network [get_clocks clk_frm] 121 | set_ideal_network [get_pins crg_1/C422/B] 122 | 123 | create_generated_clock -name clk_prng -source clk_200K -divide_by 2 -combinational [get_pins crg_1/C476/Z] 124 | set_dont_touch_network [get_clocks clk_prng] 125 | set_ideal_network [get_pins crg_1/C476/Z] 126 | 127 | 128 | 129 | # Set design rule constraints 130 | 131 | set_max_area 0 132 | 133 | set_max_fanout 20 [all_inputs] 134 | 135 | set_max_transition 0.5 [all_inputs] 136 | 137 | 138 | 139 | # Solve multiple instance 140 | 141 | uniquify 142 | 143 | set_fix_multiple_port_nets -all -buffer_constants [get_designs *] 144 | 145 | set case_analysis_with_logic_constants true 146 | 147 | 148 | 149 | # Synthesis design 150 | 151 | compile_ultra -area_high_effort_script 152 | 153 | 154 | 155 | # Optimization 156 | 157 | set_dynamic_optimization true 158 | 159 | compile -inc 160 | 161 | remove_unconnected_ports -blast_bused [get_cells * -hier] 162 | 163 | 164 | 165 | set edifout_netlist_only "TRUE" 166 | 167 | set verilogout_no_tri "TRUE" 168 | 169 | history keep 100 170 | 171 | alias h history 172 | 173 | set bus_interface_style {%s[%d]} 174 | 175 | set bus_naming_style {%s[%d]} 176 | 177 | set hdlout_internal_busses true 178 | 179 | change_names -hierarchy -rule verilog 180 | 181 | define_name_rules name_rule -allowed {a-z A-Z 0-9 _} -max_length 255 -type cell 182 | 183 | define_name_rules name_rule -allowed {a-z A-Z 0-9 _[]} -max_length 255 -type net 184 | 185 | define_name_rules name_rule -map {{"\\*cell\\" "cell"}} 186 | 187 | change_names -hierarchy -rule name_rule 188 | 189 | 190 | 191 | # Output reports and netlists 192 | 193 | # Please create "Report" and "Netlist" directory 194 | 195 | report_design > Report/bb_proc\.design 196 | 197 | report_port > Report/bb_proc\.port 198 | 199 | report_net > Report/bb_proc\.net 200 | 201 | report_timing_requirements > Report/bb_proc\.timing_requirements 202 | 203 | report_constraints > Report/bb_proc\.constraints 204 | 205 | report_timing > Report/bb_proc\.timing 206 | 207 | report_area > Report/bb_proc\.area 208 | 209 | report_resource > Report/bb_proc\.resource 210 | 211 | report_power > Report/bb_proc\.power 212 | 213 | set verilogout_higher_design_first true 214 | 215 | write -format verilog -hierarchy -output Netlist/bb_proc\_syn.v 216 | 217 | write_sdf -version 2.1 -context verilog -load_delay net Netlist/bb_proc\_syn.sdf 218 | 219 | write_sdc Netlist/bb_proc\_syn.sdc 220 | 221 | write_file -format ddc -hierarchy -output Netlist/bb_proc\_syn.ddc 222 | -------------------------------------------------------------------------------- /bb_proc_apr.tcl: -------------------------------------------------------------------------------- 1 | # Create library 2 | 3 | # The following command is an example of creating a library 4 | # Please define and create your own library 5 | 6 | create_mw_lib -technology ./tsmc18_CIC.tf -mw_reference_library {./rom_64x16_frame/rom_64x16 ./tsmc18_fram ./tpz973gv ./tpb973gv} 7 | 8 | 9 | 10 | # Check library 11 | 12 | set_check_library_option -all 13 | 14 | check_library 15 | 16 | 17 | 18 | # Specify tlu* parasitic RC model files 19 | 20 | # Please define your tluplus and map files of process 21 | 22 | set_tlu_plus_files -max_tluplus ./t18.tluplus -min_tluplus ./t18.tluplus -tech2itf_map ./t18.map 23 | 24 | 25 | 26 | # Read the netlist and create a design cel 27 | 28 | import_designs {./bb_proc_syn.v} -foramt verilog -top bb_proc -cel bb_proc 29 | 30 | 31 | 32 | # Verify logical library are loaded 33 | 34 | list_libs 35 | 36 | 37 | 38 | # Define logical power/ground connections 39 | 40 | derive_pg_connection -power_net VDD -power_pin VDD -ground_net VSS -ground_pin VSS 41 | 42 | check_mw_design -power_nets 43 | 44 | 45 | 46 | # Apply and check timing constraints 47 | 48 | read_sdc ./bb_proc_syn.sdc 49 | 50 | report_timing 51 | 52 | report_timing_requirements 53 | 54 | report_case_analysis 55 | 56 | 57 | 58 | # Ensure proper modeling of clock tree 59 | 60 | report_clock -skew 61 | 62 | 63 | 64 | # Apply timing and optimization controls 65 | 66 | set timing_enable_multiple_clocks_per_reg true 67 | 68 | set case_analysis_with_logic_constants true 69 | 70 | set fix_multiple_port_nets -all -buffer_constants 71 | 72 | set_auto_disable_drc_nets -constant false 73 | 74 | set_max_area 0 75 | 76 | 77 | 78 | # Perform a timing sanity check 79 | 80 | set_zero_interconnect_delay_mode true 81 | 82 | report_constraints -all 83 | 84 | report_timing 85 | 86 | set_zero_interconnect_delay_mode false 87 | 88 | 89 | 90 | # Save the design 91 | 92 | save_mw_cel bb_proc 93 | 94 | save_mw_cel bb_proc -as design_setup 95 | 96 | 97 | 98 | # I/O order assignments 99 | 100 | set_pin_physical_constraints -side 4 -pin_name bs_data -order 1 -width 1 -depth 1 -offset 30 101 | 102 | set_pin_physical_constraints -side 4 -pin_name clk_200K -order 2 -width 1 -depth 1 -offset 130 103 | 104 | set_pin_physical_constraints -side 4 -pin_name rst -order 3 -width 1 -depth 1 -offset 230 105 | 106 | set_pin_physical_constraints -side 4 -pin_name clk_dpie -order 4 -width 1 -depth 1 -offset 330 107 | 108 | set_pin_physical_constraints -side 4 -pin_name pie_code -order 5 -width 1 -depth 1 -offset 430 109 | 110 | set_pin_physical_constraints -side 3 -pin_name package_complete -order 1 -width 1 -depth 1 -offset 430 111 | 112 | set_pin_physical_constraints -side 3 -pin_name crc_check_pass -order 2 -width 1 -depth 1 -offset 330 113 | 114 | 115 | 116 | # Design planning 117 | 118 | gui_set_current_task -name {ALL} 119 | 120 | create_floorplan -core_utilization 0.4 -core_aspect_ratio 1 -left_io2core 20 -bottom_io2core 20 -right_io2core 20 -top_io2core 20 121 | 122 | set_fp_macro_options [get_cells rom_64x16_1] -legal_orientations W 123 | 124 | set_keepout_matgin -type hard -outer {10 0 10 0} rom_64x16_1 125 | 126 | set physopt_hard_keepout_distance 10 127 | 128 | set_fp_placement_strategy -macros_on_edge on 129 | 130 | set_fp_placement_strategy -auto_grouping high 131 | 132 | create_fp_placement 133 | 134 | set_dont_touch_placement [all_macro_cells] 135 | 136 | create_fp_placement -timing_driven -incremental all 137 | 138 | derive_pg_connection -power_net {VDD} -ground_net {VSS} -power_pin {VDD} -ground_pin {VSS} 139 | 140 | create_fp_virtual_pad -net VDD -point {63.850 0.000} 141 | 142 | create_fp_virtual_pad -net VDD -point {404.685 -0.860} 143 | 144 | create_fp_virtual_pad -net VSS -point {94.915 0.000} 145 | 146 | create_fp_virtual_pad -net VSS -point {369.310 0.000} 147 | 148 | set_fp_rail_constraints -add_layer -layer METAL5 -direction horizontal -max_strap 10 -min_strap 3 -max_width 4 -min_width 4 -spacing minimum 149 | 150 | set_fp_rail_constraints -add_layer -layer METAL4 -direction vertical -max_strap 10 -min_strap 3 -max_width 4 -min_width 4 -spacing minimum 151 | 152 | set_fp_rail_constraints -set_ring -nets {VDD VSS VDD VSS VDD VSS} -horizontal_ring_layer {METAL5} -vertical_ring_layer {METAL4} -ring_width 8 -extend_strap core_ring 153 | 154 | set_fp_rail_constraints -set_global -no_routing_over_hard_macros 155 | 156 | set_fp_block_ring_constraints -add -horizontal_layer METAL5 -horizontal_width 1.5 -horizontal_offset 1 -vertical_layer METAL4 -vertical_width 1.5 -vertical_offset 1 -block_type master -block {rom_64x16} -net {VDD VSS} 157 | 158 | synthesize_fp_rail -nets {VDD VSS} -voltage_supply 1.6 -target_voltage_drop 100 -synthesize_power_plan -power_budget 200 159 | 160 | commit_fp_rail 161 | 162 | preroute_instances -ignore_macros -ignore_cover_cells -primary_routing_layer pin -extend_for_multiple_connections -extension_gap 16 163 | 164 | preroute_instances -ignore_pads -ignore_cover_cells -primary_routing_layer pin 165 | 166 | preroute_standard_cells -extend_for_multiple_connections -extension_gap 16 -connect horizontal -remove_floating_pieces -do_not_route_over_macros -fill_empty_rows -port_filter_mode off -cell_instance_filter_mode off -voltage_area_filter_mode off 167 | 168 | set_pnet_options -complete "METAL4 METAL5" 169 | 170 | create_fp_placement -incremental all 171 | 172 | 173 | 174 | # Placement 175 | 176 | read_sdc -version Latest "./bb_proc_syn.sdc" 177 | 178 | check_physical_design -stage pre_place_opt 179 | 180 | source ./add_tie.tcl 181 | 182 | place_opt -power -optimize_dft 183 | 184 | derive_pg_connection -power_net {VDD} -ground_net {VSS} -power_pin {VDD} -ground_pin {VSS} 185 | 186 | 187 | 188 | # CTS 189 | 190 | remove_clock_tree 191 | 192 | set_clock_tree_options -target_early_delay 0.9 -target_skew 0.1 193 | 194 | clock_opt -only_cts -no_clock_route 195 | 196 | route_group -all_clock_nets 197 | 198 | clock_opt -only_psyn 199 | 200 | set_fix_hold [all_clocks] 201 | 202 | clock_opt -only_psyn 203 | 204 | optimize_clock_tree 205 | 206 | 207 | 208 | # Route 209 | 210 | check_zrt_routability -error_view bb_proc.err 211 | 212 | set_route_zrt_common_options -post_detail_route_redundant_via_insertion high -concurrent_redundant_via_mode insert_at_high_cost -concurrent_redundant_via_effort_level high 213 | 214 | route_zrt_group -all_clock_nets 215 | 216 | route_zrt_auto 217 | 218 | derive_pg_connection -power_net {VDD} -ground_net {VSS} -power_pin {VDD} -ground_pin {VSS} 219 | 220 | 221 | 222 | # DFM 223 | 224 | source ./addCoreFiller.cmd 225 | 226 | verify_zrt_route 227 | 228 | route_zrt_detail -incremental true -initial_drc_from_input true 229 | 230 | derive_pg_connection -power_net {VDD} -ground_net {VSS} -power_pin {VDD} -ground_pin {VSS} 231 | 232 | # Specify the I/O pins 233 | # Please specify the I/O pins in GUI 234 | # The following commands are examples of specifying the I/O pins 235 | # gui_set_mouse_tool_option -tool CreateTextTool -option {text} -value {bs_data} 236 | # gui_set_mouse_tool_option -tool CreateTextTool -option {text} -value {VDD} 237 | # gui_set_mouse_tool_option -tool CreateTextTool -option {text} -value {VSS} 238 | # gui_set_mouse_tool_option -tool CreateTextTool -option {text} -value {rst} 239 | # gui_set_mouse_tool_option -tool CreateTextTool -option {text} -value {pie_code} 240 | # gui_set_mouse_tool_option -tool CreateTextTool -option {text} -value {clk_dpie} 241 | # gui_set_mouse_tool_option -tool CreateTextTool -option {text} -value {clk_200K} 242 | # gui_set_mouse_tool_option -tool CreateTextTool -option {text} -value {package_complete} 243 | # gui_set_mouse_tool_option -tool CreateTextTool -option {text} -value {crc_check_pass} 244 | 245 | save_mw_cel -design "bb_proc.CEL;1" 246 | 247 | set_write_stream_options -map_layer ./macro.map -child_depth 20 -flatten_via 248 | 249 | write_stream -format gds -lib_name ./rfid_tag_bb_proc -cell {bb_proc} bb_proc.gds 250 | 251 | write_sdf -version 2.0 -context verilog -load_delay net bb_proc.sdf 252 | 253 | 254 | 255 | # Save design 256 | 257 | save_mw_cel -design "bb_proc.CEL;1" 258 | -------------------------------------------------------------------------------- /crg.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Clock/Reset Generator 3 | * 4 | * CRG controls all clock and reset signal of all modules 5 | * 6 | * Clock gating is applied to all modules for saving the power dissipation 7 | * 8 | * The clock signal of each module vibrates in the lowest frequency for saving the power dissipation 9 | * 10 | * The constraints of clock gating is specified in the file bb_proc.tcl 11 | */ 12 | 13 | 14 | `timescale 1us / 1ns 15 | 16 | 17 | module crg 18 | ( 19 | output clk_crc5, 20 | output clk_crc16, 21 | output clk_blf, 22 | output clk_cp, 23 | output clk_prng, 24 | output reg clk_frm, 25 | output clk_fm0, 26 | output reg clk_mil, 27 | output clk_mem, 28 | output rst_n, 29 | output reg rst_for_new_package, 30 | output rst_crc16, 31 | output reg start_working, 32 | input clk_200K, // 200 KHz input clock generated from multivibrator 33 | input clk_dpie, // delayed PIE code 34 | input pie_code, 35 | input rst, 36 | input dr, 37 | input [1:0]m, 38 | input en_crc5, 39 | input en_crc16, 40 | input en_2nd_clk_cp, 41 | input en_prng_idol, 42 | input en_prng_act, 43 | input en_tx, 44 | input en_if, 45 | input packet_complete_sync, 46 | input en_crc16_for_rpy, 47 | input reply_complete, 48 | input rd_complete, 49 | input bs_complete 50 | ); 51 | 52 | 53 | wire clk_200K_n; 54 | wire clk_blf_n; 55 | wire rst_for_cpu_crc16; 56 | wire en_crc16_rpy; // compute a CRC-16 of the replying data 57 | wire clk_crc16_1; 58 | wire clk_crc16_2; 59 | wire clk_dr0; 60 | wire en_cp_1; 61 | wire en_cp_2; 62 | wire clk_cp_1; 63 | wire clk_cp_2; 64 | wire en_prng_idol_for_clk; 65 | wire clk_prng_idol; 66 | wire clk_blf_for_tx; 67 | wire clk_blf_half_for_tx; 68 | wire clk_blf_quar_for_tx; 69 | wire clk_blf_eigh_for_tx; 70 | 71 | 72 | reg en_crc5_d; 73 | reg en_crc16_d; 74 | reg en_crc16_for_rpy_d; 75 | reg [1:0]reply_complete_d; 76 | reg clk_dr1; 77 | reg [2:0]cnt_dr0_p; 78 | reg [2:0]cnt_dr0_n; 79 | reg clk_dr0_p; 80 | reg clk_dr0_n; 81 | reg [1:0]dr_d; 82 | reg term_cp_1; 83 | reg [1:0]en_2nd_clk_cp_d; 84 | reg en_prng_idol_d; 85 | reg bs_complete_d; 86 | reg clk_blf_half; // clock signal in half of BLF 87 | reg clk_blf_quar; // clock signal in quarter of BLF 88 | reg clk_blf_eigh; // clock signal in one eighth of BLF 89 | reg en_tx_d; 90 | reg rd_complete_d; 91 | 92 | 93 | // --- start working when clock generated by multivibrator is oscillating --- 94 | always@(posedge clk_200K or negedge rst_n) begin 95 | if(~rst_n) start_working <= 1'b0; 96 | else start_working <= 1'b1; 97 | end 98 | 99 | 100 | // --- generate global low-active asynchronous reset --- 101 | assign rst_n = ~rst; 102 | 103 | 104 | // --- generate reset signal for a new package --- 105 | always@(negedge clk_dpie or negedge rst_n) begin 106 | if(~rst_n) rst_for_new_package <= 1'b1; 107 | else begin 108 | if(~pie_code) rst_for_new_package <= 1'b0; 109 | else rst_for_new_package <= 1'b1; 110 | end 111 | end 112 | 113 | 114 | // --- generate reset signal for CRC-16 --- 115 | assign rst_for_cpu_crc16 = en_crc16_for_rpy & ~en_crc16_for_rpy_d; 116 | 117 | assign rst_crc16 = rst_for_new_package & ~rst_for_cpu_crc16; 118 | 119 | 120 | // --- generate clock signal of CRC-5 --- 121 | always@(negedge clk_dpie or negedge rst_n) begin 122 | if(~rst_n) en_crc5_d <= 1'b0; 123 | else en_crc5_d <= en_crc5; 124 | end 125 | 126 | assign clk_crc5 = en_crc5_d & clk_dpie; 127 | 128 | 129 | // --- generate clock signal of CRC-16 --- 130 | always@(posedge clk_dpie or negedge rst_n) begin 131 | if(~rst_n) en_crc16_d <= 1'b0; 132 | else en_crc16_d <= en_crc16; 133 | end 134 | 135 | always@(negedge clk_frm or negedge rst_n) begin 136 | if(~rst_n) en_crc16_for_rpy_d <= 1'b0; 137 | else en_crc16_for_rpy_d <= en_crc16_for_rpy; 138 | end 139 | 140 | always@(negedge clk_frm or negedge rst_n) begin 141 | if(~rst_n) reply_complete_d <= 2'b0; 142 | else reply_complete_d <= {reply_complete_d[0], reply_complete}; 143 | end 144 | 145 | assign en_crc16_rpy = en_crc16_for_rpy_d & ~reply_complete_d[1]; 146 | 147 | assign clk_crc16_1 = en_crc16_d & clk_dpie; 148 | 149 | assign clk_crc16_2 = en_crc16_rpy & clk_frm; 150 | 151 | assign clk_crc16 = en_crc16_for_rpy? clk_crc16_2 : clk_crc16_1; 152 | 153 | 154 | // --- generate 100 KHz clock for DR = 1 (divide 2) --- 155 | always@(posedge clk_200K or negedge rst_n) begin 156 | if(~rst_n) clk_dr1 <= 1'b0; 157 | else begin 158 | if(dr_d[1]) clk_dr1 <= ~clk_dr1; 159 | end 160 | end 161 | 162 | 163 | // --- generate 40 KHz clock for DR = 0 (divide 5) --- 164 | assign clk_dr0 = clk_dr0_p | clk_dr0_n; 165 | 166 | always@(posedge clk_200K or negedge rst_n) begin 167 | if(~rst_n) cnt_dr0_p <= 3'b0; 168 | else begin 169 | if(~dr_d[1]) begin 170 | if(cnt_dr0_p == 3'b100) cnt_dr0_p <= 3'b0; 171 | else cnt_dr0_p <= cnt_dr0_p + 3'b1; 172 | end 173 | end 174 | end 175 | 176 | assign clk_200K_n = ~clk_200K; 177 | 178 | always@(posedge clk_200K_n or negedge rst_n) begin 179 | if(~rst_n) cnt_dr0_n <= 3'b0; 180 | else begin 181 | if(~dr_d[1]) begin 182 | if(cnt_dr0_n == 3'b100) cnt_dr0_n <= 3'b0; 183 | else cnt_dr0_n <= cnt_dr0_n + 3'b1; 184 | end 185 | end 186 | end 187 | 188 | always@(posedge clk_200K or negedge rst_n) begin 189 | if(~rst_n) clk_dr0_p <= 1'b0; 190 | else begin 191 | if(~dr_d[1]) begin 192 | if(cnt_dr0_p < 3'b010) clk_dr0_p <= 1'b1; 193 | else clk_dr0_p <= 1'b0; 194 | end 195 | end 196 | end 197 | 198 | always@(posedge clk_200K_n or negedge rst_n) begin 199 | if(~rst_n) clk_dr0_n <= 1'b0; 200 | else begin 201 | if(~dr_d[1]) begin 202 | if(cnt_dr0_n < 3'b010) clk_dr0_n <= 1'b1; 203 | else clk_dr0_n <= 1'b0; 204 | end 205 | end 206 | end 207 | 208 | 209 | // --- determine backscatter link frequency of clock --- 210 | always@(posedge clk_blf or negedge rst_n) begin 211 | if(~rst_n) dr_d <= 0; 212 | else dr_d <= {dr_d[0], dr}; 213 | end 214 | 215 | assign clk_blf = dr_d[1]? clk_dr1 : clk_dr0; 216 | 217 | 218 | // --- generate clock signal of Command Processor --- 219 | assign clk_blf_n = ~clk_blf; 220 | 221 | always@(posedge clk_blf_n or negedge rst_n) begin 222 | if(~rst_n) term_cp_1 <= 1'b0; 223 | else term_cp_1 <= packet_complete_sync; 224 | end 225 | 226 | assign en_cp_1 = packet_complete_sync & ~term_cp_1; 227 | 228 | always@(posedge clk_blf_n or negedge rst_n) begin 229 | if(~rst_n) en_2nd_clk_cp_d <= 2'b0; 230 | else en_2nd_clk_cp_d <= {en_2nd_clk_cp_d[0], en_2nd_clk_cp}; 231 | end 232 | 233 | assign en_cp_2 = ~en_2nd_clk_cp_d[1] & en_2nd_clk_cp_d[0]; 234 | 235 | assign clk_cp_1 = clk_blf & en_cp_1; 236 | 237 | assign clk_cp_2 = clk_blf & en_cp_2; 238 | 239 | assign clk_cp = clk_cp_1 | clk_cp_2; 240 | 241 | 242 | // --- generate clock signal of PRNG --- 243 | always@(posedge clk_blf_n or negedge rst_n) begin 244 | if(~rst_n) en_prng_idol_d <= 1'b0; 245 | else en_prng_idol_d <= en_prng_idol; 246 | end 247 | 248 | assign clk_prng_idol = clk_blf & en_prng_idol_d; 249 | 250 | assign clk_prng = start_working & (clk_prng_idol | en_prng_act); 251 | 252 | 253 | // --- generate clock signal of Frame Generator --- 254 | always@(posedge clk_blf_n or negedge rst_n) begin 255 | if(~rst_n) bs_complete_d <= 1'b0; 256 | else bs_complete_d <= bs_complete; 257 | end 258 | 259 | always@(posedge clk_blf or negedge rst_n) begin 260 | if(~rst_n) en_tx_d <= 1'b0; 261 | else en_tx_d <= en_tx; 262 | end 263 | 264 | always@(posedge clk_blf or negedge rst_n) begin 265 | if(~rst_n) clk_blf_half <= 1'b0; 266 | else if(en_tx & (m == 2'b01 | m == 2'b10 | m == 2'b11)) clk_blf_half <= ~clk_blf_half; 267 | end 268 | 269 | always@(posedge clk_blf_half or negedge rst_n) begin 270 | if(~rst_n) clk_blf_quar <= 1'b0; 271 | else if(en_tx & (m == 2'b10 | m == 2'b11)) clk_blf_quar <= ~clk_blf_quar; 272 | end 273 | 274 | always@(posedge clk_blf_quar or negedge rst_n) begin 275 | if(~rst_n) clk_blf_eigh <= 1'b0; 276 | else if(en_tx & m == 2'b11) clk_blf_eigh <= ~clk_blf_eigh; 277 | end 278 | 279 | assign clk_blf_for_tx = clk_blf & en_tx_d & ~bs_complete_d; 280 | 281 | assign clk_blf_half_for_tx = clk_blf_half & ~bs_complete_d; 282 | 283 | assign clk_blf_quar_for_tx = clk_blf_quar & ~bs_complete_d; 284 | 285 | assign clk_blf_eigh_for_tx = clk_blf_eigh & ~bs_complete_d; 286 | 287 | always@(*) begin 288 | if(en_tx) begin 289 | case(m) 290 | 2'b00 : clk_frm = clk_blf_for_tx; 291 | 2'b01 : clk_frm = clk_blf_half_for_tx; 292 | 2'b10 : clk_frm = clk_blf_quar_for_tx; 293 | 2'b11 : clk_frm = clk_blf_eigh_for_tx; 294 | endcase 295 | end 296 | else clk_frm = 1'b0; 297 | end 298 | 299 | 300 | // --- generate clock signal of FM0 Encoder --- 301 | assign clk_fm0 = (m == 2'b00)? clk_blf_for_tx : 1'b0; 302 | 303 | 304 | // --- generate clock signal of Miller Encoder --- 305 | always@(*) begin 306 | if(en_tx) begin 307 | case(m) 308 | 2'b00 : clk_mil = 1'b0; 309 | 2'b01 : clk_mil = clk_blf_for_tx; 310 | 2'b10 : clk_mil = clk_blf_half_for_tx; 311 | 2'b11 : clk_mil = clk_blf_quar_for_tx; 312 | endcase 313 | end 314 | else clk_mil = 1'b0; 315 | end 316 | 317 | //----- generate clock signal of Memory ----- 318 | always@(negedge clk_frm or negedge rst_n) begin 319 | if(~rst_n) rd_complete_d <= 1'b0; 320 | else rd_complete_d <= rd_complete; 321 | end 322 | 323 | assign clk_if = clk_frm & en_if & ~rd_complete_d; 324 | 325 | 326 | endmodule 327 | -------------------------------------------------------------------------------- /bb_proc_tb.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Test Bench of the baseband processor 3 | * 4 | * This module is an example of the communication between a Reader and a single Tag 5 | * 6 | * Procedure : Select -> Inventory -> Access 7 | * refer to annex E 8 | * 9 | * Define your SDF file 10 | * if you want to simulate the ideal module, comment out the line 15 and 57 - 59 11 | */ 12 | 13 | 14 | `timescale 1us / 1ns 15 | `define SDF_FILE = "./bb_proc.sdf" 16 | 17 | 18 | module bb_proc_tb; 19 | 20 | 21 | // --- input --- 22 | reg clk_200K; 23 | reg pie_code; 24 | reg clk_dpie; 25 | reg rst; 26 | 27 | 28 | // --- output --- 29 | wire bs_data; 30 | wire package_complete; 31 | wire crc_check_pass; 32 | 33 | 34 | // --- variable --- 35 | reg [59:0]data_i; 36 | reg [59:0]data_j; 37 | integer i; 38 | integer j; 39 | 40 | 41 | parameter half_of_tari = 3.125; // Tari = 6.25 us in this Tag design 42 | parameter gclk_T = 5; // frequency of global clock signal generated by multivibrator = 200 KHz 43 | 44 | 45 | bb_proc uut 46 | ( 47 | .bs_data(bs_data), 48 | .package_complete(package_complete), 49 | .crc_check_pass(crc_check_pass), 50 | .clk_200K(clk_200K), 51 | .pie_code(pie_code), 52 | .clk_dpie(clk_dpie), 53 | .rst(rst) 54 | ); 55 | 56 | 57 | initial begin 58 | $sdf_annotate(`SDF_FILE); 59 | end 60 | 61 | 62 | // --- clock signal in 200 KHz generated by multivibrator --- 63 | initial begin 64 | clk_200K = 1'b0; 65 | #(100 + 12.5 + 6.25 + half_of_tari); 66 | clk_200K = 1'b1; 67 | while(1) #(gclk_T / 2.0) clk_200K = ~clk_200K; 68 | end 69 | 70 | 71 | // --- PIE code --- 72 | initial begin 73 | pie_code = 1'b1; 74 | 75 | #100; 76 | frame_sync_pie; 77 | // Select command 78 | // 1010_100_100_01_00011011_00001011_01110001110_1_1011101100000001 79 | data_i = 56'b1010_100_100_01_00011011_00001011_01110001110_1_1011101100000001; 80 | for(i=56; i!=0; i=i-1) begin 81 | if(data_i[i-1]) pie_1; 82 | else pie_0; 83 | end 84 | 85 | #100; 86 | frame_sync_pie; 87 | // Query command 88 | // 1000_0_01_1_10_01_0_0011_01000 89 | data_i = 22'b1000_0_01_1_10_01_0_0011_01000; 90 | for(i=22; i!=0; i=i-1) begin 91 | if(data_i[i-1]) pie_1; 92 | else pie_0; 93 | end 94 | 95 | #100; 96 | frame_sync_pie; 97 | // QueryAdjust command 98 | // 1001_01_011 99 | data_i = 9'b1001_01_011; 100 | for(i=9; i!=0; i=i-1) begin 101 | if(data_i[i-1]) pie_1; 102 | else pie_0; 103 | end 104 | 105 | #100; 106 | frame_sync_pie; 107 | // QueryRep command 108 | // 00_01 109 | data_i = 4'b00_01; 110 | for(i=4; i!=0; i=i-1) begin 111 | if(data_i[i-1]) pie_1; 112 | else pie_0; 113 | end 114 | 115 | #100; 116 | frame_sync_pie; 117 | // QueryRep command 118 | // 00_01 119 | data_i = 4'b00_01; 120 | for(i=4; i!=0; i=i-1) begin 121 | if(data_i[i-1]) pie_1; 122 | else pie_0; 123 | end 124 | /* 125 | #2100; 126 | frame_sync_pie; 127 | // NAK command 128 | // 11000000 129 | data_i = 8'b11000000; 130 | for(i=8; i!=0; i=i-1) begin 131 | if(data_i[i-1]) pie_1; 132 | else pie_0; 133 | end 134 | */ 135 | #2100; 136 | frame_sync_pie; 137 | // ACK command 138 | // 01_0000010111111100 139 | data_i = 18'b01_0000010111111100; 140 | for(i=18; i!=0; i=i-1) begin 141 | if(data_i[i-1]) pie_1; 142 | else pie_0; 143 | end 144 | 145 | #3300; 146 | frame_sync_pie; 147 | // Req_RN command 148 | // 11000001_0000010111111100_1111001111000010 149 | data_i = 40'b11000001_0000010111111100_1111001111000010; 150 | for(i=40; i!=0; i=i-1) begin 151 | if(data_i[i-1]) pie_1; 152 | else pie_0; 153 | end 154 | 155 | #3000; 156 | frame_sync_pie; 157 | // Read command 158 | // 11000010_00_00000000_00000010_0000101111111000_1010101110001111 159 | data_i = 58'b11000010_00_00000000_00000010_0000101111111000_1010101110001111; 160 | for(i=58; i!=0; i=i-1) begin 161 | if(data_i[i-1]) pie_1; 162 | else pie_0; 163 | end 164 | 165 | #5000; 166 | frame_sync_pie; 167 | // Lock command 168 | // 11000101_11000000001100000000_0000101111111000_0100001111010101 169 | data_i = 60'b11000101_11000000001100000000_0000101111111000_0100001111010101; 170 | for(i=60; i!=0; i=i-1) begin 171 | if(data_i[i-1]) pie_1; 172 | else pie_0; 173 | end 174 | 175 | #3000; 176 | frame_sync_pie; 177 | // Read command 178 | // 11000010_00_00000000_00000010_0000101111111000_1010101110001111 179 | data_i = 58'b11000010_00_00000000_00000010_0000101111111000_1010101110001111; 180 | for(i=58; i!=0; i=i-1) begin 181 | if(data_i[i-1]) pie_1; 182 | else pie_0; 183 | end 184 | 185 | 186 | // Kill procedure 187 | // begin in the Open or Secured state 188 | // Req_RN -> Kill -> Req_RN -> Kill 189 | #2500; 190 | frame_sync_pie; 191 | // Req_RN command 192 | // 11000001_0000101111111000_1001000001001001 193 | data_i = 40'b11000001_0000101111111000_1001000001001001; 194 | for(i=40; i!=0; i=i-1) begin 195 | if(data_i[i-1]) pie_1; 196 | else pie_0; 197 | end 198 | #3000; 199 | frame_sync_pie; 200 | // Kill command 201 | // 11000100_1100010010100111_000_0000101111111000_0110101010101101 202 | data_i = 59'b11000100_1100010010100111_000_0000101111111000_0110101010101101; 203 | for(i=59; i!=0; i=i-1) begin 204 | if(data_i[i-1]) pie_1; 205 | else pie_0; 206 | end 207 | #3000; 208 | frame_sync_pie; 209 | // Req_RN command 210 | // 11000001_0000101111111000_1001000001001001 211 | data_i = 40'b11000001_0000101111111000_1001000001001001; 212 | for(i=40; i!=0; i=i-1) begin 213 | if(data_i[i-1]) pie_1; 214 | else pie_0; 215 | end 216 | #3000; 217 | frame_sync_pie; 218 | // Kill command 219 | // 11000100_0010100100101100_000_0000101111111000_1110110011110110 220 | data_i = 59'b11000100_0010100100101100_000_0000101111111000_1110110011110110; 221 | for(i=59; i!=0; i=i-1) begin 222 | if(data_i[i-1]) pie_1; 223 | else pie_0; 224 | end 225 | end 226 | 227 | 228 | // --- Delayed PIE code --- 229 | initial begin 230 | clk_dpie = 1; 231 | 232 | #(100 + half_of_tari + 1); 233 | frame_sync_dpie; 234 | data_j = 56'b1010_100_100_01_00011011_00001011_01110001110_1_1011101100000001; 235 | for(j=56; j!=0; j=j-1) begin 236 | if(data_j[j-1]) dpie_1; 237 | else dpie_0; 238 | end 239 | 240 | #100; 241 | frame_sync_dpie; 242 | data_j = 22'b1000_0_01_1_10_01_0_0011_01000; 243 | for(j=22; j!=0; j=j-1) begin 244 | if(data_j[j-1]) dpie_1; 245 | else dpie_0; 246 | end 247 | 248 | #100; 249 | frame_sync_dpie; 250 | data_j = 9'b1001_01_011; 251 | for(j=9; j!=0; j=j-1) begin 252 | if(data_j[j-1]) dpie_1; 253 | else dpie_0; 254 | end 255 | 256 | #100; 257 | frame_sync_dpie; 258 | data_j = 4'b00_01; 259 | for(j=4; j!=0; j=j-1) begin 260 | if(data_j[j-1]) dpie_1; 261 | else dpie_0; 262 | end 263 | 264 | #100; 265 | frame_sync_dpie; 266 | data_j = 4'b00_01; 267 | for(j=4; j!=0; j=j-1) begin 268 | if(data_j[j-1]) dpie_1; 269 | else dpie_0; 270 | end 271 | /* 272 | #2100; 273 | frame_sync_dpie; 274 | data_j = 8'b11000000; 275 | for(j=8; j!=0; j=j-1) begin 276 | if(data_j[j-1]) dpie_1; 277 | else dpie_0; 278 | end 279 | */ 280 | #2100; 281 | frame_sync_dpie; 282 | data_j = 18'b01_0000010111111100; 283 | for(j=18; j!=0; j=j-1) begin 284 | if(data_j[j-1]) dpie_1; 285 | else dpie_0; 286 | end 287 | 288 | #3300; 289 | frame_sync_dpie; 290 | data_j = 40'b11000001_0000010111111100_1111001111000010; 291 | for(j=40; j!=0; j=j-1) begin 292 | if(data_j[j-1]) dpie_1; 293 | else dpie_0; 294 | end 295 | 296 | #3000; 297 | frame_sync_dpie; 298 | data_j = 58'b11000010_00_00000000_00000010_0000101111111000_1010101110001111; 299 | for(j=58; j!=0; j=j-1) begin 300 | if(data_j[j-1]) dpie_1; 301 | else dpie_0; 302 | end 303 | 304 | #5000; 305 | frame_sync_dpie; 306 | data_j = 60'b11000101_11000000001100000000_0000101111111000_0100001111010101; 307 | for(j=60; j!=0; j=j-1) begin 308 | if(data_j[j-1]) dpie_1; 309 | else dpie_0; 310 | end 311 | 312 | #3000; 313 | frame_sync_dpie; 314 | data_j = 58'b11000010_00_00000000_00000010_0000101111111000_1010101110001111; 315 | for(j=58; j!=0; j=j-1) begin 316 | if(data_j[j-1]) dpie_1; 317 | else dpie_0; 318 | end 319 | 320 | #2500; 321 | frame_sync_dpie; 322 | data_j = 40'b11000001_0000101111111000_1001000001001001; 323 | for(j=40; j!=0; j=j-1) begin 324 | if(data_j[j-1]) dpie_1; 325 | else dpie_0; 326 | end 327 | #3000; 328 | frame_sync_dpie; 329 | data_j = 59'b11000100_1100010010100111_000_0000101111111000_0110101010101101; 330 | for(j=59; j!=0; j=j-1) begin 331 | if(data_j[j-1]) dpie_1; 332 | else dpie_0; 333 | end 334 | #3000; 335 | frame_sync_dpie; 336 | data_j = 40'b11000001_0000101111111000_1001000001001001; 337 | for(j=40; j!=0; j=j-1) begin 338 | if(data_j[j-1]) dpie_1; 339 | else dpie_0; 340 | end 341 | #3000; 342 | frame_sync_dpie; 343 | data_j = 59'b11000100_0010100100101100_000_0000101111111000_1110110011110110; 344 | for(j=59; j!=0; j=j-1) begin 345 | if(data_j[j-1]) dpie_1; 346 | else dpie_0; 347 | end 348 | 349 | #3000 $finish; 350 | end 351 | 352 | 353 | // --- reset signal generated by POR --- 354 | initial begin 355 | rst = 1'b0; 356 | #10 rst = 1'b1; 357 | #3 rst = 1'b0; 358 | end 359 | 360 | 361 | initial begin 362 | $fsdbDumpfile("bb_proc.fsdb"); 363 | $fsdbDumpvars; 364 | // $dumpfile("bb_proc.fsdb"); 365 | // $dumpvars; 366 | end 367 | 368 | 369 | // ---------------------------------------------- 370 | // task 371 | // ---------------------------------------------- 372 | 373 | 374 | // --- Frame-Sync --- 375 | task frame_sync_pie; 376 | begin 377 | pie_code = 1'b0; 378 | #12.5 pie_code = 1'b1; 379 | #half_of_tari pie_code = 1'b0; 380 | #half_of_tari pie_code = 1'b1; 381 | #(5 * half_of_tari) pie_code = 1'b0; 382 | #half_of_tari pie_code = 1'b1; 383 | end 384 | endtask 385 | 386 | task frame_sync_dpie; 387 | begin 388 | clk_dpie = 1'b0; 389 | #12.5 clk_dpie = 1'b1; 390 | #half_of_tari clk_dpie = 1'b0; 391 | #half_of_tari clk_dpie = 1'b1; 392 | #(5 * half_of_tari) clk_dpie = 1'b0; 393 | #half_of_tari clk_dpie = 1'b1; 394 | end 395 | endtask 396 | 397 | 398 | // --- PIE symbol 0 --- 399 | task pie_0; 400 | begin 401 | #half_of_tari pie_code = 1'b0; 402 | #half_of_tari pie_code = 1'b1; 403 | end 404 | endtask 405 | 406 | task dpie_0; 407 | begin 408 | #half_of_tari clk_dpie = 1'b0; 409 | #half_of_tari clk_dpie = 1'b1; 410 | end 411 | endtask 412 | 413 | 414 | // --- PIE symbol 1 --- 415 | task pie_1; 416 | begin 417 | #(3 * half_of_tari) pie_code = 1'b0; 418 | #half_of_tari pie_code = 1'b1; 419 | end 420 | endtask 421 | 422 | task dpie_1; 423 | begin 424 | #(3 * half_of_tari) clk_dpie = 1'b0; 425 | #half_of_tari clk_dpie = 1'b1; 426 | end 427 | endtask 428 | 429 | 430 | endmodule 431 | -------------------------------------------------------------------------------- /cmd_proc.v: -------------------------------------------------------------------------------- 1 | /* 2 | * Command Processor 3 | * 4 | * Process the received command and then do the action corresponding to the command and present state 5 | * 6 | * Control almost all enable signals of the baseband processor 7 | * 8 | * This module has the greatest immediate power dissipation, because of the huge computing of combinational logic 9 | * 10 | * By Operand Isolation technique save the power dissipation and reduce the max. immediate power 11 | * 12 | * This design of baseband processor is improved by TSMC 0.18 um CMOS standard process 13 | * it does not support EEPROM, so we chose ROM to be the baseband processor's memory 14 | * because we use ROM to be the memory, we are not able to verify the Write command 15 | */ 16 | 17 | 18 | `timescale 1us / 1ns 19 | 20 | 21 | module cmd_proc 22 | ( 23 | output reg reply_data, 24 | output reg reply_complete, 25 | output reg dr, 26 | output reg [1:0]m, 27 | output reg trext, 28 | output reg en_2nd_clk_cp, 29 | output reg en_tx, 30 | output reg en_prng_idol, 31 | output reg en_prng_act, 32 | output reg en_crc16_for_rpy, 33 | output reg en_if, 34 | output reg [18:0]addr, 35 | input clk_cp, 36 | input clk_frm, 37 | input rst_n, 38 | input rst_for_new_package, 39 | input [7:0]cmd, 40 | input [51:0]param, 41 | input crc_check_pass, 42 | input [15:0]prn, 43 | input pre_p_complete, 44 | input p_complete, 45 | input rd_data, 46 | input rd_complete 47 | ); 48 | 49 | 50 | // --- mandatory commands of EPC Gen2 protocol --- 51 | parameter QueryRep = 8'b0000_1100; 52 | parameter ACK = 8'b0000_1101; 53 | parameter Query = 8'b0011_1000; 54 | parameter QueryAdjust = 8'b0011_1001; 55 | parameter Select = 8'b0011_1010; 56 | parameter NAK = 8'b1100_0000; 57 | parameter Req_RN = 8'b1100_0001; 58 | parameter Read = 8'b1100_0010; 59 | //parameter Write = 8'b1100_0011; 60 | parameter Kill = 8'b1100_0100; 61 | parameter Lock = 8'b1100_0101; 62 | 63 | 64 | // --- working states --- 65 | parameter Ready = 4'h0; 66 | parameter Sloting = 4'h1; 67 | parameter Arbitrate = 4'h2; 68 | parameter Reply = 4'h3; 69 | parameter Acknowledged = 4'h4; 70 | parameter SlotTran = 4'h5; 71 | parameter Open = 4'h6; 72 | parameter Secured = 4'h7; 73 | parameter Killing = 4'h8; 74 | parameter Killed = 4'h9; 75 | 76 | 77 | // --- actions --- 78 | parameter do_nothing = 5'h00; 79 | parameter set_sl_or_if = 5'h01; 80 | parameter init_inventory = 5'h02; 81 | parameter adj_q = 5'h03; 82 | parameter dec_slot = 5'h04; 83 | parameter bs_new_rn16 = 5'h05; 84 | parameter reply_ack = 5'h06; 85 | parameter bs_new_rn16_tran_if = 5'h07; 86 | parameter adj_q_tran_if = 5'h08; 87 | parameter dec_slot_tran_if = 5'h09; 88 | parameter tran_if = 5'h0a; 89 | parameter gen_and_bs_new_handle = 5'h0b; 90 | parameter bs_new_rn16_crc16 = 5'h0c; 91 | parameter bs_read_data = 5'h0d; 92 | parameter bs_handle = 5'h0e; 93 | parameter bs_header_kill = 5'h0f; 94 | parameter bs_header_lock = 5'h10; 95 | parameter bs_error_code = 5'h11; 96 | 97 | 98 | wire clk_cp_n; 99 | 100 | reg [7:0]cmd_checked; // checked command 101 | reg [3:0]ps; // present state 102 | reg [3:0]ns; // next state 103 | reg [4:0]act; // action 104 | reg mch; // matching/not-matching 105 | reg [7:0]ptr; // pointer of Select command (bit addressing) 106 | reg trct; // parameter Truncate of Select command 107 | reg [1:0]sl; // SL flag 108 | reg if_s0; // inventoried flag of session 0 109 | reg if_s1; // inventoried flag of session 1 110 | reg if_s2; // inventoried flag of session 2 111 | reg if_s3; // inventoried flag of session 3 112 | //reg dr; // divide ratio 113 | //reg [1:0]m; // cycles per symbol 114 | //reg trext; // pilot tone 115 | reg [1:0]session; // tag's 4 sessions 116 | reg [3:0]q; // # of bits of slot 117 | reg [14:0]slot; // slot counter 118 | reg [9:0]lock_act; // action of Lock command 119 | reg tid_lock; 120 | reg epc_lock; 121 | reg accs_lock; 122 | reg kill_lock; 123 | reg [4:0]act_reg; 124 | reg [15:0]rn16; // 16-bit random number for backscattering new RN16 125 | reg [15:0]handle; // 16-bit random number for backscattering "handle" 126 | reg en_if_d; 127 | reg [4:0]r_cnt; // reply counter 128 | reg [4:0]r_end; // end point of reply counter 129 | 130 | 131 | // --- check the receieved command --- 132 | always@(*) begin 133 | if(cmd == Query | cmd == Select | cmd == Req_RN | cmd == Read | cmd == Kill | cmd == Lock) begin 134 | if(crc_check_pass) cmd_checked = cmd; 135 | else cmd_checked = 8'h00; 136 | end 137 | else cmd_checked = cmd; 138 | end 139 | 140 | 141 | // --- state register --- 142 | always@(posedge clk_cp or negedge rst_n) begin 143 | if(~rst_n) ps <= Ready; 144 | else ps <= ns; 145 | end 146 | 147 | 148 | // --- next state logic --- 149 | always@(*) begin 150 | case(ps) 151 | Ready : if(cmd_checked == Query) begin 152 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) ns = Sloting; 153 | else ns = Ready; 154 | end 155 | else ns = Ready; 156 | 157 | Sloting : if(slot == 15'b0) ns = Reply; 158 | else ns = Arbitrate; 159 | 160 | Arbitrate : if(cmd_checked == Query) begin 161 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) ns = Sloting; 162 | else ns = Ready; 163 | end 164 | else if(cmd_checked == QueryRep) begin 165 | if(param[1:0] == session) ns = Sloting; 166 | else ns = Arbitrate; 167 | end 168 | else if(cmd_checked == QueryAdjust) begin 169 | if(param[4:3] == session) ns = Sloting; 170 | else ns = Arbitrate; 171 | end 172 | else if(cmd_checked == Select) begin 173 | if(param[51:49] == 3'b101 | param[51:49] == 3'b110 | param[51:49] == 3'b111) ns = Arbitrate; 174 | else if(param[45:44] == 2'b00 & param[43:36] != 8'b0) ns = Arbitrate; 175 | else if(param[45:44] == 2'b00 & param[35:28] != 8'b0000_1000) ns = Arbitrate; 176 | else if(param[16] & (param[51:49] != 3'b100 | param[45:44] != 2'b01)) ns = Arbitrate; 177 | else ns = Ready; 178 | end 179 | else ns = Arbitrate; 180 | 181 | Reply : if(cmd_checked == Query) begin 182 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) ns = Sloting; 183 | else ns = Ready; 184 | end 185 | else if(cmd_checked == QueryRep) begin 186 | if(param[1:0] == session) ns = Arbitrate; 187 | else ns = Reply; 188 | end 189 | else if(cmd_checked == QueryAdjust) begin 190 | if(param[4:3] == session) ns = Sloting; 191 | else ns = Reply; 192 | end 193 | else if(cmd_checked == ACK) begin 194 | if(param[15:0] == rn16) ns = Acknowledged; 195 | else ns = Arbitrate; 196 | end 197 | else if(cmd_checked == NAK) ns = Arbitrate; 198 | else if(cmd_checked == Req_RN) ns = Arbitrate; 199 | else if(cmd_checked == Select) begin 200 | if(param[51:49] == 3'b101 | param[51:49] == 3'b110 | param[51:49] == 3'b111) ns = Reply; 201 | else if(param[45:44] == 2'b00 & param[43:36] != 8'b0) ns = Reply; 202 | else if(param[45:44] == 2'b00 & param[35:28] != 8'b0000_1000) ns = Reply; 203 | else if(param[16] & (param[51:49] != 3'b100 | param[45:44] != 2'b01)) ns = Reply; 204 | else ns = Ready; 205 | end 206 | else if(cmd_checked == Read) ns = Arbitrate; 207 | else if(cmd_checked == Kill) ns = Arbitrate; 208 | else if(cmd_checked == Lock) ns = Arbitrate; 209 | else ns = Reply; 210 | 211 | Acknowledged : if(cmd_checked == Query) begin 212 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) ns = SlotTran; 213 | else ns = Ready; 214 | end 215 | else if(cmd_checked == QueryRep) begin 216 | if(param[1:0] == session) ns = Ready; 217 | else ns = Acknowledged; 218 | end 219 | else if(cmd_checked == QueryAdjust) begin 220 | if(param[4:3] == session) ns = Ready; 221 | else ns = Acknowledged; 222 | end 223 | else if(cmd_checked == ACK) begin 224 | if(param[15:0] == rn16) ns = Acknowledged; 225 | else ns = Arbitrate; 226 | end 227 | else if(cmd_checked == NAK) ns = Arbitrate; 228 | else if(cmd_checked == Req_RN) begin 229 | if(param[31:16] == rn16) ns = Secured; 230 | else ns = Acknowledged; 231 | end 232 | else if(cmd_checked == Select) begin 233 | if(param[51:49] == 3'b101 | param[51:49] == 3'b110 | param[51:49] == 3'b111) ns = Acknowledged; 234 | else if(param[45:44] == 2'b00 & param[43:36] != 8'b0) ns = Acknowledged; 235 | else if(param[45:44] == 2'b00 & param[35:28] != 8'b0000_1000) ns = Acknowledged; 236 | else if(param[16] & (param[51:49] != 3'b100 | param[45:44] != 2'b01)) ns = Acknowledged; 237 | else ns = Ready; 238 | end 239 | else if(cmd_checked == Read) ns = Arbitrate; 240 | else if(cmd_checked == Kill) ns = Arbitrate; 241 | else if(cmd_checked == Lock) ns = Arbitrate; 242 | else ns = Acknowledged; 243 | 244 | SlotTran : if(slot == 15'b0) ns = Reply; 245 | else ns = Arbitrate; 246 | 247 | Open : if(cmd_checked == Query) begin 248 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) ns = SlotTran; 249 | else ns = Ready; 250 | end 251 | else if(cmd_checked == QueryRep) begin 252 | if(param[1:0] == session) ns = Ready; 253 | else ns = Open; 254 | end 255 | else if(cmd_checked == QueryAdjust) begin 256 | if(param[4:3] == session) ns = Ready; 257 | else ns = Open; 258 | end 259 | else if(cmd_checked == ACK) begin 260 | if(param[15:0] == handle) ns = Open; 261 | else ns = Arbitrate; 262 | end 263 | else if(cmd_checked == NAK) ns = Arbitrate; 264 | else if(cmd_checked == Req_RN) ns = Open; 265 | else if(cmd_checked == Select) begin 266 | if(param[51:49] == 3'b101 | param[51:49] == 3'b110 | param[51:49] == 3'b111) ns = Open; 267 | else if(param[45:44] == 2'b00 & param[43:36] != 8'b0) ns = Open; 268 | else if(param[45:44] == 2'b00 & param[35:28] != 8'b0000_1000) ns = Open; 269 | else if(param[16] & (param[51:49] != 3'b100 | param[45:44] != 2'b01)) ns = Open; 270 | else ns = Ready; 271 | end 272 | else if(cmd_checked == Read) ns = Open; 273 | else if(cmd_checked == Kill) begin 274 | // the first 16 bits kill password is d357 275 | if((param[50:35] ^ rn16) == 16'hd357 & param[31:16] == handle) ns = Killing; 276 | else ns = Arbitrate; 277 | end 278 | else if(cmd_checked == Lock) ns = Open; 279 | else ns = Open; 280 | 281 | Secured : if(cmd_checked == Query) begin 282 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) ns = SlotTran; 283 | else ns = Ready; 284 | end 285 | else if(cmd_checked == QueryRep) begin 286 | if(param[1:0] == session) ns = Ready; 287 | else ns = Secured; 288 | end 289 | else if(cmd_checked == QueryAdjust) begin 290 | if(param[4:3] == session) ns = Ready; 291 | else ns = Secured; 292 | end 293 | else if(cmd_checked == ACK) begin 294 | if(param[15:0] == handle) ns = Secured; 295 | else ns = Arbitrate; 296 | end 297 | else if(cmd_checked == NAK) ns = Arbitrate; 298 | else if(cmd_checked == Req_RN) ns = Secured; 299 | else if(cmd_checked == Select) begin 300 | if(param[51:49] == 3'b101 | param[51:49] == 3'b110 | param[51:49] == 3'b111) ns = Secured; 301 | else if(param[45:44] == 2'b00 & param[43:36] != 8'b0) ns = Secured; 302 | else if(param[45:44] == 2'b00 & param[35:28] != 8'b0000_1000) ns = Secured; 303 | else if(param[16] & (param[51:49] != 3'b100 | param[45:44] != 2'b01)) ns = Secured; 304 | else ns = Ready; 305 | end 306 | else if(cmd_checked == Read) ns = Secured; 307 | else if(cmd_checked == Kill) begin 308 | if((param[50:35] ^ rn16) == 16'hd357 & param[31:16] == handle) ns = Killing; 309 | else ns = Arbitrate; 310 | end 311 | else if(cmd_checked == Lock) ns = Secured; 312 | else ns = Secured; 313 | 314 | Killing : if(cmd_checked == Query) begin 315 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) ns = SlotTran; 316 | else ns = Ready; 317 | end 318 | else if(cmd_checked == Req_RN) ns = Killing; 319 | else if(cmd_checked == Kill) begin 320 | if((param[50:35] ^ rn16) == 16'h06cc & param[31:16] == handle) ns = Killed; 321 | else ns = Arbitrate; 322 | end 323 | else ns = Arbitrate; 324 | 325 | Killed : ns = Killed; 326 | 327 | default : ns = Arbitrate; 328 | endcase 329 | end 330 | 331 | 332 | // --- output logic --- 333 | always@(*) begin 334 | case(ps) 335 | Ready : if(cmd_checked == Query) begin 336 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) act = init_inventory; 337 | else act = do_nothing; 338 | end 339 | else if(cmd_checked == Select) begin 340 | if(param[51:49] == 3'b101 | param[51:49] == 3'b110 | param[51:49] == 3'b111) act = do_nothing; 341 | else if(param[45:44] == 2'b00 & param[43:36] != 8'b0) act = do_nothing; 342 | else if(param[45:44] == 2'b00 & param[35:28] != 8'b0000_1000) act = do_nothing; 343 | else if(param[16] & (param[51:49] != 3'b100 | param[45:44] != 2'b01)) act = do_nothing; 344 | else act = set_sl_or_if; 345 | end 346 | else act = do_nothing; 347 | 348 | Sloting : if(slot == 15'b0) act = bs_new_rn16; 349 | else act = do_nothing; 350 | 351 | Arbitrate : if(cmd_checked == Query) begin 352 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) act = init_inventory; 353 | else act = do_nothing; 354 | end 355 | else if(cmd_checked == QueryRep) begin 356 | if(param[1:0] == session) act = dec_slot; 357 | else act = do_nothing; 358 | end 359 | else if(cmd_checked == QueryAdjust) begin 360 | if(param[4:3] == session) act = adj_q; 361 | else act = do_nothing; 362 | end 363 | else if(cmd_checked == Select) begin 364 | if(param[51:49] == 3'b101 | param[51:49] == 3'b110 | param[51:49] == 3'b111) act = do_nothing; 365 | else if(param[45:44] == 2'b00 & param[43:36] != 8'b0) act = do_nothing; 366 | else if(param[45:44] == 2'b00 & param[35:28] != 8'b0000_1000) act = do_nothing; 367 | else if(param[16] & (param[51:49] != 3'b100 | param[45:44] != 2'b01)) act = do_nothing; 368 | else act = set_sl_or_if; 369 | end 370 | else act = do_nothing; 371 | 372 | Reply : if(cmd_checked == Query) begin 373 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) act = init_inventory; 374 | else act = do_nothing; 375 | end 376 | else if(cmd_checked == QueryRep) begin 377 | if(param[1:0] == session) act = dec_slot; 378 | else act = do_nothing; 379 | end 380 | else if(cmd_checked == QueryAdjust) begin 381 | if(param[4:3] == session) act = adj_q; 382 | else act = do_nothing; 383 | end 384 | else if(cmd_checked == ACK) begin 385 | if(param[15:0] == rn16) act = reply_ack; 386 | else act = do_nothing; 387 | end 388 | else if(cmd_checked == Select) begin 389 | if(param[51:49] == 3'b101 | param[51:49] == 3'b110 | param[51:49] == 3'b111) act = do_nothing; 390 | else if(param[45:44] == 2'b00 & param[43:36] != 8'b0) act = do_nothing; 391 | else if(param[45:44] == 2'b00 & param[35:28] != 8'b0000_1000) act = do_nothing; 392 | else if(param[16] & (param[51:49] != 3'b100 | param[45:44] != 2'b01)) act = do_nothing; 393 | else act = set_sl_or_if; 394 | end 395 | else act = do_nothing; 396 | 397 | Acknowledged : if(cmd_checked == Query) begin 398 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) act = init_inventory; 399 | else act = do_nothing; 400 | end 401 | else if(cmd_checked == QueryRep) begin 402 | if(param[1:0] == session) act = dec_slot_tran_if; 403 | else act = do_nothing; 404 | end 405 | else if(cmd_checked == QueryAdjust) begin 406 | if(param[4:3] == session) act = adj_q_tran_if; 407 | else act = do_nothing; 408 | end 409 | else if(cmd_checked == ACK) begin 410 | if(param[15:0] == rn16) act = reply_ack; 411 | else act = do_nothing; 412 | end 413 | else if(cmd_checked == Req_RN) begin 414 | if(param[31:16] == rn16) act = gen_and_bs_new_handle; 415 | else act = do_nothing; 416 | end 417 | else if(cmd_checked == Select) begin 418 | if(param[51:49] == 3'b101 | param[51:49] == 3'b110 | param[51:49] == 3'b111) act = do_nothing; 419 | else if(param[45:44] == 2'b00 & param[43:36] != 8'b0) act = do_nothing; 420 | else if(param[45:44] == 2'b00 & param[35:28] != 8'b0000_1000) act = do_nothing; 421 | else if(param[16] & (param[51:49] != 3'b100 | param[45:44] != 2'b01)) act = do_nothing; 422 | else act = set_sl_or_if; 423 | end 424 | else act = do_nothing; 425 | 426 | SlotTran : if(param[11:10] == session) begin 427 | if(slot == 15'b0) act = bs_new_rn16_tran_if; 428 | else act = tran_if; 429 | end 430 | else act = do_nothing; 431 | 432 | Open : if(cmd_checked == Query) begin 433 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) act = init_inventory; 434 | else act = do_nothing; 435 | end 436 | else if(cmd_checked == QueryRep) begin 437 | if(param[1:0] == session) act = dec_slot_tran_if; 438 | else act = do_nothing; 439 | end 440 | else if(cmd_checked == QueryAdjust) begin 441 | if(param[4:3] == session) act = adj_q_tran_if; 442 | else act = do_nothing; 443 | end 444 | else if(cmd_checked == ACK) begin 445 | if(param[15:0] == rn16) act = reply_ack; 446 | else act = do_nothing; 447 | end 448 | else if(cmd_checked == Req_RN) begin 449 | if(param[31:16] == handle) act = bs_new_rn16_crc16; 450 | else act = do_nothing; 451 | end 452 | else if(cmd_checked == Select) begin 453 | if(param[51:49] == 3'b101 | param[51:49] == 3'b110 | param[51:49] == 3'b111) act = do_nothing; 454 | else if(param[45:44] == 2'b00 & param[43:36] != 8'b0) act = do_nothing; 455 | else if(param[45:44] == 2'b00 & param[35:28] != 8'b0000_1000) act = do_nothing; 456 | else if(param[16] & (param[51:49] != 3'b100 | param[45:44] != 2'b01)) act = do_nothing; 457 | else act = set_sl_or_if; 458 | end 459 | else if(cmd_checked == Read) begin 460 | case(param[49:48]) 461 | 2'b00 : if(param[39:32] == 8'h0) begin 462 | if(~kill_lock & ~accs_lock & param[47:40] < 8'h3) act = bs_read_data; 463 | else act = bs_error_code; 464 | end 465 | else begin 466 | if((~kill_lock & param[47:40] < 8'h2 & (param[47:40] + param[39:32] < 8'h3)) | 467 | (~accs_lock & param[47:40] < 8'h4 & param[47:40] > 8'h1 & (param[47:40] + param[39:32] < 8'h5)) | 468 | (~kill_lock & ~accs_lock & (param[47:40] + param[39:32] < 8'h5))) act = bs_read_data; 469 | else act = bs_error_code; 470 | end 471 | 2'b01 : if(param[39:32] == 8'h0) begin 472 | if(~epc_lock & (param[47:40] < 8'h15)) act = bs_read_data; 473 | else act = bs_error_code; 474 | end 475 | else begin 476 | if(~epc_lock & ((param[47:40] + param[39:32]) < 8'hf)) act = bs_read_data; 477 | else act = bs_error_code; 478 | end 479 | 2'b10 : if(param[39:32] == 8'h0) begin 480 | if(~tid_lock & param[47:40] < 8'h2) act = bs_read_data; 481 | else act = bs_error_code; 482 | end 483 | else begin 484 | if(~tid_lock & ((param[47:40] + param[39:32]) < 8'h3)) act = bs_read_data; 485 | else act = bs_error_code; 486 | end 487 | 2'b11 : act = bs_error_code; 488 | endcase 489 | end 490 | else if(cmd_checked == Kill) begin 491 | if((param[50:35] ^ rn16) == 16'hd357 & param[31:16] == handle) act = bs_handle; 492 | else act = do_nothing; 493 | end 494 | else act = do_nothing; 495 | 496 | Secured : if(cmd_checked == Query) begin 497 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) act = init_inventory; 498 | else act = do_nothing; 499 | end 500 | else if(cmd_checked == QueryRep) begin 501 | if(param[1:0] == session) act = dec_slot_tran_if; 502 | else act = do_nothing; 503 | end 504 | else if(cmd_checked == QueryAdjust) begin 505 | if(param[4:3] == session) act = adj_q_tran_if; 506 | else act = do_nothing; 507 | end 508 | else if(cmd_checked == ACK) begin 509 | if(param[15:0] == rn16) act = reply_ack; 510 | else act = do_nothing; 511 | end 512 | else if(cmd_checked == Req_RN) begin 513 | if(param[31:16] == handle) act = bs_new_rn16_crc16; 514 | else act = do_nothing; 515 | end 516 | else if(cmd_checked == Select) begin 517 | if(param[51:49] == 3'b101 | param[51:49] == 3'b110 | param[51:49] == 3'b111) act = do_nothing; 518 | else if(param[45:44] == 2'b00 & param[43:36] != 8'b0) act = do_nothing; 519 | else if(param[45:44] == 2'b00 & param[35:28] != 8'b0000_1000) act = do_nothing; 520 | else if(param[16] & (param[51:49] != 3'b100 | param[45:44] != 2'b01)) act = do_nothing; 521 | else act = set_sl_or_if; 522 | end 523 | else if(cmd_checked == Read) begin 524 | case(param[49:48]) 525 | 2'b00 : if(param[39:32] == 8'h0) begin 526 | if(~kill_lock & ~accs_lock & param[47:40] < 8'h3) act = bs_read_data; 527 | else act = bs_error_code; 528 | end 529 | else begin 530 | if((~kill_lock & param[47:40] < 8'h2 & (param[47:40] + param[39:32] < 8'h3)) | 531 | (~accs_lock & param[47:40] < 8'h4 & param[47:40] > 8'h1 & (param[47:40] + param[39:32] < 8'h5)) | 532 | (~kill_lock & ~accs_lock & (param[47:40] + param[39:32] < 8'h5))) act = bs_read_data; 533 | else act = bs_error_code; 534 | end 535 | 2'b01 : if(param[39:32] == 8'h0) begin 536 | if(~epc_lock & (param[47:40] < 8'h15)) act = bs_read_data; 537 | else act = bs_error_code; 538 | end 539 | else begin 540 | if(~epc_lock & ((param[47:40] + param[39:32]) < 8'hf)) act = bs_read_data; 541 | else act = bs_error_code; 542 | end 543 | 2'b10 : if(param[39:32] == 8'h0) begin 544 | if(~tid_lock & param[47:40] < 8'h2) act = bs_read_data; 545 | else act = bs_error_code; 546 | end 547 | else begin 548 | if(~tid_lock & ((param[47:40] + param[39:32]) < 8'h3)) act = bs_read_data; 549 | else act = bs_error_code; 550 | end 551 | 2'b11 : act = bs_error_code; 552 | endcase 553 | end 554 | else if(cmd_checked == Kill) begin 555 | if((param[50:35] ^ rn16) == 16'hd357 & param[31:16] == handle) act = bs_handle; 556 | else act = do_nothing; 557 | end 558 | else if(cmd_checked == Lock) begin 559 | if(param[43:42] != 2'b00 | (({param[50], param[40]} == 2'b10) & lock_act[8]) | (({param[48], param[38]} == 2'b10) & lock_act[6]) | (({param[46], param[36]} == 2'b10) & lock_act[4]) | (({param[44], param[34]} == 2'b10) & lock_act[2])) act = bs_error_code; 560 | else act = bs_header_lock; 561 | end 562 | else act = do_nothing; 563 | 564 | Killing : if(cmd_checked == Query) begin 565 | if((param[11:9] == {2'b00, if_s0} | param[11:9] == {2'b01, if_s1} | param[11:9] == {2'b10, if_s2} | param[11:9] == {2'b11, if_s3}) & (~param[13] | param[13:12] == sl)) act = init_inventory; 566 | else act = do_nothing; 567 | end 568 | else if(cmd_checked == Req_RN) begin 569 | if(param[31:16] == handle) act = bs_new_rn16_crc16; 570 | else act = do_nothing; 571 | end 572 | else if(cmd_checked == Kill) begin 573 | if((param[50:35] ^ rn16) == 16'h06cc & param[31:16] == handle) act = bs_header_kill; 574 | else act = do_nothing; 575 | end 576 | else act = do_nothing; 577 | 578 | Killed : act = do_nothing; 579 | 580 | default : act = do_nothing; 581 | endcase 582 | end 583 | 584 | 585 | // --- define matching/not-matching from Select command --- 586 | always@(*) begin 587 | if(act == set_sl_or_if) begin 588 | if(param[45:44] == 2'b01 & param[43:36] < 8'b1100_0000 & ((param[43:36] - param[35:28]) > 8'b0)) mch = 1'b1; 589 | else if(param[45:44] == 2'b10 & param[43:36] < 8'b0010_0000 & ((param[43:36] - param[35:28]) > 8'b0)) mch = 1'b1; 590 | end 591 | else mch = 1'b0; 592 | end 593 | 594 | 595 | // --- execute the actions --- 596 | always@(posedge clk_cp or negedge rst_n) begin 597 | if(~rst_n) ptr <= 8'b0; 598 | else if(act == set_sl_or_if) ptr <= param[43:36] - param[35:28]; 599 | end 600 | 601 | always@(posedge clk_cp or negedge rst_n) begin 602 | if(~rst_n) trct <= 1'b0; 603 | else if(act == set_sl_or_if) trct <= param[16]; 604 | end 605 | 606 | always@(posedge clk_cp or negedge rst_n) begin 607 | if(~rst_n) sl <= 2'b10; 608 | else if(act == set_sl_or_if & param[51:49] == 3'b100) begin 609 | if(mch) begin 610 | case(param[48:46]) 611 | 3'b000 : sl <= 2'b11; 612 | 3'b001 : sl <= 2'b11; 613 | 3'b011 : sl <= ~sl; 614 | 3'b100 : sl <= 2'b10; 615 | 3'b101 : sl <= 2'b10; 616 | endcase 617 | end 618 | else begin 619 | case(param[48:46]) 620 | 3'b000 : sl <= 2'b10; 621 | 3'b010 : sl <= 2'b10; 622 | 3'b100 : sl <= 2'b11; 623 | 3'b110 : sl <= 2'b11; 624 | 3'b111 : sl <= ~sl; 625 | endcase 626 | end 627 | end 628 | end 629 | 630 | always@(posedge clk_cp or negedge rst_n) begin 631 | if(~rst_n) if_s0 <= 1'b0; 632 | else if(act == set_sl_or_if & param[51:49] == 3'b000) begin 633 | if(mch) begin 634 | case(param[48:46]) 635 | 3'b000 : if_s0 <= 1'b0; 636 | 3'b001 : if_s0 <= 1'b0; 637 | 3'b011 : if_s0 <= ~if_s0; 638 | 3'b100 : if_s0 <= 1'b0; 639 | 3'b101 : if_s0 <= 1'b0; 640 | endcase 641 | end 642 | else begin 643 | case(param[48:46]) 644 | 3'b000 : if_s0 <= 1'b1; 645 | 3'b010 : if_s0 <= 1'b1; 646 | 3'b100 : if_s0 <= 1'b0; 647 | 3'b110 : if_s0 <= 1'b0; 648 | 3'b111 : if_s0 <= ~if_s0; 649 | endcase 650 | end 651 | end 652 | else if(act == bs_new_rn16_tran_if & session == 2'b00) if_s0 <= ~if_s0; 653 | else if(act == tran_if & session == 2'b00) if_s0 <= ~if_s0; 654 | else if(act == dec_slot_tran_if & session == 2'b00) if_s0 <= ~if_s0; 655 | else if(act == adj_q_tran_if & session == 2'b00) if_s0 <= ~if_s0; 656 | end 657 | 658 | always@(posedge clk_cp or negedge rst_n) begin 659 | if(~rst_n) if_s1 <= 1'b0; 660 | else if(act == set_sl_or_if & param[51:49] == 3'b001) begin 661 | if(mch) begin 662 | case(param[48:46]) 663 | 3'b000 : if_s1 <= 1'b0; 664 | 3'b001 : if_s1 <= 1'b0; 665 | 3'b011 : if_s1 <= ~if_s1; 666 | 3'b100 : if_s1 <= 1'b1; 667 | 3'b101 : if_s1 <= 1'b1; 668 | endcase 669 | end 670 | else begin 671 | case(param[48:46]) 672 | 3'b000 : if_s1 <= 1'b1; 673 | 3'b010 : if_s1 <= 1'b1; 674 | 3'b100 : if_s1 <= 1'b0; 675 | 3'b110 : if_s1 <= 1'b0; 676 | 3'b111 : if_s1 <= ~if_s1; 677 | endcase 678 | end 679 | end 680 | else if(act == bs_new_rn16_tran_if & session == 2'b01) if_s1 <= ~if_s1; 681 | else if(act == tran_if & session == 2'b01) if_s1 <= ~if_s1; 682 | else if(act == dec_slot_tran_if & session == 2'b01) if_s1 <= ~if_s1; 683 | else if(act == adj_q_tran_if & session == 2'b01) if_s1 <= ~if_s1; 684 | end 685 | 686 | always@(posedge clk_cp or negedge rst_n) begin 687 | if(~rst_n) if_s2 <= 1'b0; 688 | else if(act == set_sl_or_if & param[51:49] == 3'b010) begin 689 | if(mch) begin 690 | case(param[48:46]) 691 | 3'b000 : if_s2 <= 1'b0; 692 | 3'b001 : if_s2 <= 1'b0; 693 | 3'b011 : if_s2 <= ~if_s2; 694 | 3'b100 : if_s2 <= 1'b1; 695 | 3'b101 : if_s2 <= 1'b1; 696 | endcase 697 | end 698 | else begin 699 | case(param[48:46]) 700 | 3'b000 : if_s2 <= 1'b1; 701 | 3'b010 : if_s2 <= 1'b1; 702 | 3'b100 : if_s2 <= 1'b0; 703 | 3'b110 : if_s2 <= 1'b0; 704 | 3'b111 : if_s2 <= ~if_s2; 705 | endcase 706 | end 707 | end 708 | else if(act == bs_new_rn16_tran_if & session == 2'b10) if_s2 <= ~if_s2; 709 | else if(act == tran_if & session == 2'b10) if_s2 <= ~if_s2; 710 | else if(act == dec_slot_tran_if & session == 2'b10) if_s2 <= ~if_s2; 711 | else if(act == adj_q_tran_if & session == 2'b10) if_s2 <= ~if_s2; 712 | end 713 | 714 | always@(posedge clk_cp or negedge rst_n) begin 715 | if(~rst_n) if_s3 <= 1'b0; 716 | else if(act == set_sl_or_if & param[51:49] == 3'b011) begin 717 | if(mch) begin 718 | case(param[48:46]) 719 | 3'b000 : if_s3 <= 1'b0; 720 | 3'b001 : if_s3 <= 1'b0; 721 | 3'b011 : if_s3 <= ~if_s3; 722 | 3'b100 : if_s3 <= 1'b1; 723 | 3'b101 : if_s3 <= 1'b1; 724 | endcase 725 | end 726 | else begin 727 | case(param[48:46]) 728 | 3'b000 : if_s3 <= 1'b1; 729 | 3'b010 : if_s3 <= 1'b1; 730 | 3'b100 : if_s3 <= 1'b0; 731 | 3'b110 : if_s3 <= 1'b0; 732 | 3'b111 : if_s3 <= ~if_s3; 733 | endcase 734 | end 735 | end 736 | else if(act == bs_new_rn16_tran_if & session == 2'b11) if_s3 <= ~if_s3; 737 | else if(act == tran_if & session == 2'b11) if_s3 <= ~if_s3; 738 | else if(act == dec_slot_tran_if & session == 2'b11) if_s3 <= ~if_s3; 739 | else if(act == adj_q_tran_if & session == 2'b11) if_s3 <= ~if_s3; 740 | end 741 | 742 | always@(posedge clk_cp or negedge rst_n) begin 743 | if(~rst_n) dr <= 1'b0; 744 | else if(act == init_inventory) dr <= param[17]; 745 | end 746 | 747 | always@(posedge clk_cp or negedge rst_n) begin 748 | if(~rst_n) m <= 2'b00; 749 | else if(act == init_inventory) m <= param[16:15]; 750 | end 751 | 752 | always@(posedge clk_cp or negedge rst_n) begin 753 | if(~rst_n) trext <= 1'b0; 754 | else if(act == init_inventory) trext <= param[14]; 755 | end 756 | 757 | always@(posedge clk_cp or negedge rst_n) begin 758 | if(~rst_n) session <= 2'b00; 759 | else if(act == init_inventory) session <= param[11:10]; 760 | end 761 | 762 | always@(posedge clk_cp or negedge rst_n) begin 763 | if(~rst_n) q <= 4'b0; 764 | else if(act == init_inventory) q <= param[8:5]; 765 | else if(act == adj_q | act == adj_q_tran_if) begin 766 | if(param[2:0] == 3'b110) q <= q + 4'b1; 767 | else if(param[2:0] == 3'b011) q <= q - 4'b1; 768 | end 769 | end 770 | 771 | always@(posedge clk_cp or negedge rst_n) begin 772 | if(~rst_n) slot <= 15'h2ac7; 773 | else if(act == init_inventory) begin 774 | case(param[8:5]) 775 | 4'h0 : slot <= 15'b0; 776 | 4'h1 : slot <= {14'b0, prn[0]}; 777 | 4'h2 : slot <= {13'b0, prn[1:0]}; 778 | 4'h3 : slot <= {12'b0, prn[2:0]}; 779 | 4'h4 : slot <= {11'b0, prn[3:0]}; 780 | 4'h5 : slot <= {10'b0, prn[4:0]}; 781 | 4'h6 : slot <= {9'b0, prn[5:0]}; 782 | 4'h7 : slot <= {8'b0, prn[6:0]}; 783 | 4'h8 : slot <= {7'b0, prn[7:0]}; 784 | 4'h9 : slot <= {6'b0, prn[8:0]}; 785 | 4'ha : slot <= {5'b0, prn[9:0]}; 786 | 4'hb : slot <= {4'b0, prn[10:0]}; 787 | 4'hc : slot <= {3'b0, prn[11:0]}; 788 | 4'hd : slot <= {2'b0, prn[12:0]}; 789 | 4'he : slot <= {1'b0, prn[13:0]}; 790 | 4'hf : slot <= prn[14:0]; 791 | endcase 792 | end 793 | else if(act == adj_q | act == adj_q_tran_if) begin 794 | if(param[2:0] == 3'b110) begin 795 | case(q) 796 | 4'hf : slot <= 15'b0; 797 | 4'h0 : slot <= {14'b0, prn[0]}; 798 | 4'h1 : slot <= {13'b0, prn[1:0]}; 799 | 4'h2 : slot <= {12'b0, prn[2:0]}; 800 | 4'h3 : slot <= {11'b0, prn[3:0]}; 801 | 4'h4 : slot <= {10'b0, prn[4:0]}; 802 | 4'h5 : slot <= {9'b0, prn[5:0]}; 803 | 4'h6 : slot <= {8'b0, prn[6:0]}; 804 | 4'h7 : slot <= {7'b0, prn[7:0]}; 805 | 4'h8 : slot <= {6'b0, prn[8:0]}; 806 | 4'h9 : slot <= {5'b0, prn[9:0]}; 807 | 4'ha : slot <= {4'b0, prn[10:0]}; 808 | 4'hb : slot <= {3'b0, prn[11:0]}; 809 | 4'hc : slot <= {2'b0, prn[12:0]}; 810 | 4'hd : slot <= {1'b0, prn[13:0]}; 811 | 4'he : slot <= prn[14:0]; 812 | endcase 813 | end 814 | else if(param[2:0] == 3'b011) begin 815 | case(q) 816 | 4'h1 : slot <= 15'b0; 817 | 4'h2 : slot <= {14'b0, prn[0]}; 818 | 4'h3 : slot <= {13'b0, prn[1:0]}; 819 | 4'h4 : slot <= {12'b0, prn[2:0]}; 820 | 4'h5 : slot <= {11'b0, prn[3:0]}; 821 | 4'h6 : slot <= {10'b0, prn[4:0]}; 822 | 4'h7 : slot <= {9'b0, prn[5:0]}; 823 | 4'h8 : slot <= {8'b0, prn[6:0]}; 824 | 4'h9 : slot <= {7'b0, prn[7:0]}; 825 | 4'ha : slot <= {6'b0, prn[8:0]}; 826 | 4'hb : slot <= {5'b0, prn[9:0]}; 827 | 4'hc : slot <= {4'b0, prn[10:0]}; 828 | 4'hd : slot <= {3'b0, prn[11:0]}; 829 | 4'he : slot <= {2'b0, prn[12:0]}; 830 | 4'hf : slot <= {1'b0, prn[13:0]}; 831 | 4'h0 : slot <= prn[14:0]; 832 | endcase 833 | end 834 | end 835 | else if(act == dec_slot | act == dec_slot_tran_if) slot <= slot - 15'b1; 836 | end 837 | 838 | always@(posedge clk_cp or negedge rst_n) begin 839 | if(~rst_n) lock_act <= 10'b00_0000_0011; 840 | else begin 841 | if(act == bs_header_lock) begin 842 | if(param[43:42] != 2'b00) lock_act <= lock_act; 843 | else if(({param[50], param[40]} == 2'b10) & lock_act[8]) lock_act <= lock_act; 844 | else if(({param[48], param[38]} == 2'b10) & lock_act[6]) lock_act <= lock_act; 845 | else if(({param[46], param[36]} == 2'b10) & lock_act[4]) lock_act <= lock_act; 846 | else if(({param[44], param[34]} == 2'b10) & lock_act[2]) lock_act <= lock_act; 847 | else begin 848 | if(param[51]) lock_act[9] <= param[41]; 849 | if(param[50]) lock_act[8] <= param[40]; 850 | if(param[49]) lock_act[7] <= param[39]; 851 | if(param[48]) lock_act[6] <= param[38]; 852 | if(param[47]) lock_act[5] <= param[37]; 853 | if(param[46]) lock_act[4] <= param[36]; 854 | if(param[45]) lock_act[3] <= param[35]; 855 | if(param[44]) lock_act[2] <= param[34]; 856 | // if(param[43]) lock_act[1] <= param[33]; 857 | // if(param[42]) lock_act[0] <= param[32]; 858 | end 859 | end 860 | end 861 | end 862 | 863 | 864 | // --- Lcok action-field functionality --- 865 | always@(*) begin 866 | case(lock_act[3:2]) 867 | 2'b00 : if((ps == Open) | (ps == Secured)) tid_lock = 0; 868 | else tid_lock = 1; 869 | 2'b01 : if((ps == Open) | (ps == Secured)) tid_lock = 0; 870 | else tid_lock = 1; 871 | 2'b10 : if(ps == Secured) tid_lock = 0; 872 | else tid_lock = 1; 873 | 2'b11 : tid_lock = 1; 874 | endcase 875 | end 876 | 877 | always@(*) begin 878 | case(lock_act[5:4]) 879 | 2'b00 : if((ps == Open) | (ps == Secured)) epc_lock = 0; 880 | else epc_lock = 1; 881 | 2'b01 : if((ps == Open) | (ps == Secured)) epc_lock = 0; 882 | else epc_lock = 1; 883 | 2'b10 : if(ps == Secured) epc_lock = 0; 884 | else epc_lock = 1; 885 | 2'b11 : epc_lock = 1; 886 | endcase 887 | end 888 | 889 | always@(*) begin 890 | case(lock_act[7:6]) 891 | 2'b00 : if((ps == Open) | (ps == Secured)) accs_lock = 0; 892 | else accs_lock = 1; 893 | 2'b01 : if((ps == Open) | (ps == Secured)) accs_lock = 0; 894 | else accs_lock = 1; 895 | 2'b10 : if(ps == Secured) accs_lock = 0; 896 | else accs_lock = 1; 897 | 2'b11 : accs_lock = 1; 898 | endcase 899 | end 900 | 901 | always@(*) begin 902 | case(lock_act[9:8]) 903 | 2'b00 : if((ps == Open) | (ps == Secured)) kill_lock = 0; 904 | else kill_lock = 1; 905 | 2'b01 : if((ps == Open) | (ps == Secured)) kill_lock = 0; 906 | else kill_lock = 1; 907 | 2'b10 : if(ps == Secured) kill_lock = 0; 908 | else kill_lock = 1; 909 | 2'b11 : kill_lock = 1; 910 | endcase 911 | end 912 | 913 | 914 | // --- action register for operand isolation --- 915 | always@(posedge clk_cp or negedge rst_for_new_package) begin 916 | if(~rst_for_new_package) act_reg <= 5'h0; 917 | else act_reg <= act; 918 | end 919 | 920 | 921 | // --- clk_cp control --- 922 | always@(*) begin 923 | if(act_reg == init_inventory | act_reg == adj_q | act_reg == dec_slot | act_reg == adj_q_tran_if | act_reg == dec_slot_tran_if) en_2nd_clk_cp = 1'b1; 924 | else en_2nd_clk_cp = 1'b0; 925 | end 926 | 927 | 928 | // --- enable PRNG --- 929 | always@(*) begin 930 | if(ps == Ready) en_prng_idol = 1'b1; 931 | else en_prng_idol = 1'b0; 932 | end 933 | 934 | always@(*) begin 935 | if(act_reg == bs_new_rn16 | act_reg == bs_new_rn16_tran_if | act_reg == gen_and_bs_new_handle | act_reg == bs_new_rn16_crc16) en_prng_act = 1'b1; 936 | else en_prng_act = 1'b0; 937 | end 938 | 939 | 940 | // --- enable TX --- 941 | always@(*) begin 942 | case(act_reg) 943 | bs_new_rn16 : en_tx = 1'b1; 944 | reply_ack : en_tx = 1'b1; 945 | bs_new_rn16_tran_if : en_tx = 1'b1; 946 | gen_and_bs_new_handle : en_tx = 1'b1; 947 | bs_new_rn16_crc16 : en_tx = 1'b1; 948 | bs_read_data : en_tx = 1'b1; 949 | bs_handle : en_tx = 1'b1; 950 | bs_header_kill : en_tx = 1'b1; 951 | bs_header_lock : en_tx = 1'b1; 952 | bs_error_code : en_tx = 1'b1; 953 | default : en_tx = 1'b0; 954 | endcase 955 | end 956 | 957 | 958 | // --- enable memory interface and ROM --- 959 | always@(*) begin 960 | if(act_reg == reply_ack) begin 961 | if(~trct & pre_p_complete) en_if = 1'b1; 962 | else if(trct & p_complete & (r_cnt < r_end + 5'h02)) en_if = 1'b1; 963 | else en_if = 1'b0; 964 | end 965 | else if(act_reg == bs_read_data) begin 966 | if(p_complete) en_if = 1'b1; 967 | else en_if = 1'b0; 968 | end 969 | else en_if = 1'b0; 970 | end 971 | 972 | 973 | // --- enable CRC-16 for replying data --- 974 | always@(*) begin 975 | if(p_complete & (act_reg == reply_ack | act_reg == gen_and_bs_new_handle | act_reg == bs_new_rn16_crc16 | act_reg == bs_read_data | 976 | act_reg == bs_handle | act_reg == bs_header_kill | act_reg == bs_header_lock)) en_crc16_for_rpy = 1'b1; 977 | else en_crc16_for_rpy = 1'b0; 978 | end 979 | 980 | 981 | // --- deliver address to memory interface --- 982 | always@(*) begin 983 | if(act_reg == reply_ack) begin 984 | if(~trct) addr = {1'b0, 2'b01, 8'b0, 8'b0}; 985 | else addr = {1'b0, 2'b01, ptr, 8'b0}; 986 | end 987 | else if(act_reg == bs_read_data) addr = {1'b1, param[49:32]}; 988 | else addr = 19'b0; 989 | end 990 | 991 | 992 | // --- load a new RN16 or handle --- 993 | assign clk_cp_n = ~clk_cp; 994 | 995 | always@(posedge clk_cp_n or negedge rst_n) begin 996 | if(~rst_n) rn16 <= 16'hac70; 997 | else if(act_reg == bs_new_rn16 | act_reg == bs_new_rn16_tran_if | act_reg == bs_new_rn16_crc16) rn16 <= prn[15:0]; 998 | end 999 | 1000 | always@(posedge clk_cp_n or negedge rst_n) begin 1001 | if(~rst_n) handle <= 16'hff31; 1002 | else if(act_reg == gen_and_bs_new_handle) handle <= prn[15:0]; 1003 | end 1004 | 1005 | 1006 | // --- enable/disable reply counter --- 1007 | always@(posedge clk_frm or negedge rst_for_new_package) begin 1008 | if(~rst_for_new_package) en_if_d <= 1'b0; 1009 | else en_if_d <= en_if; 1010 | end 1011 | 1012 | wire en_r_cnt; 1013 | 1014 | assign en_r_cnt = ~en_if_d | rd_complete; 1015 | 1016 | 1017 | // --- control reply counter --- 1018 | always@(posedge clk_frm or negedge rst_for_new_package) begin 1019 | if(~rst_for_new_package) r_cnt <= 5'h17; 1020 | else if(p_complete & en_r_cnt) begin 1021 | if(r_cnt != r_end) r_cnt <= r_cnt - 1; 1022 | else r_cnt <= r_cnt; 1023 | end 1024 | end 1025 | 1026 | 1027 | // --- determine the end of reply counter --- 1028 | always@(*) begin 1029 | case(act_reg) 1030 | bs_new_rn16 : r_end = 5'h08; 1031 | reply_ack : if(~trct) r_end = 5'h17; 1032 | else r_end = 5'h12; 1033 | bs_new_rn16_tran_if : r_end = 5'h08; 1034 | gen_and_bs_new_handle : r_end = 5'h08; 1035 | bs_new_rn16_crc16 : r_end = 5'h08; 1036 | bs_read_data : r_end = 5'h06; 1037 | bs_handle : r_end = 5'h08; 1038 | bs_header_kill : r_end = 5'h07; 1039 | bs_header_lock : r_end = 5'h07; 1040 | bs_error_code : r_end = 5'h00; 1041 | default : r_end = 5'h00; 1042 | endcase 1043 | end 1044 | 1045 | 1046 | // --- reply data --- 1047 | always@(*) begin 1048 | case(act_reg) 1049 | bs_new_rn16 : reply_data = rn16[r_cnt - 5'h08]; 1050 | reply_ack : if(~trct) reply_data = rd_data; 1051 | else begin 1052 | if(r_cnt > 5'h12) reply_data = 1'b0; 1053 | else reply_data = rd_data; 1054 | end 1055 | bs_new_rn16_tran_if : reply_data = rn16[r_cnt - 5'h08]; 1056 | gen_and_bs_new_handle : reply_data = handle[r_cnt - 5'h08]; 1057 | bs_new_rn16_crc16 : reply_data = rn16[r_cnt - 5'h08]; 1058 | bs_read_data : if(r_cnt == 5'h17) reply_data = 1'b0; 1059 | else if(r_cnt == 5'h16) reply_data = rd_data; 1060 | else if(r_cnt < 5'h16 & r_cnt > 5'h5) reply_data = handle[r_cnt - 5'h6]; 1061 | else reply_data = 1'b0; 1062 | bs_handle : reply_data = handle[r_cnt - 5'h08]; 1063 | bs_header_kill : if(r_cnt == 5'h17) reply_data = 1'b0; 1064 | else if(r_cnt < 5'h17 & r_cnt > 5'h6) reply_data = handle[r_cnt - 5'h07]; 1065 | else reply_data = 1'b0; 1066 | bs_header_lock : if(r_cnt == 5'h17) reply_data = 1'b0; 1067 | else if(r_cnt < 5'h17 & r_cnt > 5'h6) reply_data = handle[r_cnt - 5'h07]; 1068 | else reply_data = 1'b0; 1069 | bs_error_code : if(r_cnt > 5'h13) reply_data = 1'b0; 1070 | else if(r_cnt < 5'h14 & r_cnt > 5'h0f) reply_data = 1'b1; 1071 | else reply_data = handle[r_cnt]; 1072 | default : reply_data = 1'b0; 1073 | endcase 1074 | end 1075 | 1076 | 1077 | // --- determine when does the replying data complete --- 1078 | always@(*) begin 1079 | if(act_reg == reply_ack) begin 1080 | if(rd_complete) reply_complete = 1'b1; 1081 | else reply_complete = 1'b0; 1082 | end 1083 | else begin 1084 | if(r_cnt == r_end) reply_complete = 1'b1; 1085 | else reply_complete = 1'b0; 1086 | end 1087 | end 1088 | 1089 | 1090 | endmodule 1091 | --------------------------------------------------------------------------------