how to remove 1 clock delay for read data from the block ROM using Coregen in verilog?? - module

i am trying to read the data from blocked ROM using coregen by loading .coe file. But data will arrive after one clock delay when address initialized.
i want address and data in same clock cycle. module is given inline.
module pixel_read(Clk,output_pixel);
input Clk;
output [7:0] output_pixel;
reg [16:0] ADDR_IN;
initial ADDR_IN = 65535;
always # (posedge Clk)begin
if(ADDR_IN!=65536) begin
ADDR_IN<= ADDR_IN+1;
end
end
imageread MEM1(
.clka(Clk),
.addra(ADDR_IN),
.douta(output_pixel)
);
endmodule
how i remove one clock delay to read data?

You don't actually want a synchronous RAM/ROM. You want an asynchronous one - i.e. a look up table. You can force that by using LUTs instead of BRAMs. BRAMs are always synchronous.

Related

When I add memory clear logic Bram memory turn into distributed ram

I want to create a BRAM that has a data clear logic. With saying that I mean after a reset signal all the data inside of the BRAM needs to be 0.
I coded BRAM in verilog HDL.
(* ram_style = "block" *)
reg [7:0] mem [511:0];
reg [7:0] data_read = 8'b0;
always#(posedge clk) begin
if (write_i) begin
mem[addr_i] <= write_data_i;
end
else begin
data_read <= mem[addr_i];
end
end
assign read_data_o = data_read;
This code block successfully generates BRAM as netlist can be shown in the following image:
But when I add reset logic to BRAM to clear the data inside of it when reset rises, BRAM memory turns into distributed RAM.
This is the data clear logic I have added:
if (rst) begin
for(i=0; i<512 ; i= i+1) begin
mem[i] <= 8'b0;
end
end
Netlist after I added clear logic:
What is the reason of this? Why BRAM becomes distributed Ram? Isn't it possible to create a BRAM with data clear logic ?
The vendor BRAM macro/primitives/hardware do not support a global clear/write 0, or write anything else using a control signal.
See
https://docs.xilinx.com/v/u/2019.2-English/ug901-vivado-synthesis
section 4 for supported RAM inference coding styles.
There are two ways to accomplish some sort of BRAM initialization or global write.
Use a state machine controller to loop thru all the addresses
and assign the values needed (write to the ram in a controlled way using RTL to control the address, data, and wr_en)
Use Vivado IP catalog (or ISE Coregen) generated RAM and a .mif/.coe file. The contents of the .mif/.coe get loaded one time when the FPGA is configured.
More info on using .mif files here:
https://docs.xilinx.com/r/en-US/ug896-vivado-ip/IP-User-Files-ip_user_files-for-Core-Container
The memory generator GUI provides the opportunity to load a .coe file. The .coe is used for synthesis, .mif file for simulation.
If you want to use the generated IP method see:
https://docs.xilinx.com/v/u/en-US/pg058-blk-mem-gen
My preference is a state machine, so that external files and external IP are not needed.

STM32F4 UART HAL driver 'save string in variable buffer'

I am in the process of writing software for an STM32F4. The STM32 needs to pull in a string via a UART. This string is variable in length and comes in from a sensor every second. The string is stored in a fixed buffer, so the buffer content changes continuously.
The incoming string looks like this: "A12941;P2507;T2150;C21;E0;"
The settings of the UART:
Baud Rate: 19200
Word lengt: 8Bits
Parity: None
Stop Bids: 1
Over sampling: 16 Samples
Global interrupt: Enabled
No DMA settings
Part of the used code in the main.c function:
uint8_t UART3_rxBuffer[25];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Receive_IT(&huart3, UART3_rxBuffer, 25); //restart interrupt reception mode
int main(void)
{
HAL_UART_Receive_IT (&huart3, UART3_rxBuffer,25);
}
while (1)
{
}
}
Part of the code in stm32f4xx_it.c
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3);
/* USER CODE BEGIN USART3_IRQn 1 */
/* USER CODE END USART3_IRQn 1 */
}
It does work to fill the buffer with the variable strings in this way, but because the buffer is constantly being replenished, it is difficult to extract a beginning and an end of the string. For example, the buffer might look like this:
[0]'E' [1]'0' [2]'/n' [3]'A' [4]'1' [5]'2' [6]'9' [7]'4' [8]'1' [9]';' [10]'P' etc....
But I'd like to have a buffer that starts on 'A'.
My question is, how can I process incoming strings on the uart correctly so that I only have the string "A12941;P2507;T2150;C21;E0;"?
Thanks in advance!!
I can see three possibilities:
Do all of your processing in the interrupt. When you get to the end of a variable-length message then do everything that you need to do with the information and then change the location variable to restart filling the buffer from the start.
Use (at least) two buffers in parallel. When you detect the end of the variable-length message in interrupt context then start filling a different buffer from position zero and signal to main context that previous buffer is ready for processing.
Use two buffers in series. Let the interrupt fill a ring buffer in a circular way that takes no notice of when a message ends. In main context scan from the end of the previous message to see if you have a whole message yet. If you do, then copy it out into another buffer in a way that makes it start at the start of the buffer. Record where it finished in the ring-buffer for next time, and then do your processing on the linear buffer.
Option 1 is only suitable if you can do all of your processing in less than the time it takes the transmitter to send the next byte or two. The other two options use a bit more memory and are a bit more complicated to implement. Option 3 could be implemented with circular mode DMA as long as you poll for new messages frequently enough, which avoids the need for interrupts. Option 2 allows to queue up multiple messages if your main context might not poll frequently enough.
I would like to share a sample code related to your issue. However it is not what you are exactly looking for. You can edit this code snippet as you wish. If i am not wrong you can also edit it according to option 3.
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART2) {
HAL_UART_Receive_IT(&huart2,&rData,1);
rxBuffer[pos++] = rData;
if (rData == '\n') {
pos = 0;
}
}
Before start, in the main function, before while loop you should enable interrupt for one byte using "HAL_UART_Receive_IT(&huart2,&rData,1);". If your incoming data has limiter like '\n', so you can save whole data which may have different length for each frame.
If you want data frame start with some specific character, then you can wait to save data until you get this character. In this case you can edit this code by changing '\n' as your character, and after you get that character, you should start to save following data to inside the buffer.

Difference in timing while getting values from ROM or RAM

So I am having a hard time understanding the time it takes to get values from ram or rom in vhdl. To insert data into ram I know happens on the rising edge of the clock and takes one clock such as the example I have, but in terms of getting data out does it take one clock to get the data from memory and then get then another clock cycle to get the data to output meaning it takes 2 clock cycles to get data?
process(clk)
begin
if(rising_edge(clk)) then
if(write_en = '1') then
mem(to_integer(unsigned(address))) <= incoming_data;--insert data
end if;
end if;
end process;
out_data <= mem(to_integer(unsigned(address))); -- takes 2 clock cycles to get data ?
No, it takes 1 clock cycle:
In your code you have two concurrent processes. One is explicit:
process(clk)
begin
if(rising_edge(clk)) then
if(write_en = '1') then
mem(to_integer(unsigned(address))) <= incoming_data;--insert data
end if;
end if;
end process;
The other is implicit; it is a concurrent signal assignment:
out_data <= mem(to_integer(unsigned(address))); -- takes 2 clock cycles to get data ?
The concurrent signal assignment is exactly equivalent to this:
process(address, mem)
begin
out_data <= mem(to_integer(unsigned(address))); -- takes 2 clock cycles to get data ?
end process;
In other words, it is equivalent to a process with address and mem in the sensitivity list. Any concurrent signal assignment is equivalent to a process with all the inputs in the sensitivity list. An input to a concurrent signal assignment is any signal on the right hand side of the signal assignment operator (<=). So, you get a sensitivity list for free and that is an advantage of using concurrent signal assignments: you cannot accidentally miss out a signal from the sensitivity list, because the compiler creates it for you.
So, lets consider what happens when each process is executed. The first process has just the signal clk in its sensitivity list, so the process executes whenever there is a change (an event) on clk. If this change is not a rising edge then the rising_edge function returns FALSE and the process immediately suspends. If this change is a rising edge then the rising_edge function returns TRUE and if the expression write_en = '1' is also TRUE then this line gets executed:
mem(to_integer(unsigned(address))) <= incoming_data;--insert data
The effect of this line is to put an event on the event queue to drive the correct value of mem on the next delta cycle (assuming there is some change to the signal mem as a result). The event queue is the simulator's "to do" list; a delta cycle is one iteration of the simulator; the next iteration will occur once all the processes that are executing in the current iteration suspend.
So, the next iteration cycle occurs and the signal mem gets its new value. The signal mem is in the implicit sensitivity list of the second (implicit) process (the concurrent signal assignment). So, this second process starts executing and the line with the signal assignment to out_data is executed and (as with the executing of any line containing a signal assignment) an event is put on the event queue to drive the target signal - out_data in this case - to a new value (again assuming the value should change).
So, the change to the signal out_data always occurs one delta cycle after a change on the signal mem. We've already established that the signal mem changes one delta cycle after any rising edge on the signal clk, so we can see that the signal out_data changes two delta cycles after any rising edge on the signal clk.
Whilst it is vital to be aware of delta cycles when writing VHDL, we don't usually need to worry about them if we adopt a good, conventional style. So, we can just say that the signal out_data changes on any rising edge of the signal clk or, in other words, there is a delay of one clock cycle between any changes on the signals write_en, incoming_data or address and any corresponding change on the signal out_data.

How to declare a global variable in Verilog?

I am writing to ask how to declare a global variable in Verilog. What declared by parameter and define keywords are essentially constants, not variables.
What I need is the following:
`define Glitch
module Cell ( Shift_In, Shift_Out_Screwed, Clk );
input Clk, Shift_In;
output Shift_Out_Screwed;
wire Shift_Out_Screwed;
wire Shift_Out;
Inverter INV1 ( Shift_In, Shift_Out, Clk );
assign Shift_Out_Screwed = Glitch ? ~Shift_Out : Shift_Out
endmodule
This is a very simple glitch insertion. When Glitch==1, the original output is reversed; when Glitch==0, the original output is kept unchanged. I want the signal Glitch to be defined in an external simulation testbench.v file although it is declared and used here, and I don't want to add the signal Glitch to the input port list of the module cell. This is because that my real circuit is a very complicated one, and if I add an input port to a certain cell, there will be many other cells affected.
Does anyone know how to declare a global variable in Verilog?
The problem you are wrestling with sounds like error injection. You want the ability to inject a bit error on an output port from within a testbench. You can do it like this:
module Cell ( Shift_In, Shift_Out_Screwed, Clk );
input Clk, Shift_In;
output Shift_Out_Screwed;
wire Shift_Out_Screwed;
wire Shift_Out;
Inverter INV1 ( Shift_In, Shift_Out, Clk );
`ifdef SIMULATION
// This logic is used in simulation, but not synthesis. Use care.
logic Glitch = 1'b0;
assign Shift_Out_Screwed = Glitch ? ~Shift_Out : Shift_Out
`else
// This logic is used in synthesis, but not simulation. Use care.
assign Shift_out_Screwed = Shift_out;
`endif
endmodule
Note that I use the "SIMULATION" preprocessor switch to hide the "Glitch" error injection from synthesis. Use this technique with care to avoid creating simulation/synthesis mismatches.
In your testbench, you can induce a glitch in a specific instance of your cell by referencing the "Glitch" signal in the design hierarchy, like this:
initial begin
...
#(posedge Clk); #1;
$top.u_foo.u_bar.u_cell.Glitch = 1'b1;
#(posedge Clk); #1;
$top.u_foo.u_bar.u_cell.Glitch = 1'b1;
...
end
The above code snippet will inject one cycle of "Glitch".
As an alternative: a more traditional way of injecting errors is to use the "force" statement in the testbench to override a driven in a device under test.

Output skew when using clocking blocks

I am using a clocking block in my interface for signal aliasing. I want to concatenate some of the bits together to form a bus, and then drive this bus from my driver. So, for example:
interface bus_intf (clk);
input logic clk;
logic[1:0] x_lsb;
logic[1:0] x_msb;
clocking driver_bus #(posedge clk)
default input #1step output #0;
output x_bus = {x_msb, x_lsb};
endclocking
endinterface
Now the problem with this is, in one of my assertions, I need to read bus_intf.driver_bus.x_bus. As stated in the SV manual, an output variable from a clocking block should not be read by the testbench, and if it is, then simulator spits out an error (or warning in my case).
So I modified the interface:
interface bus_intf (clk);
input logic clk;
logic[1:0] x_lsb;
logic[1:0] x_msb;
clocking driver_bus #(posedge clk)
default input #1step output #0;
inout x_bus = {x_msb, x_lsb};
endclocking
endinterface
The problem now is, in my waveform I see two signals being created - x_bus and x_bus__o. I understand why Questasim did this - it is to separate the inout declaration so I can view both versions.
However, the problem now is all my clocking drive is delayed by one clock cycle! so x_bus__o which is connected to the DUT is one clock cycle later than x_bus. This is inspite of me explicitly stating that output skew is #0.
Any idea why this happens? Am I doing something wrong or have I misunderstood?
I've put your code on EDAPlayground and tried it out. It seems to be working as expected. Here's my test harness:
module top;
bit clk;
always #1 clk = ~clk;
bus_intf busif(clk);
initial begin
#busif.driver_bus;
$display("time = ", $time);
busif.driver_bus.x_bus <= 'hf;
repeat (2)
#(negedge clk);
$display("time = ", $time);
busif.driver_bus.x_bus <= 'ha;
#100;
$finish();
end
always #(busif.x_lsb)
$display("time = ", $time, " x_lsb = ", busif.x_lsb);
always #(busif.x_msb)
$display("time = ", $time, " x_msb = ", busif.x_msb);
endmodule
The link is here if you want to try it online: http://www.edaplayground.com/x/Utf
If I drive x_bus at a posedge, then the value will be written immediately, as would be expected due to the #0 output delay. If I drive x_bus at a negedge (or at any other time aside from a posedge), then it will wait until the next posedge to drive the value. I see this behavior regardless of whether x_bus is declared as output or inout.
Check to see when you are scheduling your writes; this might be the reason you see some delays on your waves.
When you have bidirectional flow through a clocking block, the signal from the verification to the hardware and back has to go through two virtual D-FFs. So the original observation is correct. The input of 1-step is one D-FF to the design; then the return is one more D-FF back appearing 0ns (i.e., just after the clock). Clocking blocks are not useful in the situation of a signal that requires a single-cycle turn-around, and for that reason, you avoid them if that is a requirement. For most designs, it is simply not necessary. Monitors will observe the signals with a pipeline delay of one cycle, which is generally not a problem.