本文有hitter整理编辑,如需引用请注明出处。
总述:... 1
一、.. 原始代码以及RTL视图... 1
1 gpio_atr模块源码... 1
2 gpio_atr模块RTL视图... 3
3 setting_reg模块源码... 4
4 setting_reg模块源码... 5
二、. gpio_atr中次级模块例化分析... 6
三、. gpio_atr内实现功能分析... 7
1 输入,输出数据选择... 7
2 执行in/out选择以及赋值... 8
3 回读功能分析... 9
四、. gpio_atr其他输入引脚说明... 10
1 set_stb引脚... 10
2 set_addr[7:0]引脚... 10
3 set_addr[31:0]引脚... 10
总述:射频子板控制verilog模块为gpio_atr模块,其实现的功能即为:与控制与子板的通信,包括16个输入引脚,以及16个输出引脚。都为该模块控制。下文中将具体分析其控制的逻辑。
一、 原始代码以及RTL视图
其代码中例化setting_reg模块,现现将两部分源码以及RTL级视图如下:
1 gpio_atr模块源码
module gpio_atr
#(parameter BASE = 0,
parameter WIDTH = 32)
(input clk, input reset,
input set_stb, input [7:0] set_addr, input [31:0] set_data,
input rx, input tx,
inout [WIDTH-1:0] gpio,
output reg [31:0] gpio_readback
);
wire [WIDTH-1:0] ddr, in_idle,in_tx, in_rx, in_fdx;
reg [WIDTH-1:0] rgpio, igpio;
setting_reg #(.my_addr(BASE+0),.width(WIDTH)) reg_idle
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),
.out(in_idle),.changed());
setting_reg #(.my_addr(BASE+1), .width(WIDTH)) reg_rx
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),
.out(in_rx),.changed());
setting_reg #(.my_addr(BASE+2), .width(WIDTH)) reg_tx
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),
.out(in_tx),.changed());
setting_reg #(.my_addr(BASE+3), .width(WIDTH)) reg_fdx
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),
.out(in_fdx),.changed());
setting_reg #(.my_addr(BASE+4), .width(WIDTH)) reg_ddr
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),
.out(ddr),.changed());
always @(posedge clk)
case({tx,rx})
2'b00: rgpio <= in_idle;
2'b01: rgpio <= in_rx;
2'b10: rgpio <= in_tx;
2'b11: rgpio <= in_fdx;
endcase // case ({tx,rx})
integer n;
always @*
for(n=0;n igpio[n] <= ddr[n] ? rgpio[n] : 1'bz; assign gpio = igpio; always @(posedge clk) gpio_readback <= gpio; endmodule // gpio_atr 2 gpio_atr模块RTL视图
图1 3 setting_reg模块源码 module setting_reg #(parameter my_addr = 0, parameter width = 32, parameter at_reset=32'd0) (input clk, input rst, inputstrobe, input wire [7:0] addr, input wire [31:0] in, outputreg [width-1:0] out, output reg changed); always @(posedge clk) if(rst) begin out <= at_reset; changed <= 1'b0; end else if(strobe &(my_addr==addr)) begin out <= in; changed <= 1'b1; end else changed <= 1'b0; endmodule // setting_reg 4 setting_reg模块源码 图2 二、 gpio_atr中次级模块例化分析 图3 图3中在gpio_atr中对setting_reg模块进行了5次例化调用。其逻辑视图见图1所示。 这5次例化分别实现了不同的功能。分别是reg_idle(空闲状态),reg_rx(接收状态), reg_tx(发送状态),reg_fdx(全双工状态),reg_ddr(引脚输入输出转换) 图 4 5个状态的例化代码如图4。其中重点要看.out变量的例化,有不同。该模块调用之后的输出分别输出到模块中不同的变量中。 在者,每次例化都对模块的my_addr地址进行了更改(my_addr中分别代表了该模块的地址,再下文中将具体说明),其地址分别为: reg_idle BASE+0 reg_rx BASE+1 reg_tx BASE+2 reg_fdx BASE+3 reg_ddr BASE+4 表 1(BASE=184,下文紧接着给出BASE值出处) 图 5 其中BASE在gpio_atr模块例化调用的程序中可以找到其具体值 可以看到例化该模块时将SR_GPIO给了BASE,及BASE=184,并且刚好留有5个地址位,对应着上述的5个工作状态。 三、 gpio_atr内实现功能分析 前文已经说明,该模块实现了对射频子板接口的输入、输出数据的控制,该部分将分析其中代码,分析其工作原理。 1 输入,输出数据选择 图 6 该部分代码如图6所示,其通过两个输入tx、rx实现了数据位的选择。从RTL视图中可以看出其中tx、rx分别来自相同模块vita_tx_chain、vita_rx_chain中的run引脚得到。如下图7位vita_tx_chain模块 图 7 2 执行in/out选择以及赋值 图 8 图8位该部分代码,其主要实现的功能室根据ddr变量的值不同对引脚进行幅值,其中gpio为32位的inout型。追溯到其例化程序(图5)可以看到其例化过程中,前16位是tx,后16位是rx。所以在这里猜测,ddr的数据为,前16位是’1’,后16位是’0’。即gpio的前16位(tx)根据rgpio的值进行输出赋值,而后16位(rx)保持高阻态作为输入引脚等待数据输入。 同时在RTL视图中,我们也可以看到,gpio最终分别连接在了FPGA硬件的io_tx和io_rx引脚上。 图 9 3 回读功能分析
该部分代码比较简单,每当时钟上升沿来临时,读取一次gpio的值,然后输出给settings_fifo_ctrl模块进行进一步的处理。 四、 gpio_atr其他输入引脚说明 1 set_stb引脚 该引脚在setting_reg模块中例化,为状态控制引脚,只有在该引脚输入为1的时候,setting_reg中才会对输出变量赋值。 其状态settings_bus_crossclock模块控制。 2 set_addr[7:0]引脚 该引脚为地址输入引脚,该数据同样有settings_bus_crossclock中的set_addr_o引脚控制 3 set_addr[31:0]引脚 该引脚为地址输入引脚,该数据同样有settings_bus_crossclock中的set_data_o引脚控制