如何在verilog中为16个端口映射内存

how to map memory for 16 ports in verilog

module testing123(Clk, Rst_n);
. . .
wire [7:0] port1_data;
wire [7:0] port2_data;
wire [7:0] port3_data;
wire [7:0] port4_data;
wire [7:0] port5_data;
wire [7:0] port6_data;
wire [7:0] port7_data;
wire [7:0] port8_data;
wire [7:0] port9_data;
wire [7:0] port10_data;
wire [7:0] port11_data;
wire [7:0] port12_data;
wire [7:0] port13_data;
wire [7:0] port14_data;
wire [7:0] port15_data;

 reg [flit_port_width-1:0] flit_out1;
 reg [flit_port_width-1:0] flit_out2;
 reg [flit_port_width-1:0] flit_out3;
 reg [flit_port_width-1:0] flit_out4; 
 reg [flit_port_width-1:0] flit_out5; 
 reg [flit_port_width-1:0] flit_out6;
 reg [flit_port_width-1:0] flit_out7;
 reg [flit_port_width-1:0] flit_out8;
 reg [flit_port_width-1:0] flit_out9;
 reg [flit_port_width-1:0] flit_out10;
 reg [flit_port_width-1:0] flit_out11;
 reg [flit_port_width-1:0] flit_out12;
 reg [flit_port_width-1:0] flit_out13;
 reg [flit_port_width-1:0] flit_out14;
 reg [flit_port_width-1:0] flit_out15;  
 . . .

RAM_Memory #(/*addr_width*/ 32'd16,
        /*data_width*/ 32'd8,
        /*lo*/ 32'd0,
        /*hi*/ 32'd63) Memory1(.clk(Clk)
,.rst(Rst_n)
,.flit_out(flit_out1)
,.dataout(port1_data)
);
RAM_Memory #(/*addr_width*/ 32'd16,
        /*data_width*/ 32'd8,
        /*lo*/ 32'd0,
        /*hi*/ 32'd63) Memory2(.clk(Clk)
,.rst(Rst_n)
,.flit_out(flit_out2)
,.dataout(port2_data)
);
RAM_Memory #(/*addr_width*/ 32'd16,
        /*data_width*/ 32'd8,
        /*lo*/ 32'd0,
        /*hi*/ 32'd63)  Memory3(.clk(Clk) ...
);
. . . 
endmodule

module RAM_Memory(
  flit_out,
 rst,
 clk,    
  dataout
);

  parameter                   addr_width = 1;
  parameter                   data_width = 1;
  parameter                   lo = 0;
  parameter                   hi = 1;

integer count, i;

input [34:0] flit_out;
input rst,clk;
output [data_width - 1 : 0] dataout;

reg we;
 reg [data_width - 1 : 0] dataout;
 reg [addr_width - 1 : 0] addr;
 reg [data_width - 1 : 0] data_in;
 reg [data_width - 1 : 0] mem [lo:hi];

 initial begin 
    count =0; i=0;
 end

 always @(posedge clk)begin
        count<=count+1;
        we<=0;
  if(count>=1) begin
         we<=1;
end 
end 

always @(we)begin 
            assign data_in = flit_out[7:0];
            assign addr = flit_out[23:8];
            mem[addr]<= data_in;
        assign dataout = mem[addr];         
    end

always @(count)begin
        if(count>=68)begin
            count<=0;
        end
    end
  endmodule

这里给出一个RAM_Memory模块,通过端口映射到其他模块testing123,用于将数据从15个端口存储到64宽内存。但是只有一个端口内存模块存储64个数据,"mem"寄存器不会为其他映射模块刷新。数据会丢失。如何刷新"mem"寄存器或所有映射端口从0值开始?

我没有完全理解这个问题,但发现了一些错误。您的代码包含:

always @(we)begin 
        assign data_in = flit_out[7:0];
        assign addr = flit_out[23:8];
        mem[addr]<= data_in;
    assign dataout = mem[addr];         
end

其中包含一些问题。

  1. 您触发了始终开启的 we 但未在块内使用 we。这并不代表硬件中的任何内容。您更有可能希望触发器在使能为高时更新。

代码示例

always @(posedge clk) begin
  if (en) begin
    //..
  end
 end
  1. 在内部使用 assign 可能总是无法达到您的预期。

您很可能只想:

always @* begin 
  data_in = filt_out[7:0]
  addr    = flit_out[23:8];
  dataout = mem[addr];
  1. 最好不要混合使用非阻塞 (<=) 和阻塞 (=) 分配。如果它们都是触发器 (@(posedge clk)) 则使用非阻塞 (<=) 如果它是组合 (always @*) 则使用阻塞 (=).

有问题的代码块将变为

always @(posedge clk)begin 
  if (we) begin
    data_in   <= flit_out[7:0];
    addr      <= flit_out[23:8];
    mem[addr] <= data_in;
    dataout   <= mem[addr];         
  end
end

查看代码,我认为这不是您想要的 data_in 并且 addr 解码应该在该块之外完成。

//Semantically split the bus
assign  data_in   = flit_out[7:0];
assign  addr      = flit_out[23:8];

always @(posedge clk)begin 
  if (we) begin
    mem[addr] <= data_in;
    dataout   <= mem[addr];         
  end
end

一些使您更容易阅读代码的建议。

使用现代端口声明对可读性有很大影响。

module RAM_Memory(
  flit_out,
 rst,
 clk,    
  dataout
);

  parameter                   addr_width = 1;
  parameter                   data_width = 1;
  parameter                   lo = 0;
  parameter                   hi = 1;

input [34:0] flit_out;
input rst,clk;
output [data_width - 1 : 0] dataout;
reg [data_width - 1 : 0] dataout;

变成

module RAM_Memory#(
  parameter ADDR_WIDTH = 1, //They don not have to be upper case 
  parameter DATA_WIDTH= 1, // But most languages semantically define upper case as constants
  parameter LO = 0;
  parameter HI = 1;
)(
  input            [34:0] flit_out,
  input                   rst,
  input                   clk,    
  output [DATA_WIDTH-1:0] dataout
);

您的实例可以从 :

RAM_Memory #(/*addr_width*/ 32'd16,
        /*data_width*/ 32'd8,
        /*lo*/ 32'd0,
        /*hi*/ 32'd63) Memory2(.clk(Clk)
,.rst(Rst_n)
,.flit_out(flit_out2)
,.dataout(port2_data)
);

RAM_Memory #(
 .ADDR_WIDTH(  6 ), //No need to specify the width of parameter
 .DATA_WIDTH(  8 ), 
 .LO        (  0 ),
 .HI        ( 63 ) 
) Memory2 (
  .clk      ( Clk       )
 ,.rst      ( Rst_n     )
 ,.flit_out ( flit_out2 )
 ,.dataout  ( port2_data)
);

Accessing instance of one module from inside of several other modules? (verilog)