代码前几天写好的,今天打算上VIVADO实际试验了,觉得没仿真不踏实,就仿真一把。
模块代码如下:将4路(可以通过使能控制是使用2路)的12位从AD9361采集到的原始数据转换成字节流(用以发送给后续的FPGA实现的千兆以太网)。
module IQ2FIFO(
input clk,rst,
input en,a_valid,b_valid,
input [11:0] d0,d1,d2,d3,
output reg rd_ab_io,
input wr_full, // when first full ,it can allow at least 16 items
output reg wr_fifo,
output reg [7:0] wr_data
);
wire access_ok = en & ~wr_full ;
wire a_or_b_valid = a_valid | b_valid ;
reg [7:0] b5,b4,b3,b2,b1,b0 ;
wire [7:0] b5w,b4w,b3w,b2w,b1w,b0w ;
reg[7:0] st,str; always @(posedge clk) str <= st ;
always @(posedge clk) if (str == 10) { b5,b4,b3, b2,b1,b0} <= { d3 , d2 , d1 , d0 };
assign { b5w,b4w,b3w,b2w,b1w,b0w } = { d3 , d2 , d1 , d0 };
always @ (posedge clk) if (rst) st<=0; else
case (st) 0:st<=10;
10: case ({access_ok,a_valid,b_valid})
3'b110 :st<=20;
3'b101 :st<=30;
3'b111 :st<=40;
endcase
20: st<=21; // save byte1 b5
21: st<=10; // save byte2 b4
// save byte3 when str ==21 b3
30: st<=31; // save byte1 b2
31: st<=10; // save byte2 b1
// save byte3 when st==10 check str==31 b0
40:st<=41; // byte 1 b5
41:st<=42; // byte 2 b4
42:st<=43; // byte 3 b3
43:st<=44; // byte 4 b2
44:st<=10; // byte 5 b1
// save byte6 when str==44 b0
default st<=0;
endcase
always @(*)rd_ab_io = ( st==10 & access_ok & ( a_valid | b_valid ) ) ;
always @(posedge clk) case (st)
20,21,30,31,40,41,42,43,44:wr_fifo <= 1;
default wr_fifo <= (str==21) ||(str==31) ||(str==44) ;endcase
always@(posedge clk) case (st)
20:wr_data <=b5w;
21:wr_data <=b4;
30:wr_data <=b2w;
31:wr_data <=b1;
40:wr_data <=b5w;
41:wr_data <=b4;
42:wr_data <=b3;
43:wr_data <=b2;
44:wr_data <=b1;
default case (str)21:wr_data<=b3;31,44:wr_data<=b0;endcase
endcase
endmodule
例化一下模块上来就写测试代码:
module iq2fifo_tb ;
reg clk=0,rst=0,en=0,a_valid=1,b_valid=1;
always#5 clk <= ~clk ;
initial begin
$dumpfile ("a.vcd") ;
$dumpvars (0, iq2fifo_tb) ;
end
initial begin
rst = 0 ;
#10; rst = 1 ;
#20; rst = 0 ;
@(posedge clk);
//f=0;
a_valid=1; b_valid=0; en=1;
#10000;//f = 1 ;
@(posedge clk);
a_valid=0; b_valid=1; en=1;
#10000;//f = 2 ;
@(posedge clk);
a_valid=1; b_valid=1; en=1;
#10000;//f = 2 ;
@(posedge clk);
$finish ;
end
wire [47:0]d3210_0 = {12'h333,12'h222,12'h111,12'h000} ;
wire [47:0]d3210_1 = {12'h444,12'h333,12'h222,12'h111} ;
wire [47:0]d3210_2 = {12'h555,12'h444,12'h333,12'h222} ;
wire [47:0]d3210_3 = {12'h666,12'h555,12'h444,12'h333} ;
reg [1:0] idx = 0; always @(posedge clk ) if(rd_ab_io)idx<=idx+1 ;
reg [11:0] d0,d1,d2,d3;
always @ (posedge clk) case (idx)
0: {d3,d2,d1,d0} <= d3210_0 ;
1: {d3,d2,d1,d0} <= d3210_1 ;
2: {d3,d2,d1,d0} <= d3210_2 ;
3: {d3,d2,d1,d0} <= d3210_3 ;
endcase
wire rd_ab_io ;
wire [7:0] wr_data ;
IQ2FIFO IQ2FIFO(
.clk( clk ),
.rst( rst ),
.en( en ),
.a_valid( a_valid ),
.b_valid( b_valid),
.d0( d0 ),
.d1( d1 ),
.d2( d2 ),
.d3( d3 ),
.rd_ab_io( rd_ab_io ),
.wr_full( 1'b0 ), // when first full ,it can allow at least 16 items
.wr_fifo( wr_fifo ),
.wr_data ( wr_data )
);
endmodule
在icarvous verilog下面仿真。
上图可以看到在两个有效情况下输出正确。并且IO段每三个周期取一个数据,正好是每次取三个字节,没有浪费周期。
上图可以看到在两个有效情况下输出正确。并且IQ每6个周期取一个数据,正好是每次取6个字节(12X4=48位),没有浪费周期。