我正在编写一个 SystemVerilog 模块,该模块将数据存储在 2 个存储器中以进行矩阵向量乘法。我正在运行我的教授提供的测试平台,但我一直在努力调试一个内存地址逻辑,它根本不会重置为零!非常感谢任何想法或建议。
模块代码:
module input_mems #(
parameter INW=4,
parameter M=4,
parameter N=4,
localparam LOGN = $clog2(N),
localparam LOGMN = $clog2(M*N)
)(
input clk, reset,
input [INW-1:0] AXIS_TDATA,
input AXIS_TVALID,
input AXIS_TLAST,
input [LOGN:0] AXIS_TUSER,
output logic AXIS_TREADY,
output logic input_loaded,
input done,
output logic [LOGN-1:0] D,
input [LOGN-1:0] vector_read_addr,
output logic [INW-1:0] vector_val,
output logic [LOGN-1:0] vector_row,
input [LOGMN-1:0] matrix_read_addr,
output logic [INW-1:0] matrix_data
);
enum {RESET, INM, INV, INL} state, next_state;
logic [LOGMN-1:0] matrix_addr;
logic matrix_wr_en;
logic [LOGN-1:0] vector_addr;
logic vector_wr_en;
logic matrix_loaded;
logic vector_loaded;
logic new_matrix;
assign new_matrix = AXIS_TUSER[0];
logic INM_skip;
logic [$clog2(N)-1:0] row;
assign row = AXIS_TUSER[$clog2(N):1];
logic [INW+$clog2(N)-1:0] vector_cat_in;
logic [INW+$clog2(N)-1:0] vector_cat_out;
logic data_ready_INM;
logic data_ready_INV;
//fsm
//output logic
always_comb begin
if(state == RESET) begin
AXIS_TREADY = 0;
input_loaded = 0;
end
else if(state == INM) begin
AXIS_TREADY = 1;
input_loaded = 0;
end
else if(state == INV) begin
AXIS_TREADY = 1;
input_loaded = 0;
end
else if(state == INL) begin
input_loaded = 1;
AXIS_TREADY = 0;
end
else begin
AXIS_TREADY = 0;
input_loaded = 0;
end
end
//next state logic
always_comb begin
if((state == RESET) && (reset == 1)) //stay in reset state
next_state = RESET;
else if((state == RESET) && (reset == 0)) //exit reset state
next_state = INM;
else if((state == INM) && (matrix_loaded == 1)) //matrix is loaded
next_state = INV;
else if((state == INM) && (INM_skip == 1)) //new_matrix says reuse matrix
next_state = INV;
else if((state == INM) && (matrix_loaded == 0)) //matrix not loaded yet
next_state = INM;
else if((state == INV) && (vector_loaded == 1)) //TLAST asserted
next_state = INL;
else if((state == INV) && (vector_loaded == 0)) //vector not loaded yet
next_state = INV;
else if((state == INL) && (done == 1)) //go back to beginning
next_state = INM;
else if((state == INL) && (done == 0)) //data not loaded yet
next_state = INL;
end
//state register
always_ff @(posedge clk) begin
if(reset == 1)
state <= RESET;
else
state <= next_state;
end
//memory reset
always_ff @(posedge clk) begin
if (reset == 1) begin
matrix_addr <= 0;
vector_addr <= 0;
D <= 0; //reset D counter
end
else if (state == INL && next_state == INM) begin
matrix_addr <= 0;
vector_addr <= 0;
D <= 0;
end
end
//Matrix memory
memory #(
.WIDTH(INW),
.SIZE(M*N)
)memory_matrix(
.data_in(AXIS_TDATA),
.data_out(matrix_data),
.clk(clk),
.addr(matrix_addr),
.wr_en(matrix_wr_en));
//Vector memory
memory#(
.WIDTH(INW+$clog2(N)),
.SIZE(N)
)memory_vector(
.data_in(vector_cat_in),
.data_out(vector_cat_out),
.clk(clk),
.addr(vector_addr),
.wr_en(vector_wr_en));
//Matrix
//wr_en signal
always_comb begin
if((AXIS_TREADY == 1) && (AXIS_TVALID == 1) && (state == INM))
matrix_wr_en = 1;
else
matrix_wr_en = 0;
end
//Matrix address
always_ff @(posedge clk) begin
if(matrix_wr_en == 1)
matrix_addr <= matrix_addr + 1;
else
matrix_addr <= matrix_addr;
end
//Matrix loaded check
always_comb begin
if(reset == 1)
matrix_loaded = 0;
else if(matrix_addr == $clog2(M*N)) //we have written to all addresses
matrix_loaded = 1;
else
matrix_loaded = 0;
end
//new_matrix check
always_comb begin
if((AXIS_TREADY == 1) && (AXIS_TVALID == 1) && (state == INM) && (matrix_addr == 0) && (new_matrix == 0))
INM_skip = 1;
else
INM_skip = 0;
end
//Vector
//wr_en signal
always_comb begin
if((AXIS_TREADY == 1) && (AXIS_TVALID == 1) && (state == INV))
vector_wr_en = 1;
else
vector_wr_en = 0;
end
//Vector address
always_ff @(posedge clk) begin
if(reset == 1)
vector_addr <= 0;
else if(vector_wr_en == 1)
vector_addr <= vector_addr + 1;
else
vector_addr <= vector_addr;
end
//Vector loaded check
always_comb begin
if(reset == 1)
vector_loaded = 0;
else if(AXIS_TLAST == 1) //TLAST signal
vector_loaded = 1;
else
vector_loaded = 0;
end
//Vector Data Concat.
always_comb begin
vector_cat_in = {AXIS_TDATA, row};
end
//D Counter
always_ff @(posedge clk) begin
if(reset == 1)
D <= 0;
else if((AXIS_TREADY == 1) && (AXIS_TVALID == 1) && (state == INV) && (AXIS_TDATA != 0))
D <= D + 1;
else
D <= D;
end
//Loaded
//Matrix Read
always_ff @(posedge clk) begin
if(input_loaded == 1)
matrix_addr <= matrix_read_addr;
else
matrix_addr <= matrix_addr;
end
//Vector Read
always_ff @(posedge clk) begin
if(input_loaded == 1) begin
vector_addr <= vector_read_addr;
vector_val <= vector_cat_out[INW+$clog2(N)-1:$clog2(N)]; // Select INW upper bits
vector_row <= vector_cat_out[$clog2(N)-1:0]; // Select $clog2(N) lower bits
end
else
vector_addr <= vector_addr;
end
endmodule
不要过多关注数据发生的情况,我只是不明白为什么我的重置不会将我的matrix_addr设置为零。
该帖子在变量matrix_addr上有多个驱动程序
这个过程
//memory reset
always_ff @(posedge clk) begin
if (reset == 1) begin
matrix_addr <= 0;
vector_addr <= 0;
D <= 0; //reset D counter
end
else if (state == INL && next_state == INM) begin
matrix_addr <= 0;
vector_addr <= 0;
D <= 0;
end
end
还有这个过程
//Matrix address
always_ff @(posedge clk) begin
if(matrix_wr_en == 1)
matrix_addr <= matrix_addr + 1;
else
matrix_addr <= matrix_addr;
end
还有这个过程
//Loaded
//Matrix Read
always_ff @(posedge clk) begin
if(input_loaded == 1)
matrix_addr <= matrix_read_addr;
else
matrix_addr <= matrix_addr;
end
全部驱动相同的变量matrix_addr。
只有一个进程可以驱动同一范围内的变量。
我在 EDA Playground 上使用 Cadence 时遇到了几个与此类似的编译错误。
xmelab: *E,MULAXX (./design.sv,124|11): Multiple drivers to always_ff output variable matrix_addr detected.