目录
SV DAY6
未完成:
实验0代码解读
其实实验0是没有formater这一部分的
通道端slave和FIFO的代码
//
module slave_fifo (
input clk_i, // Clock input
input rstn_i, // Reset signal
input [31:0] chx_data_i, // 通道数据输入---->From outside
input a2sx_ack_i, // Read ack ---->From Arbiter
input chx_valid_i, // 通道数据高位有效--->From Outside
output reg [31:0] slvx_data_o, // Data Output ---->To Arbiter
output [5:0] slvx_margin_o, // Data margin ---->To Outside
output reg chx_ready_o, // Ready to accept data--->To outside
output reg slvx_val_o, // Output data is valid--->To Arbiter
output reg slvx_req_o // Request to send date--->To Arbiter
);
//声明内部变量,FIFO需要用到指针//
reg [5:0] wr_pointer_r;
reg [5:0] rd_pointer_r;
reg [31:0] mem [0:31]; //FIFO宽度32深度32
//声明net类型的变量,分别是FIFO满了,空了,可以读的信号,还有数据空间裕量//
wire full_s, empty_s, rd_en_s ;
wire [5:0] data_cnt_s;
//同步FIFO空满的标志,指针完全相同则为空,最高位相反其他位相同则为满//
assign full_s = ({~wr_pointer_r[5],wr_pointer_r[4:0]}==rd_pointer_r);
assign empty_s = (wr_pointer_r == rd_pointer_r);
//cnt用来计算FIFO还有多少空间?
assign data_cnt_s = (6'd32 - (wr_pointer_r - rd_pointer_r));
assign slvx_margin_o = data_cnt_s;
assign rd_en_s = a2sx_ack_i;
//如果不满,ready信号置1,表示可以进来数据//
always @ (*) //ready signal
begin
if (!full_s) chx_ready_o = 1'b1;
else chx_ready_o = 1'b0;
end
//如果不空,req信号置1,表示可以发送数据,和上面可以同时出现//
always @ (*) //reset signal
begin
if (!rstn_i) slvx_req_o = 1'b0;
else if (!empty_s) slvx_req_o = 1'b1;
else slvx_req_o = 1'b0;
end
//写指针的定义,由于是同步FIFO,不用跨时钟域转换格雷码
always @ (posedge clk_i or negedge rstn_i)
begin : WRITE_POINTER
if (!rstn_i) begin
wr_pointer_r <= 6'b0000;
end else
if (chx_valid_i && chx_ready_o) begin
wr_pointer_r <= wr_pointer_r + 6'b0001;
end
end
//读指针
always @ (posedge clk_i or negedge rstn_i)
begin : READ_POINTER
if (!rstn_i) begin
rd_pointer_r <= 6'b0000;
end else
if (rd_en_s && (!empty_s)) begin
rd_pointer_r <= rd_pointer_r + 6'b0001;
end
end
//若无复位信号,且read使能信号高位,FIFO不空,则valid信号置1,表示可以输出(读)数据
always @ (posedge clk_i or negedge rstn_i)
begin
if (!rstn_i) slvx_val_o <= 1'b0;
else if (rd_en_s && (!empty_s))
slvx_val_o <= 1'b1;
else slvx_val_o <= 1'b0;
end
// 将mem中的数据给到输出
always @ (posedge clk_i )
begin : READ_DATA
if (rstn_i && rd_en_s && (!empty_s)) begin
slvx_data_o <= mem[rd_pointer_r[4:0]];
end
end
// 将外部输入数据写给mem
always @ (posedge clk_i)
begin : MEM_WRITE
if (rstn_i && chx_valid_i && chx_ready_o) begin
mem[wr_pointer_r[4:0]] <= chx_data_i;
end
end
endmodule
arbiter部分
//需要用到clk和rst就要继续声明,变量名保持一致即可。//
module arbiter(
input clk_i,
input rstn_i,
//输入端是来自上一个module slv_fifo读出来的数据,三个通道分别是012.包括数据,req,valid总共3*3个//
input [31:0] slv0_data_i,
input [31:0] slv1_data_i,
input [31:0] slv2_data_i,
input slv0_req_i,
input slv1_req_i,
input slv2_req_i,
input slv0_val_i,
input slv1_val_i,
input slv2_val_i,
//a2si_ack_0是assign给rd_en_s的,也就是告诉3个FIFO谁可以读出数据给到arb