I have a problem when I try to simulate a circuit which is supposed to process data taken from an SRAM memory. Firstly, an SRAM memory is filled with data, this could be seen if one has a look over the last testbench, than, the stored data will be processed by an automaton. Then, the output, in some specific situations, is stored in another SRAM memory. Thus, when simulated, the circuit behaves in a strange way, because the rd_data_instrucions, which represents read data from the first SRAM memory, is always undefined. Consequently, all other signals depending on rd_data_instructions are undefined too. The code is posted here.
P.S.: Modules sram_1port_instructions and sram_1port_data should behave as clocked SRAMs, having a write enable signal so that when wr_en is high, the memory stores data received(wr_data) and when wr_en is low, the memory could output data (rd_data).
Module user represents an "interface" which facilitates the writing process so that writing in the SRAM instruction memory does not require the address to which data is stored because this module provides a mechanism which increments the "write-address-pointer" of the memory. Further, we can see the corresponding testbench for this module. Then, we can see the corresponding module of another memory, which is created for output storage, and a module designed to facilitate the reading process (i.e. something similar to the previous situation, but, instead of facilitating the writing process, it eases reading).
Last, but not least, we may distinguish a wishbone module, which is supposed to interconnect all the previous modules in order to create a digital system. Consequently, an automaton takes data from the SRAM instruction memory, then outputs some data which is stored in another memory. Finally, the outcome could be read from the SRAM data memory.
The problem occurs when I try to simulate the system because I encounter difficulties when trying to read some signals, e.g. rd_data_instructions, which should display the previously stored values from the SRAM instruction memory, implicitly the "in" signal, which should provide the input for the automaton, and so on. Within the wishbone module, I used a special signal labelled "start" which sets the write-enable on 0 so that the SRAM memory is prepared for the reading process. This special signal actually triggers the automaton, by "feeding" it with input data from the memory.
//wishbone module
module wishbone(
input clk,rst,start,
output reg [2:0]in,
output reg wr_en_instructions,wr_en_display,
input [2:0] wr_data_instructions,//created for usr, in order to make possible to write data
output reg [3:0] wr_data_display,
output [2:0] rd_data_instructions,
output [3:0] rd_data_display,//created for user, in order to make possible the display
output [12:0]o
);
reg [15:0] pointer_instructions,pointer_display;
initial wr_en_instructions = 1'b1;
control_unit i0(.clk(clk),.rst(rst),.in(in),.o(o));
user i1(.clk(clk),.wr_en(wr_en),.address_in(pointer_instructions),.wr_data(wr_data_instructions),.rd_data(rd_data_instructions));
display i2(.clk(clk),.wr_en(wr_en_display),.address_in(pointer_display),.wr_data(wr_data_display),.rd_data(rd_data_display));
integer i = 0;
always # * begin
wr_en_display = ~wr_en_instructions;
end
always #(posedge clk) begin
if(start) begin
pointer_instructions <= 16'b0;
pointer_display <= 16'b0;
wr_en_instructions <= 1'b0;
end
else begin
$display(rd_data_instructions);
if(!wr_en_instructions) begin
if(rd_data_instructions == 3'b1xx) begin
wr_en_instructions <= 1'b1;//???
end
else if(rd_data_instructions == 3'b010) begin
in <= rd_data_instructions;
wr_data_display <= o;
pointer_instructions <= pointer_instructions + 1;
pointer_display <= pointer_display + 1;
end
else begin
in <= rd_data_instructions;
pointer_instructions <= pointer_instructions + 1;
end
end
else begin
i = i + 1;
end
end
end
endmodule
//testbench for top module
module wishbone_tb(
output reg clk,rst,start,
output [2:0]in,
output wr_en_instructions,wr_en_display,
output reg [2:0] wr_data_instructions,//created for usr, in order to make possible to write data
output [3:0] wr_data_display,
output [2:0] rd_data_instructions,
output [3:0] rd_data_display,//created for user, in order to make possible the display
output [12:0]o
);
wishbone cut(
.clk(clk),.rst(rst),.start(start),
.in(in),
.wr_en_instructions(wr_en_instructions),.wr_en_display(wr_en_display),
.wr_data_instructions(wr_data_instructions),
.wr_data_display(wr_data_display),
.rd_data_instructions(rd_data_instructions),
.rd_data_display(rd_data_display),
.o(o)
);
initial $dumpvars(0,wishbone_tb);
initial begin
clk = 1'd1;
repeat (600000)
#100 clk = ~clk;
end
initial begin
rst = 1'b1;
#400 rst = 1'b0;
end
initial begin
start = 1'b0;
#13000400 start = 1'b1;
#400 start = 1'b0;
end
initial begin
wr_data_instructions = 3'd1;
#3000400 wr_data_instructions = 3'd2;
#1000000 wr_data_instructions = 3'd1;
#3000000 wr_data_instructions = 3'd0;
#2000000 wr_data_instructions = 3'd3;
#1000000 wr_data_instructions = 3'd1;
#3000000 wr_data_instructions = 3'd4;//halt
end
endmodule
Related
module delay(
input [11:0] data_in,
input delay_clk, //here i will use a 20kHz clk
output reg [11:0] data_out
);
reg[11:0]memory[0:20000];
reg[15:0]write_index;//i
reg[15:0]read_index;//j
initial begin
write_index = 16'b0000000000000000;
read_index = 16'b0100111000100000;
end
always#(posedge delay_clk) begin
read_index = read_index+1;
memory [write_index] <= data_in;
data_out <= memory[read_index];
end
endmodule
I want to make a 1 second delay by using the circular memory.
I generate bitstream and program it to FGPA but there is no sound come out.
So how can i improve this verilog codes?
You don't increment write_index anywhere (like you do with read_index), it will cause this hardware to overwrite 1 memory cell over and over again. I don't think this is what you wanted, it beats the idea of using a memory array.
If you intend to store read_index in some kind of a memory element use <= assignment like the ones for memory and data_out.
Your write_index and read_index are a 16 bit variables. You use them to iterate over a 20k cells memory. They will overflow at some point. Is this intentional? I mean why 16bits and is it ok for those indexes to point at e.g. address 41k?
I have a problem with the Synthesise in VHDL. This is the part of the code where it gives me error:
CASE stare_curenta IS
WHEN verde =>
stare_urm <= albastru;
rosuS1368stg <= '1';
galbenS1368stg <= '0';
verdeS1368stg <= '0';
rosuS1368 <= '0';
galbenS1368 <= '0';
if ( clock'event and clock = '0') then
galbenS1368 <= '1';
end if;
verdeS1368 <= '1';
rosup1v1i4v2i3v1i2v2i6v1i5v2i8v1i7v2 <= '0';
verdep1v1i4v2i3v1i2v2i6v1i5v2i8v1i7v2 <= '1';
rosuS2457stg <= '1';
galbenS2457stg <= '0';
if (clock'event and clock = '0') then
galbenS2457stg <= '1';
end if;
verdeS2457stg <= '0';
rosuS2457 <= '1';
galbenS2457 <= '0';
verdeS2457 <= '0';
rosup2v1i1v2i4v1i3v2i5v1i8v2i7v1i6v2 <= '1';
verdep2v1i1v2i4v1i3v2i5v1i8v2i7v1i6v2 <= '0';
I have another process of clock and clock'event below, like this one:
PROCESS(clock,stare_urm)
BEGIN
if (clock'event and clock = '1')then
stare_curenta <= stare_urm;
end if;
END PROCESS;
The 'Check Syntax' and 'Simulation' are going well, only the Synthesise it gives me the error: Signal galbenS1368 cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
Thank you!
The problem is:
if (clock'event and clock = '0') then
inside your state decoding. It's not a syntax problem, and simulators will dutifully carry out exactly what you wrote (though you may not get the results you intended), but as the error message says, it's not a supported synthesis style (embedding a clocked segment of code, i.e. a portion of a process intended to create a register, inside a larger combinational process).
Either way, I'm not sure it's what you really want to do. A process is evaluated when a signal in its sensitivity list changes. The way you've coded it, you're effectively saying "when this process is evaluated, if at that exact instant the clock is falling, register the signal", even though what you probably intended was to assign a value which is then registered on the next falling clock edge.
Assuming that last statement is so, it basically tells you how to code it. It has two parts. (1) assign a value:
when verde =>
...
galbenS2457stg <= '1';
(2) which is registered on the next falling clock edge:
process (clock)
begin
if clock'event and clock = '0' then
galbenS2457stg_reg <= galbenS2457stg;
end if;
end process;
Synchronous design in synthesis is essentially register -> a bunch of combinational logic -> register -> combinational logic -> etc. Coding it like that, with your registers separated from your combinational logic in code, is a good way to start thinking more in terms of hardware.
edit for clarification
Based on your responses in the comments, it seems I was not clear enough on what I was recommending.
You have some sort of process to handle your state machine. I'm assuming most of it is unclocked. You tried to insert small, clocked portions into it, and this is what the tool is complaining about. I'm suggesting you try coding in the following manner (not complete code, just to illustrate the point):
comb1 : process (...) -- fill in sensitivity list as needed
begin
-- state machine decode
...
when verde =>
...
galbenS2457stg <= '1';
...
end process comb1;
clocked1 : process (clock)
begin
if clock'event and clock = '0' then
galbenS2457stg_reg <= galbenS2457stg;
end if;
end process clocked1;
Change the names if you need to - since you only posted part of your code, it wasn't evident that galbenS2457stg was an output at all. However you name them, the signal assigned in your state decode process should be an internal signal, and would be declared in the architecture declarative region, not as an output port, while the clocked signal would be the output port, and would be declared as such.
How can I make a memory module in which DATA bus width are passed as parameter to each instances and my design re-configure itself according to the parameter? For example, assuming I have byte addressable memory and DATA-IN bus width is 32 bit (4 bytes written in each cycle) and DATA-OUT is 16 bits (2 bytes read each cycle). For other instance DATA-IN is 64 bits and DATA-OUT is 16 bits. For all such instances my design should work.
What I have tried is to generate write pointer values according to design parameters, e.g. DATA-IN 32 bit, write pointer will increment 4 every cycle while writing. For 64 bit -increment will be by 8 and so on.
Problem is: how to make 4 or 8 or 16 bytes to be written in single cycle according to parameters passed to instance?
//Something as following I want to implement. This memory instance can be considered as internal memory of FIFO having different datawidth for reading and writing in case you think of an application of such memory
module mem#(parameter DIN=16, parameter DOUT=8, parameter ADDR=4,parameter BYTE=8)
(
input [DIN-1:0] din,
output [DOUT-1:0] dout,
input wen,ren,clk
);
localparam DEPTH = (1<<ADDR);
reg [BYTE-1:0] mem [0:DEPTH-1];
reg wpointer=5'b00000;
reg rpointer=5'b00000;
reg [BYTE-1:0] tmp [0:DIN/BYTE-1];
function [ADDR:0] ptr;
input [4:0] index;
integer i;
begin
for(i=0;i<DIN/BYTE;i=i+1) begin
mem[index] = din[(BYTE*(i+1)-1):BYTE*(i)]; // something like this I want to implement, I know this line is not allowed in verilog, but is there any alternative to this?
index=index+1;
end
ptr=index;
end
endfunction
always #(posedge clk) begin
if(wen==1)
wpointer <= wptr(wpointer);
end
always #(posedge clk) begin
if(ren==1)
rpointer <= ptr(rpointer);
end
endmodule
din[(BYTE*(i+1)-1):BYTE*(i)] will not compile in Verilog because the MSB and LSB select bits are both variables. Verilog requires a known range. +: is for part-select (also known as a slice) allows a variable select index and a constant range value. It was introduced in IEEE Std 1364-2001 § 4.2.1. You can also read more about it in IEEE Std 1800-2012 § 11.5.1, or refer to previously asked questions: What is `+:` and `-:`? and Indexing vectors and arrays with +:.
din[BYTE*i +: BYTE] should work for you, alternatively you can use din[BYTE*(i+1)-1 -: BYTE].
Also, you should use non-blocking assignments (<=) to mem. In your code read and write can happen at the same time. With blocking there is a race condition between when accessing the same byte. It may synthesize, but your RTL and gate simulation may generated different results. I also strongly advice agent using functions for assigning memory. Functions in synthesizable code without nasty surprises need to self contained without references on anything outside of the function and any internal variables are always reset to a static constant at the start of the function.
With the guidelines mentioned above, I'd recommend recoding to something like the below. This is a template to start with, not a free lunch. I left out the out-of-range index compensation for you to figure out on your own.
...
localparam DEPTH = (1<<ADDR);
reg [BYTE-1:0] mem [0:DEPTH-1];
reg [ADDR-1:0] wpointer, rpointer;
integer i;
initial begin // init values for pointers (FPGA, not ASIC)
wpointer = {ADDR{1'b0}};
rpointer = {ADDR{1'b0}};
end
always #(posedge clk) begin
if (ren==1) begin
for(i=0; i < DOUT/BYTE; i=i+1) begin
dout[BYTE*i +: BYTE] <= mem[rpointer+i];
end
rpointer <= rpointer + (DOUT/BYTE);
end
if (wen==1) begin
for(i=0; i < DIN/BYTE; i=i+1) begin
mem[wpointer+i] <= din[BYTE*i +: BYTE];
end
wpointer <= wpointer + (DIN/BYTE);
end
end
I am trying to implement a small line buffer in Verilog. I am putting data from one end and reading it from the other side.
wire [29:0] temp_pixel;
reg [29:0] temp_buffer[2:0];
I can use blocking assigment statements like these and it should work as expected.
always #(posedge TD_CLK27)
begin
temp_buffer[0] = temp_buffer[1];
temp_buffer[1] = temp_buffer[2];
temp_buffer[2] = temp_pixel;
end
But, can I use non-blocking statements(shown below) and still get the expected result? Or would temp_buffer[1] get overwritten by temp_buffer[2], before it was read into temp_buffer[0]?
always #(posedge TD_CLK27)
begin
temp_buffer[0] <= temp_buffer[1];
temp_buffer[1] <= temp_buffer[2];
temp_buffer[2] <= temp_pixel;
end
Would both the blocks work same, or does it compulsorily have to be blocking assignment statements and why?
This minimal example of blocking, notice the = :
module test(
input data_in, clk,
output data_out
);
reg [2:0] temp;
always #(posedge clk)
begin
temp[2] = data_in;
temp[1] = temp[2];
temp[0] = temp[1];
end
assign data_out = temp[0];
endmodule
creates 1 Flip-Flop:
While non-blocking, notice the <=:
module test(
input data_in, clk,
output data_out
);
reg [2:0] temp;
always #(posedge clk)
begin
temp[2] <= data_in;
temp[1] <= temp[2];
temp[0] <= temp[1];
end
assign data_out = temp[0];
endmodule
creates 3 flip-flops:
Buffers are created like this:
module test(
input data_in, clk,
output data_out
);
wire [2:0] temp;
buf(temp[2], data_in);
buf(temp[1], temp[2]);
buf(temp[0], temp[1]);
assign data_out = temp[0];
endmodule
More information here.
Both the blocks are different.
When you use blocking assignments, the next statement does not begin executing until the assignment has finished.
x = #5 y + z;
This statement is executed as follows:
Evaluates the RHS expression and save the result
Wait for the specified delay
Perform assignment
So in your case there is no delay while assigning your buffers you have created and verilog interprets it as a single flip flop.
x <= y + z;
The normal non-blocking assignment is executed as follows:
Evaluate the RHS expression and save the result in a temporary buffer
Finish executing all other events in the procedural block except for other non-blocking assignments
Perform the assignment at the end.
So in your second example, temp_buffer[2] gets the previous value of temp_buffer[1]. So there is a cycle delay before which you can access the value. so there is a string of flip flops (depending on your code)before you get the actual output.
Again , the link in previous answer is an excellent paper to read.here are a few more
Sunburst Design
Link2
I have an array of vectors that I want to be stored in Block RAM on a Virtex-5 using ISE 13.4. It is 32Kb which should fit in 1 BRAM but it is all being stored in logic. My system uses an AMBA APB bus so I check for a select line and an enable line. Please help me understand why this code isn't inferring a BRAM. Note: this is a dummy example which is simpler to understand and should help me with my other code.
architecture Behavioral of top is
type memory_array is array (63 downto 0) of std_logic_vector(31 downto 0);
signal memory : memory_array;
attribute ram_style: string;
attribute ram_style of memory : signal is "block";
begin
process(Clk)
begin
if(rising_edge(Clk)) then
if(Sel and Wr_en and Enable) = '1' then
memory(to_integer(Paddr(5 downto 0))) <= Data_in;
elsif(Sel and not Wr_en and Enable) = '1' then
Data_out <= memory(to_integer(Paddr(5 downto 0)));
end if;
end if;
end process;
end Behavioral;
I declare the ram_style of the array as block but the XST report says: WARNING:Xst:3211 - Cannot use block RAM resources for signal <Mram_memory>. Please check that the RAM contents is read synchronously.
It appears that the problem lies in a read_enable condition, but the Virtex 5 User Guide makes it sound like there is an enable and a write_enable on the BRAM hard blocks. I could drive the output all the time, but I don't want to and that would waste power. Any other ideas?
Your logic may not match how your device's BRAM works (there are various limitations depending on the device). Usually, the data_out is updated on every clock cycle the RAM is enabled for, not just "when not writing" - try this:
process(Clk)
begin
if(rising_edge(Clk)) then
if(Sel and Enable) = '1' then
Data_out <= memory(to_integer(Paddr(5 downto 0)));
if wr_en = '1' then
memory(to_integer(Paddr(5 downto 0))) <= Data_in;
end if;
end if;
end if;
end process;
I moved the Data_out assignment "upwards" to make it clear that it gets the "old" value - that's the default behaviour of the BRAM, although other styles can also be set up.
Alternatively, the tools may be being confused by the sel and enable and write all in a single if statement - this is because they are mainly "template matching" rather than "function matching" when inferring BRAM. You may find that simply splitting out an "enable if" and a "write if" (as I did above) whilst keeping the rest of the functionality the same is sufficient to make the synthesiser do what is required.
If you are using Xilinx's XST then you can read all about inferring RAMs in the docs (page 204 onwards of my XST user guide - the chapter is called "RAM HDL Coding techniques")
Use the appropriate macro for the BRAM block on your device? I found that to work much better than relying on the synthesis tool not beeing stupid.
I tried many different combinations and here is the only one I got to work:
en_BRAM <= Sel and Enable;
process(Clk)
begin
if(rising_edge(Clk)) then
if(en_BRAM = '1')then
if(Wr_en = '1') then
icap_memory(to_integer(Paddr(5 downto 0))) <= Data_in;
else
Data_out <= icap_memory(to_integer(Paddr(5 downto 0)));
end if;
end if;
end if;
end process;
So I think the enable needs to be on the whole RAM and it can only be 1 signal. Then the write enable can also only be 1 signal and the read has to be only an else statement (not if/elsif). This instantiates a BRAM according to XST in ISE 13.3 on Windows 7 64-bit.