基于网络编码的多信源组播通信系统,包括源代码,原理图等(四)
扫描二维码
随时随地手机看文章
4 结论
网络编码从提出到现在已有十年,在这期间,网络编码的理论研究和工程应用不断发展和成熟,基于网络编码的多信源组播系统是网络编码在硬件方面的实现。它突破了以往网络编码的应用研究只停留在软件和虚拟网络,通过搭建实际的组播通信网络,并应用NetFPGA平台使网络编码在硬件中得以实现。
文档的前面分别介绍了网络编码的基本概念和研究动态、编解码策略和算法以及编码、转发、解码三个系统的详细设计方案,包括系统的软硬接口和软件的基本功能。由于系统中的网络编解码都是由硬件完成,软件的功能主要是控制和测试时使用,因此方案设计以硬件为主。
图4-1,图4-2和图4-3分别是编码、转发以及解码路由器三个系统的verilog代码树状图,除去MAC层和core generator产生的代码,代码量有11,000行。附录给出了编码路由器和解码路由器中的关键代码。
图4-1 编码路由器代码树状图
图4-2 转发路由器代码树状图
图4-3 解码路由器代码树状图
附录
附1:编码路由器核心代码:编码模块: payload_router.v
/////////////////////////////////////////////////////////////////////////////
// vim:set shiftwidth=3 softtabstop=3 expandtab:
// Copyright(c) 2009, All rights reserved.
// Advanced Network technology Lab, Shenzhen graduated school of PKU
// Module: payload_router.v
// Project: nf2_coding.ise
// Time and Author: 2009-12-25 liyining
// Description:determine whether should carry out coding operation, and route
// the packets
/////////////////////////////////////////////////////////////////////////////
`define DLY 1
`timescale 1ns/1ns
module payload_router
#(parameter DATAWIDTH = 64,
parameter CTRLWIDTH = DATAWIDTH / 8 //bit-width parameter
)
(
//payload fifo 1 port
input [DATAWIDTH - 1:0] data_payloadfifo_router_1,
input [CTRLWIDTH - 1:0] ctrl_payloadfifo_router_1,
input empty_payloadfifo_router_1,
output reg rd_en_payloadfifo_router_1,
//payload fifo 2 port
input [DATAWIDTH - 1:0] data_payloadfifo_router_2,
input [CTRLWIDTH - 1:0] ctrl_payloadfifo_router_2,
input empty_payloadfifo_router_2,
output reg rd_en_payloadfifo_router_2,
//multiplier 1 port
input rdy_router_multiplier_1,
output reg [DATAWIDTH - 1:0] data_router_multiplier_1,
output reg first_dword_1, //flag to indicate the start of a pkt. only when it is the first double word of a pkt, should the random number be updated.
output reg val_router_multiplier_1,
//multiplier 2 port
input rdy_router_multiplier_2,
output reg [DATAWIDTH - 1:0] data_router_multiplier_2,
output reg first_dword_2, //flag to indicate the start of a pkt. only when it is the first double word of a pkt, should the random number be updated.
output reg val_router_multiplier_2,
//rand number generator port
output reg rand_num_en, //enable the random number generator
input rand_num_val,
//packing fifo port
input rdy_router_packingfifo,
input empty_packingfifo, // only when the whole last pkt is sent out, and the packing fifo is empty, then proceed the next pkt
output reg [DATAWIDTH + CTRLWIDTH:0] data_router_packingfifo, //an extra bit(MSB) to indicate whether it is a coded pkt
output reg val_router_packingfifo,
output reg [2:0] router_status, //send router_status to packing_fifo, indicate where to get data
//misc
input clk,
input rst_n
);
reg [DATAWIDTH - 1:0] data_temp1;
reg [CTRLWIDTH - 1:0] ctrl_temp1;
reg [DATAWIDTH - 1:0] data_temp2;
reg [CTRLWIDTH - 1:0] ctrl_temp2;
reg [1:0] counter_getdata; //counter for the read-FIFO-delay, 1 clock circle
parameter JUDGE = 3'b000;
parameter GET_DATA2 = 3'b001;
parameter SEND_DATA2 = 3'b010;
parameter GET_DATA1 = 3'b011;
parameter SEND_DATA1 = 3'b100;
parameter GET_BOTH = 3'b101;
parameter SEND_BOTH_1 = 3'b110;
parameter SEND_BOTH_2 = 3'b111;
always @(posedge clk or negedge rst_n) begin
//reset process
if (rst_n == 0) begin
router_status <= JUDGE;
data_temp1 <= 64'h0;
ctrl_temp1 <= 8'h0;
data_temp2 <= 64'h0;
ctrl_temp2 <= 8'h0;
counter_getdata <= 2'b0;
end
else begin
case (router_status)
JUDGE: begin
first_dword_1 <= 0;
first_dword_2 <= 0;
rand_num_en <= 0;
val_router_multiplier_2 <= 0; //clear some signals
//program hold, when packing FIFO inempty
if (!empty_packingfifo) begin
router_status <= JUDGE;
end
else begin
//both FIFO ctrl payload 1 & 2 are empty
if (empty_payloadfifo_router_1 && empty_payloadfifo_router_2) begin
rd_en_payloadfifo_router_1 <= 0;
rd_en_payloadfifo_router_2 <= 0;
router_status <= JUDGE;
end
//FIFO ctrl paylaod 2 is inempty, read from this FIFO,
//coding will be unnecessary
else if (empty_payloadfifo_router_1 && (!empty_payloadfifo_router_2)) begin
rd_en_payloadfifo_router_2 <= 1;
rd_en_payloadfifo_router_1 <= 0;
counter_getdata <= 0;
router_status <= GET_DATA2;
end
//FIFO ctrl payload 1 is inempty, read from this FIFO,
//coding will be unnecessary
else if ((!empty_payloadfifo_router_1) && empty_payloadfifo_router_2) begin
rd_en_payloadfifo_router_1 <= 1;
rd_en_payloadfifo_router_2 <= 0;
counter_getdata <= 0;
router_status <= GET_DATA1;
end
//both FIFO ctrl payload 1&2 are inempty, read from both
//of them, coding is needed
else if ((!empty_payloadfifo_router_1) && (!empty_payloadfifo_router_2)) begin
rd_en_payloadfifo_router_1 <= 1;
rd_en_payloadfifo_router_2 <= 1;
counter_getdata <= 0;
router_status <= GET_BOTH;
end
end
end //state JUDGE ends
//read data from FIFO ctrl payload 2
GET_DATA2: begin
val_router_packingfifo <= 0; //clear the output valid signal
//read-FIFO-delay
if (counter_getdata < 2'b01) begin
counter_getdata <= counter_getdata + 1;
router_status <= GET_DATA2;
rd_en_payloadfifo_router_2 <= 0; //clear rd_en signal
end
else begin
data_temp2 <= data_payloadfifo_router_2;
ctrl_temp2 <= ctrl_payloadfifo_router_2;
router_status <= SEND_DATA2;
end
end //state GET_DATA2 ends
//send data to packing fifo without coding
SEND_DATA2: begin
if (!rdy_router_packingfifo) begin
router_status <= SEND_DATA2;
end
else begin
data_router_packingfifo <= {ctrl_temp2, 1'b0 , data_temp2 }; //MSB = 0 means it is an uncoded pkt
val_router_packingfifo <= 1;
//this is the end of a packet, goto JUDGE
if (& (ctrl_temp2)) begin
router_status <= JUDGE;
end
//this is not the end of a packet, goto GET_DATA2
else begin
router_status <= GET_DATA2;
rd_en_payloadfifo_router_2 <= 1;
counter_getdata <= 0;
end
end
end //state SEND_DATA2 ends[!--empirenews.page--]
GET_DATA1: begin
val_router_packingfifo <= 0; //clear output valid signal
//read-FIFO-delay
if (counter_getdata < 2'b01) begin
counter_getdata <= counter_getdata + 1;
router_status <= GET_DATA1;
rd_en_payloadfifo_router_1 <= 0; //clear rd_en signal
end
else begin
data_temp1 <= data_payloadfifo_router_1;
ctrl_temp1 <= ctrl_payloadfifo_router_1;
rd_en_payloadfifo_router_1 <= 0;
router_status <= SEND_DATA1;
end
end //state GET_DATA1 ends
SEND_DATA1: begin
if (!rdy_router_packingfifo) begin
router_status <= SEND_DATA1;
end
else begin
data_router_packingfifo <= {ctrl_temp1, 1'b0 , data_temp1 }; //MSB = 0 means it is an uncoded pkt
val_router_packingfifo <= 1;
//this is the end of a packet, goto JUDGE
if (& (ctrl_temp1)) begin
router_status <= JUDGE;
end
//this is not the end of a packet, goto GET_DATA1
else begin
router_status <= GET_DATA1;
rd_en_payloadfifo_router_1 <= 1;
counter_getdata <= 0;
end
end
end //state SEND_DATA1 ends
GET_BOTH: begin
first_dword_2 <= 0; //
val_router_multiplier_2 <= 0; //clear valid signal
//read-FIFO-delay
if (counter_getdata < 2'b01) begin
counter_getdata <= counter_getdata + 1;
router_status <= GET_BOTH;
rd_en_payloadfifo_router_1 <= 0;
rd_en_payloadfifo_router_2 <= 0; //clear rd_en signals
end
else begin
data_temp1 <= data_payloadfifo_router_1;
ctrl_temp1 <= ctrl_payloadfifo_router_1;
data_temp2 <= data_payloadfifo_router_2;
ctrl_temp2 <= ctrl_payloadfifo_router_2;
router_status <= SEND_BOTH_1;
end
end //state GET_BOTH ends
//according to the random number generator, data from both
//input channels should be sent out seperately
SEND_BOTH_1: begin
if (!rdy_router_multiplier_1) begin
val_router_multiplier_1 <= 0;
router_status <= SEND_BOTH_1;
end
else begin
data_router_multiplier_1 <= data_temp1;
val_router_multiplier_1 <= 1;
if (ctrl_temp1 == 8'hff) begin
first_dword_1 <= 1;
rand_num_en <= 1;
end
else begin
first_dword_1 <=0;
rand_num_en <= 0;
end
router_status <= SEND_BOTH_2;
end
end //state SEND_BOTH_1 ends
SEND_BOTH_2: begin
first_dword_1 <= 0;
val_router_multiplier_1 <= 0; //clear valid signal
//confirm the first random number is generated successfully
//before enable to generate the second.
if (ctrl_temp1 == 8'hff) begin
if (!rand_num_val) begin
rand_num_en <= 0;
router_status <= SEND_BOTH_2;
end
end[!--empirenews.page--]
else begin
if (!rdy_router_multiplier_2) begin
val_router_multiplier_2 <= 0;
router_status <= SEND_BOTH_2;
end
else begin
data_router_multiplier_2 <= data_temp2;
val_router_multiplier_2 <= 1;
if (ctrl_temp2 == 8'hff) begin
first_dword_2 <= 1;
rand_num_en <= 1;
end
else begin
first_dword_2 <= 0;
rand_num_en <= 0;
end
if (((ctrl_temp1 == 8'hf0) && (& (ctrl_temp2))) || ((ctrl_temp2 == 8'hf0) && (& (ctrl_temp1)))) begin
router_status <= JUDGE;
end
else begin
rd_en_payloadfifo_router_1 <= 1;
rd_en_payloadfifo_router_2 <= 1;
counter_getdata <= 0;
router_status <= GET_BOTH;
end
end
end
end //state SEND_BOTH_2 ends
endcase
end
end
endmodule
附2:解码路由器核心代码之一:解码控制模块:decode_control_sm. v
///////////////////////////////////////////////////////////////////////////////
// vim:set shiftwidth=3 softtabstop=3 expandtab:
// Copyright(c) 2009, All rights reserved.
// Advanced Network technology Lab, Shenzhen graduated school of PKU
// Module: decode_control_sm.v
// Project: NF2.1
// Time and Author: 2009-12-15 zhang ming long
// Description: According to the pkts' source and generation sequence number,
// this module goes round-robin strategy to control the module decoder
// to decode the pkts stored in DRAMS.
///////////////////////////////////////////////////////////////////////////////
`define DLY #1
`timescale 1ns/1ps
module decode_control_sm
#(parameter SRC_WIDTH = 4,
parameter GEN_WIDTH = 8,
parameter REG_GRP_WIDTH = 12,
parameter SRC_GEN_SEQ_WIDTH = 24,
parameter DRAM_NUMS = 3,
parameter CAM_NUMS = 3,
parameter DRAM_NUMS_WIDTH = log2(DRAM_NUMS),
parameter CAM_NUMS_WIDTH = log2(CAM_NUMS),
parameter DRAM_BLOCK_WIDTH = 8,
parameter CAM_ADDR_WIDTH = 8,
parameter CMP_DATA_MASK = 12'hfff
)
(// --- cam interface
output [SRC_GEN_SEQ_WIDTH-1:0] cmp_data_0,
output reg [SRC_GEN_SEQ_WIDTH-1:0] cmp_data_mask_0,
input [CAM_ADDR_WIDTH-1:0] match_addr_0,
input match_0,
output [SRC_GEN_SEQ_WIDTH-1:0] cmp_data_1,
output reg [SRC_GEN_SEQ_WIDTH-1:0] cmp_data_mask_1,
input [CAM_ADDR_WIDTH-1:0] match_addr_1,
input match_1,
output [SRC_GEN_SEQ_WIDTH-1:0] cmp_data_2,
output reg [SRC_GEN_SEQ_WIDTH-1:0] cmp_data_mask_2,
input [CAM_ADDR_WIDTH-1:0] match_addr_2,
input match_2,
// ---DRAM control interface
output reg [DRAM_NUMS_WIDTH-1:0] port_num_rd,
output reg [DRAM_BLOCK_WIDTH-1:0] block_num_rd,
output reg addr_vld,
input rd_idle,
// ---input_arbiter interface
input cam_vld,
// ---decoder interface
output reg pkt_vld,
output reg [REG_GRP_WIDTH-1:0] pkt_dcoding,
output reg pkt_not_find,
output reg has_other_factor,
input [REG_GRP_WIDTH-1:0] pkt_need_src_gen,
input need_pkt_vld,
input decod_com,
// ---decoded reg grp interface
output reg rd_dcod_reg_req_1,
output [REG_GRP_WIDTH-1:0] rd_dcod_src_gen_1,
input req_ack_vld_1,
input alredy_decod_1,
// --- Misc
input rst_n,
input clk
);[!--empirenews.page--]
function integer log2;
input integer number;
begin
log2=0;
while(2**log2<number) begin
log2=log2+1;
end
end
endfunction // log2
// ------------ Internal Params --------
parameter NUM_STATES = 4;
parameter IDLE = 4'b0;
parameter GET_SRC_GEN_NUM = 4'b0001;
parameter LOOK_UP_CAM = 4'b0010;
parameter GET_CMP_RESLT_FIRST = 4'b0011;
parameter GET_CMP_RESLT_SEC = 4'b0100;
parameter RD_DRAM_MAIN_STEP = 4'b0101;
parameter LUP_DCOD_FACTOR1_FIRST = 4'b0110;
parameter LUP_DCOD_FACTOR1_SEC = 4'b0111;
parameter GET_FACTOR1_RESLT = 4'b1000;
parameter RD_DRAM_MINOR_STEP = 4'b1001;
parameter LUP_DCOD_FACTOR2 = 4'b1011;
// ------------- Regs/ wires -----------
wire [SRC_WIDTH-1:0] src_num_plus1;
reg [SRC_WIDTH-1:0] src_num,src_num_sel,src_num_sel_next; //source sequence number for packets that is being decoded
reg [SRC_WIDTH-1:0] src_num_next;
wire [GEN_WIDTH-1:0] gen_num_plus1;
reg [GEN_WIDTH-1:0] gen_num,gen_num_sel,gen_num_sel_next; //generation sequence number for packets that is being decoded
reg [GEN_WIDTH-1:0] gen_num_next;
reg [CAM_NUMS-1:0] cam_lookup_reslt; // result of looking up packets in cam,stands for which cam finds the packet
reg [CAM_NUMS-1:0] cam_lookup_reslt_next;
reg[CAM_NUMS-1:0] cam_lookup_reslt_pre,cam_lookup_reslt_save;
reg[CAM_NUMS-1:0] cam_lookup_reslt_pre_next,cam_lookup_reslt_save_next;
reg [CAM_ADDR_WIDTH-1:0] other_dram_addr;
reg [CAM_ADDR_WIDTH-1:0] other_dram_addr_next;
reg [DRAM_NUMS_WIDTH-1:0] other_port_num_rd; //the other result from looking up cams
reg has_factor2; //has the other looking up result
reg has_factor2_next;
reg [DRAM_NUMS_WIDTH-1:0] other_port_num_rd_next;
reg [NUM_STATES-1:0] state;
reg [NUM_STATES-1:0] state_next;
reg [4:0] couter;
wire [4:0] couter_next;
reg couter_start;
reg[CAM_ADDR_WIDTH-1:0] atch_addr_temp_2,match_addr_temp_2_next;
reg[CAM_ADDR_WIDTH-1:0] match_addr_temp_1,match_addr_temp_1_next;
reg[CAM_ADDR_WIDTH-1:0] match_addr_temp_0,match_addr_temp_0_next;
reg [SRC_GEN_SEQ_WIDTH-1:0] cmp_data;
// ------------ main code and logic -------------
assign src_num_plus1 = (src_num == 2) ? 0 : src_num + 1;
assign gen_num_plus1 = (gen_num == 2**GEN_WIDTH-1) ? 0 : gen_num + 1;
assign rd_dcod_src_gen_1 = {src_num_sel,gen_num_sel};
assign couter_next = (couter_start == 1) ? couter+1 : couter;
assign cmp_data_0 = cmp_data;
assign cmp_data_1 = cmp_data;
assign cmp_data_2 = cmp_data;
/* This state machine completes decode control task. If enough packets have
* been saved in cams and DRAMS, it starts to decode to packets. If
* a packet can not be decoded becouse of losing, it will decode the next
* packet automatically */
always @(*) begin
state_next = state;
gen_num_next = gen_num;
src_num_next = src_num;
src_num_sel_next = src_num_sel;
gen_num_sel_next = gen_num_sel;
cam_lookup_reslt_next = cam_lookup_reslt;
rd_dcod_reg_req_1 = 1'b0;
addr_vld = 1'b0;
pkt_vld = 1'b0;
pkt_not_find = 1'b0;
other_dram_addr_next = other_dram_addr;
other_port_num_rd_next =other_port_num_rd;
has_factor2_next = has_factor2;
pkt_dcoding = 12'hfff;
block_num_rd = 2'b0;
cam_lookup_reslt_pre_next = cam_lookup_reslt_pre;
cam_lookup_reslt_save_next = cam_lookup_reslt_save;
port_num_rd = 2'b11;
couter_start = 1'b0;
match_addr_temp_2_next = match_addr_temp_2;
match_addr_temp_1_next = match_addr_temp_1;
match_addr_temp_0_next = match_addr_temp_0;
cmp_data_mask_0 = 24'h0;
cmp_data_mask_1 = 24'h0;
cmp_data_mask_2 = 24'h0;
has_other_factor = 0;
cmp_data = 24'hffffff;
case(state)
/* --- waiting for the cam has been writen enough packet */
IDLE: begin
if(cam_vld) begin
couter_start = 1;
end
if(couter == 5'b11111)
state_next = GET_SRC_GEN_NUM;
end
/* Goes round-robin around the sources and generations,
* gets the source sequence number and generation sequebce
* number of a packet need to be decoded */
GET_SRC_GEN_NUM: begin
state_next = LOOK_UP_CAM;
rd_dcod_reg_req_1 = 1; // read the decoded reg grp
src_num_sel_next = src_num;
gen_num_sel_next = gen_num;
src_num_next = src_num_plus1;
if(src_num == 4'b0010)
gen_num_next = gen_num_plus1;
end
/* --- look up pkt in three cams to get block number of DRAM*/
LOOK_UP_CAM:
if(req_ack_vld_1) begin
if(alredy_decod_1 == 1) // it has been decoded,decode the next packet
state_next = GET_SRC_GEN_NUM;
else begin
cmp_data = {src_num_sel,gen_num_sel,12'hfff};
cmp_data_mask_0 = {12'h0,CMP_DATA_MASK};
cmp_data_mask_1 = {12'h0,CMP_DATA_MASK};
cmp_data_mask_2 = {12'h0,CMP_DATA_MASK};
state_next = GET_CMP_RESLT_FIRST;
end
end
GET_CMP_RESLT_FIRST: begin
cam_lookup_reslt_next = {match_2,match_1,match_0};
cmp_data = {12'hfff,src_num_sel,gen_num_sel};
cmp_data_mask_0 = {CMP_DATA_MASK,12'h0};
cmp_data_mask_1 = {CMP_DATA_MASK,12'h0};
cmp_data_mask_2 = {CMP_DATA_MASK,12'h0};
state_next = GET_CMP_RESLT_SEC;
match_addr_temp_2_next = match_addr_2;
match_addr_temp_1_next = match_addr_1;
match_addr_temp_0_next = match_addr_0;
end[!--empirenews.page--]
/* get the address from the cams, if there are two adresses from
* the cams, then outputs the one to the DRAM control and save
* the other for later use. If there is no valid address, we could not
* decode, then get out and decode the next one */
GET_CMP_RESLT_SEC: begin
state_next = RD_DRAM_MAIN_STEP;
cam_lookup_reslt_next = cam_lookup_reslt | {match_2,match_1,match_0};
cam_lookup_reslt_pre_next = cam_lookup_reslt | {match_2,match_1,match_0};
cam_lookup_reslt_save_next = cam_lookup_reslt | {match_2,match_1,match_0};
if(match_2) begin
match_addr_temp_2_next = match_addr_2;
end
if(match_1) begin
match_addr_temp_1_next = match_addr_1;
end
if(match_0) begin
match_addr_temp_0_next = match_addr_0;
end
end
/* reads the DRAM accroding to the CAM's address, then updates the look
* up result */
RD_DRAM_MAIN_STEP:
if(rd_idle) begin
if(|cam_lookup_reslt) begin
if(cam_lookup_reslt==3'b101) begin
other_dram_addr_next = match_addr_temp_2;
other_port_num_rd_next = 2'b10;
has_factor2_next = 1;
addr_vld = 1;
block_num_rd = match_addr_temp_0;
port_num_rd = 0;
cam_lookup_reslt_next = 3'b100;
end
else if (cam_lookup_reslt == 3'b011) begin
other_dram_addr_next = match_addr_temp_1;
other_port_num_rd_next = 2'b01;
has_factor2_next = 1;
addr_vld = 1;
block_num_rd = match_addr_temp_0;
port_num_rd = 0;
cam_lookup_reslt_next = 3'b010;
end
else if (cam_lookup_reslt==3'b110) begin
other_dram_addr_next = match_addr_temp_2;
other_port_num_rd_next = 2'b10;
has_factor2_next = 1;
addr_vld = 1;
block_num_rd = match_addr_temp_1;
port_num_rd = 2'b01;
cam_lookup_reslt_next=3'b100;
end
else if (cam_lookup_reslt==3'b001) begin
has_factor2_next = 0;
addr_vld = 1;
block_num_rd = match_addr_0;
port_num_rd = 2'b00;
cam_lookup_reslt_next = 0;
end
else if (cam_lookup_reslt==3'b010) begin
has_factor2_next = 0;
addr_vld = 1;
block_num_rd = match_addr_1;
port_num_rd = 2'b01;
cam_lookup_reslt_next = 0;
end
else if (cam_lookup_reslt==3'b100) begin
has_factor2_next = 0;
addr_vld = 1;
block_num_rd = match_addr_2;
port_num_rd = 2'b10;
cam_lookup_reslt_next = 0;
end
state_next=LUP_DCOD_FACTOR1_FIRST;
pkt_vld = 1;
pkt_dcoding = {src_num_sel,gen_num_sel};
end // end-- if(|cam_lookup_reslt)
else
state_next = GET_SRC_GEN_NUM; //could not find the pkt in cams.
end //end--if(rd_idle)
/* waiting for decoding completion, if needs the decoding factor pkt,
* then look up the factor in the remain cams */
LUP_DCOD_FACTOR1_FIRST: begin
if(decod_com) begin
state_next=GET_SRC_GEN_NUM;
end
if(need_pkt_vld) begin // need other packet to decode current packet
if((cam_lookup_reslt^~cam_lookup_reslt_pre)==3'b110) begin
cmp_data = {pkt_need_src_gen,12'hfff};
cmp_data_mask_2 = {12'h0,CMP_DATA_MASK};
cmp_data_mask_1 = {12'h0,CMP_DATA_MASK};
end
else if((cam_lookup_reslt^~cam_lookup_reslt_pre)==3'b101) begin
cmp_data = {pkt_need_src_gen,12'hfff};
cmp_data_mask_2 = {12'h0,CMP_DATA_MASK};
cmp_data_mask_0 = {12'h0,CMP_DATA_MASK};
end [!--empirenews.page--]
else if((cam_lookup_reslt^~cam_lookup_reslt_pre)==3'b011) begin
cmp_data = {pkt_need_src_gen,12'hfff};
cmp_data_mask_1 = {12'h0,CMP_DATA_MASK};
cmp_data_mask_0 = {12'h0,CMP_DATA_MASK};
end
else if((cam_lookup_reslt^~cam_lookup_reslt_pre)==3'b001) begin
cmp_data = {pkt_need_src_gen,12'hfff};
cmp_data_mask_0 = {12'h0,CMP_DATA_MASK};
end
else if((cam_lookup_reslt^~cam_lookup_reslt_pre)==3'b010) begin
cmp_data = {pkt_need_src_gen,12'hfff};
cmp_data_mask_1 = {12'h0,CMP_DATA_MASK};
end
else if((cam_lookup_reslt^~cam_lookup_reslt_pre)==3'b100) begin
cmp_data = {pkt_need_src_gen,12'hfff};
cmp_data_mask_2 = {12'h0,CMP_DATA_MASK};
end
state_next = LUP_DCOD_FACTOR1_SEC;
end
end
LUP_DCOD_FACTOR1_SEC: begin
state_next = GET_FACTOR1_RESLT;
cam_lookup_reslt_next = {match_2,match_1,match_0};
match_addr_temp_2_next = match_addr_2;
match_addr_temp_1_next = match_addr_1;
match_addr_temp_0_next = match_addr_0;
if((cam_lookup_reslt^~cam_lookup_reslt_pre)==3'b110) begin
cmp_data = {12'hfff,pkt_need_src_gen};
cmp_data_mask_2 = {CMP_DATA_MASK,12'h0};
cmp_data_mask_1 = {CMP_DATA_MASK,12'h0};
end
else if((cam_lookup_reslt^~cam_lookup_reslt_pre)==3'b101) begin
cmp_data = {12'hfff,pkt_need_src_gen};
cmp_data_mask_2 = {CMP_DATA_MASK,12'h0};
cmp_data_mask_0 = {CMP_DATA_MASK,12'h0};
end
else if((cam_lookup_reslt^~cam_lookup_reslt_pre)==3'b011) begin
cmp_data = {12'hfff,pkt_need_src_gen};
cmp_data_mask_0 = {CMP_DATA_MASK,12'h0};
cmp_data_mask_1 = {CMP_DATA_MASK,12'h0};
end
else if((cam_lookup_reslt^~cam_lookup_reslt_pre)==3'b001) begin
cmp_data = {12'hfff,pkt_need_src_gen};
cmp_data_mask_0 = {CMP_DATA_MASK,12'h0};
end
else if((cam_lookup_reslt^~cam_lookup_reslt_pre)==3'b010) begin
cmp_data = {12'hfff,pkt_need_src_gen};
cmp_data_mask_1 = {CMP_DATA_MASK,12'h0};
end
else if((cam_lookup_reslt^~cam_lookup_reslt_pre)==3'b100) begin
cmp_data = {12'hfff,pkt_need_src_gen};
cmp_data_mask_2 = {CMP_DATA_MASK,12'h0};
end
end
/* --- get the factor pkt address from the cam, then reads the DRAM
if no address matches, then check the decode factor2 */
GET_FACTOR1_RESLT: begin
state_next = RD_DRAM_MINOR_STEP;
cam_lookup_reslt_next = cam_lookup_reslt | {match_2,match_1,match_0};
cam_lookup_reslt_pre_next = cam_lookup_reslt | {match_2,match_1,match_0};
if(match_2) begin
match_addr_temp_2_next = match_addr_2;
end
if(match_1) begin
match_addr_temp_1_next = match_addr_1;
end
if(match_0) begin
match_addr_temp_0_next = match_addr_0;
end
end
RD_DRAM_MINOR_STEP:
if(rd_idle)
if(|cam_lookup_reslt) begin
state_next = LUP_DCOD_FACTOR1_FIRST;
if(cam_lookup_reslt==3'b001)
begin
addr_vld = 1;
block_num_rd = match_addr_temp_0;
port_num_rd = 2'b00;
cam_lookup_reslt_next=0;
end
else if (cam_lookup_reslt==3'b010)
begin
addr_vld = 1;
block_num_rd = match_addr_temp_1;
port_num_rd = 2'b01;
cam_lookup_reslt_next=0;
end
else if (cam_lookup_reslt==3'b100)
begin
addr_vld = 1;
block_num_rd = match_addr_temp_2;
port_num_rd = 2'b10;
cam_lookup_reslt_next=0;
end
end
else
begin
state_next = LUP_DCOD_FACTOR2;
pkt_not_find = 1;
has_other_factor = has_factor2;
end
/* decoding the packet by decode factor2 */
LUP_DCOD_FACTOR2:
if(has_factor2) begin
addr_vld = 1;
block_num_rd = other_dram_addr;
port_num_rd = other_port_num_rd;
state_next = LUP_DCOD_FACTOR1_FIRST;
cam_lookup_reslt_pre_next = cam_lookup_reslt_save;
has_factor2_next = 0;
end
else begin
pkt_not_find = 1;
has_other_factor = has_factor2;
state_next = GET_SRC_GEN_NUM;
end
endcase // case(state)
end // always @ (*)
always @(posedge clk) begin
src_num_sel <= `DLY src_num_sel_next;
gen_num_sel <= `DLY gen_num_sel_next;
cam_lookup_reslt_pre <= `DLY cam_lookup_reslt_pre_next;
other_dram_addr <= `DLY other_dram_addr_next;
other_port_num_rd <= `DLY other_port_num_rd_next;
match_addr_temp_2 <= `DLY match_addr_temp_2_next;
match_addr_temp_1 <= `DLY match_addr_temp_1_next;
match_addr_temp_0 <= `DLY match_addr_temp_0_next;
cam_lookup_reslt_save <= `DLY cam_lookup_reslt_save_next;
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
state <= IDLE;
src_num <= 0;
gen_num <= 0;
has_factor2 <= 0;
cam_lookup_reslt <= 0;
couter <= 5'b0;
end
else begin
state <= `DLY state_next;
src_num <= `DLY src_num_next;
gen_num <= `DLY gen_num_next;
couter <= `DLY couter_next;
cam_lookup_reslt <= `DLY cam_lookup_reslt_next;
has_factor2 <= `DLY has_factor2_next;
end
end
endmodule //decode_control_sm