├── .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 | | NAME | DESCRIPTION |
26 |
27 |
28 | | bb_proc | baseband processor, top module |
29 |
30 |
31 | | cmd_buf | command buffer, serial to parallel |
32 |
33 |
34 | | cmd_proc | command processor, processes received commands |
35 |
36 |
37 | | crc16 | CRC-16 encoder/decoder |
38 |
39 |
40 | | crc5 | CRC-5 encoder/decoder |
41 |
42 |
43 | | crg | clock/reset generator, timing control |
44 |
45 |
46 | | fm0_enc | FM0 Encoder, operates in the lowest freq. |
47 |
48 |
49 | | frmgen | frame generator, generates preamble, backscattered data, end-of-signaling |
50 |
51 |
52 | | fs_detector | frame-sync detector |
53 |
54 |
55 | | mem_if | memory interface |
56 |
57 |
58 | | miller_enc | Miller encoder, operates in the lowest freq. |
59 |
60 |
61 | | prng | 16-bit Pseudorandom number generator |
62 |
63 |
64 | | rx | Receive |
65 |
66 |
67 | | two_dff_sync | Synchronizer, synchronizes signals from clock domain A to B |
68 |
69 |
70 | | tx | Transmit |
71 |
72 |
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 |
--------------------------------------------------------------------------------