1`timescale 1ns / 1ps 2/* 3 * This software is Copyright (c) 2018 Denis Burykin 4 * [denis_burykin yahoo com], [denis-burykin2014 yandex ru] 5 * and it is hereby released to the general public under the following terms: 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted. 8 * 9 */ 10 11// 12// Unit output packet format: 13// - header (1 word) 14// - IDs (64 bits) 15// - MD5 hash (128 bits) 16// 17// Total: 16+8 = 24 bytes 18// 19module arbiter_rx #( 20 parameter N_UNITS = -1, 21 parameter UNIT_OUTPUT_WIDTH = -1, 22 parameter PKT_NUM_WORDS = `RESULT_LEN/2 + 4 23 )( 24 input CLK, 25 input mode_cmp, 26 // Units 27 input [UNIT_OUTPUT_WIDTH * N_UNITS -1 :0] unit_dout, 28 output reg [N_UNITS-1:0] unit_rd_en = 0, 29 input [N_UNITS-1:0] unit_empty, 30 // Iteraction with arbiter_tx 31 input [31:0] num_processed_tx, 32 input [15:0] pkt_id_tx, 33 input pkt_tx_done, 34 output reg pkt_rx_done = 0, 35 output reg recv_item = 0, // asserts for 1 for every RX item 36 // Comparator 37 output reg [31:0] cmp_data, 38 output reg cmp_start = 0, 39 input cmp_found, cmp_finished, 40 input [`HASH_NUM_MSB:0] cmp_hash_num, 41 // Output 42 output reg [`OUTPKT_TYPE_MSB:0] outpkt_type, 43 output [15:0] dout, 44 input [`MSB(PKT_NUM_WORDS-1):0] rd_addr, 45 output reg [15:0] pkt_id, 46 output reg [31:0] num_processed = 0, 47 output reg [`HASH_NUM_MSB:0] hash_num, 48 input rd_en, 49 output reg empty = 1, 50 51 output reg [1:0] err = 0, 52 output reg [15:0] debug = 0 53 ); 54 55 reg [`MSB(N_UNITS-1):0] unit_num = 0; 56 reg [UNIT_OUTPUT_WIDTH-1 :0] din = 0; 57 reg unit_empty_r = 1; 58 always @(posedge CLK) begin 59 din <= unit_dout [unit_num * UNIT_OUTPUT_WIDTH +:UNIT_OUTPUT_WIDTH]; 60 unit_empty_r <= unit_empty [unit_num]; 61 end 62 63 (* RAM_STYLE="DISTRIBUTED" *) 64 reg [15:0] output_r [0:PKT_NUM_WORDS-1]; 65 assign dout = output_r [rd_addr]; 66 67 reg rd_tmp_wr_en = 0; 68 reg [`MSB(PKT_NUM_WORDS-1):0] rd_tmp_wr_addr = 0; 69 always @(posedge CLK) 70 if (rd_tmp_wr_en) 71 output_r [rd_tmp_wr_addr] <= rd_tmp; 72 73 74 reg [2:0] rd_count = 0; 75 reg [15:0] rd_tmp = 0; 76 reg [`MSB(PKT_NUM_WORDS-1):0] result_word_count = 0; 77 78 reg [31:0] delay_shr = 0; 79 80 localparam STATE_IDLE = 0, 81 STATE_WAIT = 1, 82 STATE_WAIT2 = 2, 83 STATE_READ = 3, 84 STATE_RX_HEADER = 4, 85 STATE_RX_DATA = 5, 86 STATE_RX_END = 6, 87 STATE_CMP = 7, 88 STATE_OUTPKT_RESULT = 8, 89 STATE_PKT_ACCOUNT = 9, 90 STATE_PKT_ACCOUNT2 = 10, 91 STATE_PKT_ACCOUNT3 = 11, 92 STATE_OUTPKT_PROCESSING_DONE = 12; 93 94 (* FSM_EXTRACT="true" *) 95 reg [3:0] state = STATE_IDLE; 96 97 always @(posedge CLK) begin 98 if (rd_tmp_wr_en) 99 rd_tmp_wr_en <= 0; 100 101 if (cmp_start) 102 cmp_start <= 0; 103 104 if (pkt_rx_done) 105 pkt_rx_done <= 0; 106 107 if (recv_item) 108 recv_item <= 0; 109 110 if (state == STATE_IDLE | delay_shr[31]) 111 delay_shr <= { delay_shr[30:0], state == STATE_IDLE }; 112 113 case (state) 114 STATE_IDLE: if (delay_shr[31]) 115 state <= STATE_WAIT; 116 117 STATE_WAIT: 118 if (~unit_empty_r)// [unit_num]) 119 state <= STATE_READ; 120 else begin 121 unit_num <= unit_num == N_UNITS-1 122 ? {`MSB(N_UNITS-1)+1{1'b0}} : unit_num + 1'b1; 123 state <= STATE_WAIT2; 124 end 125 126 STATE_WAIT2: 127 state <= STATE_WAIT; 128 129 STATE_READ: begin 130 recv_item <= 1; 131 unit_rd_en [unit_num] <= 1; 132 state <= STATE_RX_HEADER; 133 end 134 135 STATE_RX_HEADER: begin 136 unit_rd_en <= 0; 137 result_word_count <= 0; 138 if (din != 0) begin 139 if (din != {UNIT_OUTPUT_WIDTH{1'b1}}) begin 140 err[0] <= 1; 141 debug [unit_num] <= 1; 142 end 143 else 144 state <= STATE_RX_DATA; 145 end 146 end 147 148 // Collect PKT_NUM_WORDS words X 16 bit in output_r 149 STATE_RX_DATA: begin 150 rd_tmp [rd_count * UNIT_OUTPUT_WIDTH +:UNIT_OUTPUT_WIDTH] 151 <= din; 152 rd_count <= rd_count + 1'b1; 153 if (rd_count == (16 / UNIT_OUTPUT_WIDTH) -1) begin 154 rd_tmp_wr_en <= 1; 155 rd_tmp_wr_addr <= result_word_count; 156 result_word_count <= result_word_count + 1'b1; 157 if (result_word_count == PKT_NUM_WORDS-1) 158 state <= STATE_RX_END; 159 end 160 161 // 2nd 16-bit word: pkt_id 162 if (result_word_count == 2 & rd_count == 0) 163 pkt_id <= rd_tmp; 164 165 // externalize comparator data, start comparison 166 // before all the data received from a computing unit 167 if (result_word_count == 5 & rd_count == 0) 168 cmp_data[15:0] <= rd_tmp; 169 if (result_word_count == 6 & rd_count == 0) begin 170 cmp_data[31:16] <= rd_tmp; 171 cmp_start <= 1; 172 end 173 end 174 175 STATE_RX_END: begin 176 outpkt_type <= `OUTPKT_TYPE_RESULT; 177 if (din != 0) begin 178 err[1] <= 1; 179 debug [unit_num] <= 1; 180 end 181 else if (mode_cmp) 182 state <= STATE_CMP; 183 else begin 184 empty <= 0; 185 state <= STATE_OUTPKT_RESULT; 186 end 187 end 188 189 STATE_CMP: begin 190 if (cmp_found) begin 191 outpkt_type <= `OUTPKT_TYPE_CMP_RESULT; 192 hash_num <= cmp_hash_num; 193 empty <= 0; 194 state <= STATE_OUTPKT_RESULT; 195 end 196 else if (cmp_finished) 197 state <= STATE_PKT_ACCOUNT; 198 end 199 200 // output PKT_RESULT or PKT_CMP_RESULT 201 STATE_OUTPKT_RESULT: if (rd_en) begin 202 empty <= 1; 203 if (mode_cmp) 204 state <= STATE_PKT_ACCOUNT; 205 else 206 state <= STATE_WAIT; 207 end 208 209 STATE_PKT_ACCOUNT: begin 210 num_processed <= num_processed + 1'b1; 211 if (pkt_tx_done) 212 state <= STATE_PKT_ACCOUNT2; 213 else 214 state <= STATE_WAIT; 215 end 216 217 STATE_PKT_ACCOUNT2: 218 if (num_processed_tx == num_processed) 219 state <= STATE_PKT_ACCOUNT3; 220 else 221 state <= STATE_WAIT; 222 223 STATE_PKT_ACCOUNT3: begin 224 outpkt_type <= `OUTPKT_TYPE_PACKET_DONE; 225 pkt_id <= pkt_id_tx; 226 empty <= 0; 227 pkt_rx_done <= 1; 228 state <= STATE_OUTPKT_PROCESSING_DONE; 229 end 230 231 // output PKT_PROCESSING_DONE 232 STATE_OUTPKT_PROCESSING_DONE: if (rd_en) begin 233 empty <= 1; 234 num_processed <= 0; 235 state <= STATE_WAIT; 236 end 237 endcase 238 end 239 240 241endmodule 242