📜 ⬆️ ⬇️

Verilog. RAM wrappers and why it is needed

The fact is that my acquaintance with the FPGA for two years. In my student years, reading code examples from Altera and Xilinx, I paid little attention to the description of RAM and ROM, because this was not necessary. I knew that there was a FIFO, but I didn’t even guess why I needed it. So I defended my diploma by making my project head on.

I found a job thanks to my “knowledge” in the field of FPGA. Immediately, problems emerged that I didn’t suspect: existing projects occupied 90% of the logical elements, and my work was to place digital filters in the projects. It is clear that "in the forehead" to solve this problem was impossible. Rewrite existing code? It helped, but not much. And only then did I understand how to play with RAM to solve the tasks.

Attention! LEDs will not blink here. Instead, the implementation of the shift register in the form of a wrapper for M4K will be considered. This publication assumes minimal familiarity with FPGA and the Verilog language.

To begin with, having made the necessary filter in the forehead in a separate project, it became clear where there is a thin place in it. It turned out to be a shift register of length 444 * 16 bits (444 is the order of the filter, 16 bits is the dimension of the word). With this you need to do something. The thought came to the conclusion that the shift is a trivial operation. Get the current value of the register in step N and write there the value of the register taken in step N-1. After reading through code examples, I found how to do this with RAM:
')
module pip #(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=9) ( input [(DATA_WIDTH-1):0] data, input [(ADDR_WIDTH-1):0] read_addr, write_addr, input we, clk, output reg [(DATA_WIDTH-1):0] q ); (*ramstyle = "M4K"*)reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0]; always @ (posedge clk) begin q <= ram[read_addr]; if (we) ram[write_addr] <= data; end endmodule 


This is taken directly from the examples, only the parameters have changed. It now remains to make this RAM work, as described above. For this, what I called the RAM wrapper was written. A simple state machine:

 module upr #(parameter DATA_WIDTH = 16, parameter ADDR_WIDTH = 9) ( input wire clk, input wire en, input wire [ (DATA_WIDTH-1) : 0 ] ram_upr, input wire [ (DATA_WIDTH-1) : 0 ] data_in, output wire [ (DATA_WIDTH-1) : 0 ] upr_ram, output wire we_ram, output wire [ (ADDR_WIDTH-1) : 0 ] adr_out ); assign upr_ram = ram; assign we_ram = r_we; assign adr_out = r_adr; reg [ 2 : 0 ] r_state = state0; localparam state0 = 3'b001, state1 = 3'b010, state2 = 3'b100; reg [ (ADDR_WIDTH-1) : 0 ] r_adr = {ADDR_WIDTH{1'b0}}; reg [ (DATA_WIDTH-1) : 0 ] ram = {DATA_WIDTH{1'b0}}; reg r_we = 1'b0; always @(posedge clk) if(en) begin case(r_state) state0: r_state <= state1; state1: r_state <= state2; state2: r_state <= state1; endcase end always @(posedge clk) case(r_state) state0: begin r_we <= 1'b0; r_adr <= {ADDR_WIDTH{1'b0}}; ram <= data_in; end state1: begin r_we <= 1'b1; if(r_adr == {ADDR_WIDTH{1'b0}}) ram <= data_in; else ram <= ram_upr; end state2: begin r_adr <= r_adr + 1'b1; r_we <= 1'b0; end endcase endmodule 


It works in two stages + one state that can be used during a reset. The state machine is extremely simple - no conditions for the transition, only the front of the clock signal. At the first step (State1) there is a capture of data, or a previous output value from RAM. It was such a feedback. To the second step, a write signal is set to one and the RAM captures what is needed.

This approach has a significant disadvantage - the shift takes 2 bars, but this problem can be easily solved. Another significant drawback is that it is impossible to “pull out” at least two values ​​from the shift register in one measure. This means that a convolutional encoder cannot be made on this. The advantage of this approach is the saving of logical elements (LE or Slice) at the expense of memory.

How to solve the problem of 2 cycles and, more interestingly, how to make a fully parameterized digital FIR filter based on this, I will tell if it will be interesting to anyone.

Source: https://habr.com/ru/post/134035/


All Articles