• AXI_Round_Robin_Arbiter 设计 - AW、W通道部分



    1. 状态机设计

    还是基于状态机,思路是收到了一包AW通道的数据,记录下它的len,然后根据len和awid收相应的AXI Master的W通道数据,保证AW通道和W通道顺序一致。

    在这里插入图片描述

    那权重怎么变化呢?此处想的是每AW和W通道完成一次收数,权重变化一次。注意要保证AW接受和W接收必须来自同一个AXI Master

    1.1. WAIT_AW

    等待某个AW通道与AXI Slave握手完成,即可转入下一状态

    根据req输出grant

    此处的req其实就是各AXI Master的awvalid组成的多bit数据,而grant就是仲裁的结果。注意在WAIT_AW时状态不发生变化

    状态转移条件:AW通道握手完成

    注意原算法的状态转移条件是req发生变化就转移,但在此处需要某个Master的awvalid为高且awready信号拉高才能握手,如下图

    在这里插入图片描述

    prio其实就是权重。虽然req中途发生了变化,但状态转移的条件是与Master0握手完成才转移条件。

    注意AW通道只是一次性传递多个控制信息,不是burst,awready&awvalid有效一拍即可完成握手。
    转入WAIT_W状态后awready不应再拉高,必须等待从WAIT_W回到WAIT_AW才能再拉高。

    1.2. WAIT_W

    然后进入WAIT_W状态,之前WAIT_AW状态下与哪个Master完成了握手,此处就必须等这个Master的W通道握手完成才能结束WAIT_W状态。

    grant保持,接受W通道数据

    这里的grant必须要与WAIT_AW状态下握手完成时的grant一致,同时要一直接受W通道来的数据

    状态转移条件:W通道握手完成

    由于Master是固定的,所以只需看那个Master的wlast即可,这个信号表示最后一个数据。

    在这里插入图片描述

    握手完成之后,重新回到WAIT_AW状态。注意此时prio权重也要根据grant作修正,同时grant不能再继续保持了,转入WAIT_AW后要根据awvalid_mst作组合逻辑输出

    综上所述,状态机变成

    在这里插入图片描述

    1.3. 代码

    module axi_round_robin_arbiter_aw_w #(
    	parameter AWID_WIDTH				= 8,
    	parameter AWADDR_WIDTH 				= 16,
    	parameter WDATA_WIDTH 				= 16,
    	parameter MAX_PRIO_INITIAL_INDEX 	= 0
    	)(
    	input							aclk,
    	input							arstn,
    	
    	//AW CHANNEL
    	input	[(AWID_WIDTH+2)*4-1:0]		awid_mst,
    	input	[AWADDR_WIDTH*4-1:0]	awaddr_mst,
    	input	[8*4-1:0]				awlen_mst,
    	input	[3*4-1:0]				awsize_mst,
    	input	[2*4-1:0]				awburst_mst,
    	input	[1*4-1:0]				awvalid_mst,
    	output	[1*4-1:0]				awready_mst,
    	output	[(AWID_WIDTH+2)-1:0]		awid,
    	output	[AWADDR_WIDTH-1:0]		awaddr,
    	output	[8-1:0]					awlen,
    	output	[3-1:0]					awsize,
    	output	[2-1:0]					awburst,
    	output							awvalid,
    	input							awready,
    	
    	//W CHANNEL
    	input	[WDATA_WIDTH*4-1:0]		wdata_mst,
    	input	[1*4-1:0]				wlast_mst,
    	input	[1*4-1:0]				wvalid_mst,
    	output	[1*4-1:0]				wready_mst,
    	output	[WDATA_WIDTH-1:0]		wdata,
    	output	[1-1:0]					wlast,
    	output	[1-1:0]					wvalid,
    	input	[1-1:0]					wready
    	);
    
    localparam	WAIT_AW = 1'b0;	
    localparam	WAIT_W  = 1'b1;	
    	
    
    reg		[4-1:0]					cur_state;
    reg		[4-1:0]					nxt_state;
    reg		[4-1:0]					grant;
    reg		[4-1:0]					grant_tmp;
    reg		[4-1:0]					prio;
    reg								wvalid_mst_cs;
    reg								wlast_mst_cs;
    wire	[4-1:0]					inital_state;
    wire	[4:0]					res1;
    wire	[4:0]					res2;
    
    assign inital_state = {{(4-MAX_PRIO_INITIAL_INDEX-1){1'b0}},1'b1,{MAX_PRIO_INITIAL_INDEX{1'b0}}};
    
    always@(posedge aclk or negedge arstn) begin
    	if(!arstn)
    		cur_state <= WAIT_AW;
    	else 
    		cur_state <= nxt_state;
    end
    
    always@(*) begin
    	case(cur_state)
    		WAIT_AW:
    			if((|awvalid_mst) && awready)
    				nxt_state = WAIT_W;
    			else
    				nxt_state = WAIT_AW;
    		WAIT_W:
    			if(wvalid_mst_cs && wlast_mst_cs && wready)
    				nxt_state = WAIT_AW;
    			else
    				nxt_state = WAIT_W;
    		default:	nxt_state = WAIT_AW;
    	endcase
    end
    
    
    always@(posedge aclk or negedge arstn) begin
    	if(!arstn)
    		prio <= inital_state;
    	else if(cur_state == WAIT_W && wvalid_mst_cs && wlast_mst_cs && wready) 
    		prio <= (grant[3])? 4'b1:(grant << 1);
    end
    
    always@(*) begin
    	if(cur_state == WAIT_AW)
    		wlast_mst_cs = 1'b0;
    	else begin
    		case(grant)
    			4'b0001:
    				wlast_mst_cs = wlast_mst[0];
    			4'b0010:
    				wlast_mst_cs = wlast_mst[1];
    			4'b0100:
    				wlast_mst_cs = wlast_mst[2];
    			4'b1000:                      
    				wlast_mst_cs = wlast_mst[3];
    			default:
    				wlast_mst_cs = 1'b0;
    		endcase
    	end
    end
    
    always@(*) begin
    	if(cur_state == WAIT_W)
    		wvalid_mst_cs = 1'b0;
    	else begin
    		case(grant)
    			4'b0001:
    				wvalid_mst_cs = wvalid_mst[0];
    			4'b0010:
    				wvalid_mst_cs = wvalid_mst[1];
    			4'b0100:
    				wvalid_mst_cs = wvalid_mst[2];
    			4'b1000:                      
    				wvalid_mst_cs = wvalid_mst[3];
    			default:
    				wvalid_mst_cs = 1'b0;
    		endcase
    	end
    end
    
    always@(posedge aclk or negedge arstn) begin
    	if(!arstn)
    		grant_tmp <= 'd0;
    	else if(cur_state == WAIT_AW && (|awvalid_mst) && awready)
    		grant_tmp <= grant;
    end
    
    
    assign res1 = {1'b0,~awvalid_mst} + {1'b0,prio};
    
    assign res2 = res1[4] + res1;
    
    always@(*) begin
    	if(cur_state == WAIT_AW)
    		grant = awvalid_mst & res2;
    	else
    		grant = grant_tmp;
    end
    
    
    
    
    //-----------------AW channel chip select--------------------------
    
    reg		[(AWID_WIDTH+2)-1:0]		awid_r;
    reg		[AWADDR_WIDTH-1:0]		awaddr_r;
    reg		[8-1:0]					awlen_r;
    reg		[3-1:0]					awsize_r;
    reg		[2-1:0]					awburst_r;
    reg								awvalid_r;
    reg		[1*4-1:0]				awready_mst_r;
    
    
    always@(*) begin
    	if(cur_state == WAIT_AW) begin
    		case(grant)
    			4'b0001:
    				awid_r = awid_mst[(AWID_WIDTH+2)-1:0];
    			4'b0010:
    				awid_r = awid_mst[(AWID_WIDTH+2)*2-1:(AWID_WIDTH+2)];
    			4'b0100:
    				awid_r = awid_mst[(AWID_WIDTH+2)*3-1:(AWID_WIDTH+2)*2];
    			4'b1000:
    				awid_r = awid_mst[(AWID_WIDTH+2)*4-1:(AWID_WIDTH+2)*3];
    			default:
    				awid_r = 'd0;
    		endcase
    	end
    	else
    		awid_r = 'd0;	
    end
    
    assign awid = awid_r;
    
    always@(*) begin
    	if(cur_state == WAIT_AW) begin
    		case(grant)
    			4'b0001:
    				awaddr_r = awaddr_mst[AWADDR_WIDTH-1:0];
    			4'b0010:
    				awaddr_r = awaddr_mst[AWADDR_WIDTH*2-1:AWADDR_WIDTH];
    			4'b0100:
    				awaddr_r = awaddr_mst[AWADDR_WIDTH*3-1:AWADDR_WIDTH*2];
    			4'b1000:
    				awaddr_r = awaddr_mst[AWADDR_WIDTH*4-1:AWADDR_WIDTH*3];
    			default:
    				awaddr_r = 'd0;
    		endcase
    	end
    	else
    		awaddr_r = 'd0;
    end
    
    assign awaddr = awaddr_r;
    
    always@(*) begin
    	if(cur_state == WAIT_AW) begin
    		case(grant)
    			4'b0001:
    				awlen_r = awlen_mst[8-1:0];
    			4'b0010:
    				awlen_r = awlen_mst[8*2-1:8];
    			4'b0100:
    				awlen_r = awlen_mst[8*3-1:8*2];
    			4'b1000:
    				awlen_r = awlen_mst[8*4-1:8*3];
    			default:
    				awlen_r = 'd0;
    		endcase
    	end
    	else
    		awlen_r = 'd0;
    end
    
    assign awlen = awlen_r;
    
    always@(*) begin
    	if(cur_state == WAIT_AW) begin
    		case(grant)
    			4'b0001:
    				awsize_r = awsize_mst[3-1:0];
    			4'b0010:
    				awsize_r = awsize_mst[3*2-1:3];
    			4'b0100:
    				awsize_r = awsize_mst[3*3-1:3*2];
    			4'b1000:
    				awsize_r = awsize_mst[3*4-1:3*3];
    			default:
    				awsize_r = 'd0;
    		endcase
    	end
    	else
    		awsize_r = 'd0;
    end
    
    assign awsize = awsize_r;
    
    always@(*) begin
    	if(cur_state == WAIT_AW) begin
    		case(grant)
    			4'b0001:
    				awburst_r = awburst_mst[2-1:0];
    			4'b0010:
    				awburst_r = awburst_mst[2*2-1:2];
    			4'b0100:
    				awburst_r = awburst_mst[2*3-1:2*2];
    			4'b1000:
    				awburst_r = awburst_mst[2*4-1:2*3];
    			default:
    				awburst_r = 'd0;
    		endcase
    	end
    	else
    		awburst_r = 'd0;
    end
    
    assign awburst = awburst_r;
    
    always@(*) begin
    	if(cur_state == WAIT_AW) begin	
    		case(grant)
    			4'b0001:
    				awvalid_r = awvalid_mst[1-1:0];
    			4'b0010:
    				awvalid_r = awvalid_mst[1*2-1:1];
    			4'b0100:
    				awvalid_r = awvalid_mst[1*3-1:1*2];
    			4'b1000:
    				awvalid_r = awvalid_mst[1*4-1:1*3];
    			default:
    				awvalid_r = 'd0;
    		endcase
    	end
    	else
    		awvalid_r = 'd0;
    end
    
    assign awvalid = awvalid_r;
    
    always@(*) begin
    	if(cur_state == WAIT_AW)
    		awready_mst_r = awready << grant;
    	else
    		awready_mst_r = 'd0;
    end
    
    assign awready_mst = awready_mst_r;
    
    
    //-----------------W channel chip select--------------------------
    
    reg		[1*4-1:0]				wready_mst_r;
    reg		[WDATA_WIDTH-1:0]		wdata_r;
    reg		[1-1:0]					wlast_r;
    reg		[1-1:0]					wvalid_r;
    
    
    always@(*) begin
    	if(cur_state == WAIT_AW) 
    		wready_mst_r = 'd0;
    	else 
    		wready_mst_r = wready << grant;
    end
    
    assign wready_mst = wready_mst_r;
    
    always@(*) begin
    	if(cur_state == WAIT_AW) 
    		wdata_r = 'd0;
    	else begin
    		case(grant)
    			4'b0001:
    				wdata_r = wdata_mst[WDATA_WIDTH-1:0];
    			4'b0010:
    				wdata_r = wdata_mst[WDATA_WIDTH*2-1:WDATA_WIDTH];
    			4'b0100:
    				wdata_r = wdata_mst[WDATA_WIDTH*3-1:WDATA_WIDTH*2];
    			4'b1000:
    				wdata_r = wdata_mst[WDATA_WIDTH*4-1:WDATA_WIDTH*3];
    			default:
    				wdata_r = 'd0;
    		endcase
    	end
    end
    
    assign wdata = wdata_r;
    
    always@(*) begin
    	if(cur_state == WAIT_AW) 
    		wlast_r = 'd0;
    	else begin
    		case(grant)
    			4'b0001:
    				wlast_r = wlast_mst[0];
    			4'b0010:
    				wlast_r = wlast_mst[1];
    			4'b0100:
    				wlast_r = wlast_mst[2];
    			4'b1000:
    				wlast_r = wlast_mst[3];
    			default:
    				wlast_r = 'd0;
    		endcase
    	end
    end
    
    assign wlast = wlast_r;
    
    always@(*) begin
    	if(cur_state == WAIT_AW) 
    		wvalid_r = 'd0;
    	else begin
    		case(grant)
    			4'b0001:
    				wvalid_r = wvalid_mst[0];
    			4'b0010:
    				wvalid_r = wvalid_mst[1];
    			4'b0100:
    				wvalid_r = wvalid_mst[2];
    			4'b1000:
    				wvalid_r = wvalid_mst[3];
    			default:
    				wvalid_r = 'd0;
    		endcase
    	end
    end
    
    assign wvalid = wvalid_r;
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372

    2. 状态机改流水

    可以发现,在上述状态机的设计中,WAIT_AW状态时AXI Master的AW通道和AXI Slave的AW通道信号能够相互通信,但此时W通道被阻断。在WAIT_W状态下,W通道的信号被打通,而AW通道的信号被阻隔。

    此时想到,在WAIT_W状态下,AW通道直接被阻隔了,那能不能放开,让AW通道正常通信,即WAIT_AW和WAIT_W两种状态并行呢?

    流水线设计可从状态机改造而来,例如乘法器就可分为先单bit相乘、再错位相加,那么在错位相加的时候可不可以对新的数据进行单bit相乘呢?可以,按照这个思路就将状态机优化成流水线了。
    RTL乘法器IP设计
    当然不是所有的状态机都可以完全优化成流水线,有的完全不能优化(例如USART),有的可以将部分状态进行流水优化。

    那么 怎么将WAIT_AW和WAIT_W并行起来呢?

    AW通道和W通道协同设计的根本原因是,W通道没有wid,所以AW通道的收数顺序必须与W通道的收数顺序一致。

    所以,只需每次AW完成握手一次,记录下此时握手的Master是谁,即grant。每完成一次握手就将grant放入FIFO,而W通道呢则每完成一次握手就从FIFO读出grant知道下次要交互的Master,这样就实现了AW通道和W通道的流水啦。

    既然两个通道使用同步FIFO隔离,那么就可以分成两个模块了

    在这里插入图片描述

    2.1. axi_round_robin_arbiter_aw

    AW通道仲裁比较好说,但还是要使用状态机,此处的状态就要改成FIFO是否满了,FIFO满了通信就要阻断。

    代码

    module axi_round_robin_arbiter_aw #(
    	parameter AWID_WIDTH				= 8,
    	parameter AWADDR_WIDTH 				= 16,
    	parameter MAX_PRIO_INITIAL_INDEX 	= 0
    	)(
    	input							aclk,
    	input							arstn,
    	
    	//AW CHANNEL
    	input	[(AWID_WIDTH+2)*4-1:0]	awid_mst,
    	input	[AWADDR_WIDTH*4-1:0]	awaddr_mst,
    	input	[8*4-1:0]				awlen_mst,
    	input	[3*4-1:0]				awsize_mst,
    	input	[2*4-1:0]				awburst_mst,
    	input	[1*4-1:0]				awvalid_mst,
    	output	[1*4-1:0]				awready_mst,
    	output	[(AWID_WIDTH+2)-1:0]	awid,
    	output	[AWADDR_WIDTH-1:0]		awaddr,
    	output	[8-1:0]					awlen,
    	output	[3-1:0]					awsize,
    	output	[2-1:0]					awburst,
    	output							awvalid,
    	input							awready,
    	
    	input							grant_fifo_full,
    	output	[4-1:0]					grant,
    	output							grant_val
    	);
    
    reg		[4-1:0]					cur_state;
    reg		[4-1:0]					nxt_state;
    wire	[4-1:0]					inital_state;
    wire	[4:0]					res1;
    wire	[4:0]					res2;
    
    assign inital_state = {{(4-MAX_PRIO_INITIAL_INDEX-1){1'b0}},1'b1,{MAX_PRIO_INITIAL_INDEX{1'b0}}};
    
    always@(posedge aclk or negedge arstn) begin
    	if(!arstn)
    		cur_state <= inital_state;
    	else 
    		cur_state <= nxt_state;
    end
    
    always@(*) begin
    	if(grant_val) begin
    		if(grant[3])
    			nxt_state = 4'b1;
    		else
    			nxt_state = grant << 1;
    	end
    	else
    		nxt_state = cur_state;
    end
    
    
    assign res1 = {1'b0,~awvalid_mst} + {1'b0,cur_state};
    
    assign res2 = res1[4] + res1;
    
    assign grant = awvalid_mst & res2;
    
    assign grant_val = awvalid && awready;
    
    
    
    //-----------------AW channel chip select--------------------------
    
    reg		[(AWID_WIDTH+2)-1:0]	awid_r;
    reg		[AWADDR_WIDTH-1:0]		awaddr_r;
    reg		[8-1:0]					awlen_r;
    reg		[3-1:0]					awsize_r;
    reg		[2-1:0]					awburst_r;
    reg								awvalid_r;
    reg		[1*4-1:0]				awready_mst_r;
    
    
    always@(*) begin
    	if(!grant_fifo_full) begin
    		case(grant)
    			4'b0001:
    				awid_r = awid_mst[(AWID_WIDTH+2)-1:0];
    			4'b0010:
    				awid_r = awid_mst[(AWID_WIDTH+2)*2-1:(AWID_WIDTH+2)];
    			4'b0100:
    				awid_r = awid_mst[(AWID_WIDTH+2)*3-1:(AWID_WIDTH+2)*2];
    			4'b1000:
    				awid_r = awid_mst[(AWID_WIDTH+2)*4-1:(AWID_WIDTH+2)*3];
    			default:
    				awid_r = 'd0;
    		endcase
    	end
    	else
    		awid_r = 'd0;	
    end
    
    assign awid = awid_r;
    
    always@(*) begin
    	if(!grant_fifo_full) begin
    		case(grant)
    			4'b0001:
    				awaddr_r = awaddr_mst[AWADDR_WIDTH-1:0];
    			4'b0010:
    				awaddr_r = awaddr_mst[AWADDR_WIDTH*2-1:AWADDR_WIDTH];
    			4'b0100:
    				awaddr_r = awaddr_mst[AWADDR_WIDTH*3-1:AWADDR_WIDTH*2];
    			4'b1000:
    				awaddr_r = awaddr_mst[AWADDR_WIDTH*4-1:AWADDR_WIDTH*3];
    			default:
    				awaddr_r = 'd0;
    		endcase
    	end
    	else
    		awaddr_r = 'd0;
    end
    
    assign awaddr = awaddr_r;
    
    always@(*) begin
    	if(!grant_fifo_full) begin
    		case(grant)
    			4'b0001:
    				awlen_r = awlen_mst[8-1:0];
    			4'b0010:
    				awlen_r = awlen_mst[8*2-1:8];
    			4'b0100:
    				awlen_r = awlen_mst[8*3-1:8*2];
    			4'b1000:
    				awlen_r = awlen_mst[8*4-1:8*3];
    			default:
    				awlen_r = 'd0;
    		endcase
    	end
    	else
    		awlen_r = 'd0;
    end
    
    assign awlen = awlen_r;
    
    always@(*) begin
    	if(!grant_fifo_full) begin
    		case(grant)
    			4'b0001:
    				awsize_r = awsize_mst[3-1:0];
    			4'b0010:
    				awsize_r = awsize_mst[3*2-1:3];
    			4'b0100:
    				awsize_r = awsize_mst[3*3-1:3*2];
    			4'b1000:
    				awsize_r = awsize_mst[3*4-1:3*3];
    			default:
    				awsize_r = 'd0;
    		endcase
    	end
    	else
    		awsize_r = 'd0;
    end
    
    assign awsize = awsize_r;
    
    always@(*) begin
    	if(!grant_fifo_full) begin
    		case(grant)
    			4'b0001:
    				awburst_r = awburst_mst[2-1:0];
    			4'b0010:
    				awburst_r = awburst_mst[2*2-1:2];
    			4'b0100:
    				awburst_r = awburst_mst[2*3-1:2*2];
    			4'b1000:
    				awburst_r = awburst_mst[2*4-1:2*3];
    			default:
    				awburst_r = 'd0;
    		endcase
    	end
    	else
    		awburst_r = 'd0;
    end
    
    assign awburst = awburst_r;
    
    always@(*) begin
    	if(!grant_fifo_full) begin	
    		case(grant)
    			4'b0001:
    				awvalid_r = awvalid_mst[1-1:0];
    			4'b0010:
    				awvalid_r = awvalid_mst[1*2-1:1];
    			4'b0100:
    				awvalid_r = awvalid_mst[1*3-1:1*2];
    			4'b1000:
    				awvalid_r = awvalid_mst[1*4-1:1*3];
    			default:
    				awvalid_r = 'd0;
    		endcase
    	end
    	else
    		awvalid_r = 'd0;
    end
    
    assign awvalid = awvalid_r;
    
    always@(*) begin
    	if(!grant_fifo_full)
    		awready_mst_r = awready << grant;
    	else
    		awready_mst_r = 'd0;
    end
    
    assign awready_mst = awready_mst_r;
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213

    2.2. axi_round_robin_arbiter_w

    对于W通道而言,必须从FIFO读出grant才能与grant规定的Master握手,所以还是按照状态机的设计过程,分为两个状态

    在这里插入图片描述

    RD_GRANT

    该状态下就一直读FIFO,同时W通道被阻塞,直到grant被读出

    在这里插入图片描述

    HANDSHAKE

    此时grant会一直保持,按照grant选择Master等待握手完成就可以。

    在这里插入图片描述

    代码

    module axi_round_robin_arbiter_w #(
    	parameter WDATA_WIDTH 				= 16,
    	parameter MAX_PRIO_INITIAL_INDEX 	= 0
    	)(
    	input							aclk,
    	input							arstn,
    	
    	//W CHANNEL
    	input	[WDATA_WIDTH*4-1:0]		wdata_mst,
    	input	[1*4-1:0]				wlast_mst,
    	input	[1*4-1:0]				wvalid_mst,
    	output	[1*4-1:0]				wready_mst,
    	output	[WDATA_WIDTH-1:0]		wdata,
    	output	[1-1:0]					wlast,
    	output	[1-1:0]					wvalid,
    	input	[1-1:0]					wready,
    	
    	output							fifo_rd_en,
    	input							fifo_empty,
    	input		[4-1:0]				grant,
    	input							grant_val
    	);
    
    localparam	IDLE 		= 2'b00;	
    localparam	RD_GRANT  	= 2'b01;	
    localparam	HANDSHAKE  	= 2'b11;	
    	
    
    reg		[1:0]		cur_state;
    reg		[1:0]		nxt_state;
    reg					fifo_rd_en_r;
    
    always@(posedge aclk or negedge arstn) begin
    	if(!arstn)
    		cur_state <= IDLE;
    	else 
    		cur_state <= nxt_state;
    end
    
    always@(*) begin
    	case(cur_state)
    		IDLE:
    			nxt_state = RD_GRANT;
    		RD_GRANT:
    			if(grant_val)
    				nxt_state = HANDSHAKE;
    			else
    				nxt_state = RD_GRANT;
    		HANDSHAKE:
    			if(wlast && wready)
    				nxt_state = HANDSHAKE;
    			else
    				nxt_state = RD_GRANT;
    		default:	nxt_state = IDLE;
    	endcase
    end
    
    
    always@(posedge aclk or negedge arstn) begin
    	if(!arstn)
    		fifo_rd_en_r <= 1'b0;
    	else if(cur_state == IDLE)
    		fifo_rd_en_r <= 1'b1;
    	else if(cur_state == RD_GRANT) begin
    			if(!fifo_empty)
    				fifo_rd_en_r <= 1'b0;
    	end
    	else if(cur_state == HANDSHAKE) begin
    			if(wlast && wready)
    				fifo_rd_en_r <= 1'b1;
    	end		
    end
    
    assign fifo_rd_en = fifo_rd_en_r;
    
    
    //-----------------W channel chip select--------------------------
    
    reg		[1*4-1:0]				wready_mst_r;
    reg		[WDATA_WIDTH-1:0]		wdata_r;
    reg		[1-1:0]					wlast_r;
    reg		[1-1:0]					wvalid_r;
    
    
    always@(*) begin
    	if(!cur_state[0]) 								//(cur_state == IDLE) && (cur_state == RD_GRANT) 
    		wready_mst_r = 'd0;
    	else 
    		wready_mst_r = wready << grant;
    end
    
    assign wready_mst = wready_mst_r;
    
    always@(*) begin
    	if(!cur_state[0]) 
    		wdata_r = 'd0;
    	else begin
    		case(grant)
    			4'b0001:
    				wdata_r = wdata_mst[WDATA_WIDTH-1:0];
    			4'b0010:
    				wdata_r = wdata_mst[WDATA_WIDTH*2-1:WDATA_WIDTH];
    			4'b0100:
    				wdata_r = wdata_mst[WDATA_WIDTH*3-1:WDATA_WIDTH*2];
    			4'b1000:
    				wdata_r = wdata_mst[WDATA_WIDTH*4-1:WDATA_WIDTH*3];
    			default:
    				wdata_r = 'd0;
    		endcase
    	end
    end
    
    assign wdata = wdata_r;
    
    always@(*) begin
    	if(!cur_state[0]) 
    		wlast_r = 'd0;
    	else begin
    		case(grant)
    			4'b0001:
    				wlast_r = wlast_mst[0];
    			4'b0010:
    				wlast_r = wlast_mst[1];
    			4'b0100:
    				wlast_r = wlast_mst[2];
    			4'b1000:
    				wlast_r = wlast_mst[3];
    			default:
    				wlast_r = 'd0;
    		endcase
    	end
    end
    
    assign wlast = wlast_r;
    
    always@(*) begin
    	if(!cur_state[0]) 
    		wvalid_r = 'd0;
    	else begin
    		case(grant)
    			4'b0001:
    				wvalid_r = wvalid_mst[0];
    			4'b0010:
    				wvalid_r = wvalid_mst[1];
    			4'b0100:
    				wvalid_r = wvalid_mst[2];
    			4'b1000:
    				wvalid_r = wvalid_mst[3];
    			default:
    				wvalid_r = 'd0;
    		endcase
    	end
    end
    
    assign wvalid = wvalid_r;
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
  • 相关阅读:
    spark学习笔记(十二)——sparkStreaming-RDD队列/自定义数据源/kafka数据源/DStream转换/DStream输出/优雅关闭
    浏览器播放rtsp视频,基于nodeJs
    国家强制性灯具安全标准GB7000.1-2015
    Idea部署dubbo-admin
    【python】python进行debug操作
    五个可以永远相信的神仙网站推荐
    浅谈归并排序:合并 K 个升序链表的归并解法
    基于Material Design风格开源、易用、强大的WPF UI控件库
    大数据要怎么样学才可以到企业级实战
    Kafka CMAK KeeperErrorCode = Unimplemented
  • 原文地址:https://blog.csdn.net/Starry__/article/details/125417003