I got a problem.
I am a Verilog newbie, and I have to write a counter based memory array. Basically, my array is 16 x 8 bits (16 x 1 byte). I have 8 bit data coming into my memory, 16 times. So I made a memory block, and a counter which supplies addresses to this memory block by incrementing with the positive edge of the clock (actually, on each positive edge, 8 bit data is fed into the memory, so I increment my counter). Now I have done this process 16 times, and now 128 bits of data are stored and provided by my memory block. But now I want to reset my counter, and repeat the whole process again after a small delay. I am confused as to how I do this. Please have a look at my code and advise.
Thanking all of you in advance.
// creation of counter & a dummy variable
wire cnt;
wire cnt_next;
reg [3:0] counter;
always #(posedge clock)
assign cnt_next=cnt+1'b1;
counter <= cnt_next
wire [3:0] write_address = counter;
//creation of ram function
module single_port_ram
(
input [7:0] data,
input [3:0] addr,
input wr, clk, rd
output [127:0] q
);
reg [15:0] ram[0:7];
always # (posedge clk or posedge reset)
begin
// Code for writing the data
if (wr)
{
addr <= write_address
case {addr}
4'b0000: ram[0] <= data
4'b0001: ram[1] <= data
4'b0010: ram[2] <= data
4'b0011: ram[3] <= data
4'b0100: ram[4] <= data
4'b0101: ram[5] <= data
4'b0110: ram[6] <= data
4'b0111: ram[7] <= data
4'b1000: ram[8] <= data
4'b1001: ram[8] <= data
4'b1010: ram[10] <= data
4'b1011: ram[11] <= data
4'b1100: ram[12] <= data
4'b1101: ram[13] <= data
4'b1110: ram[14] <= data
4'b1111: ram[15] <= data
end
always # (posedge clk or posedge reset)
begin
//Code for reading the data
if (rd)
{
q <= {ram[15],ram[14],ram[13],ram[12],ram[11],ram[10],ram[9],ram[8],ram[7],ram[6],ram[5],ram[4],ram [3],ram[2],ram[1],ram[0]}
}
Make your counter a little bigger, say up to 31 instead of 15. For the first 16 clocks, write the memory address like you are doing, for the next 16 clocks just do nothing but increment (the small delay you wanted), and then when the counter reaches 31 just reset it back to 0. Then the process should restart.
to have 16 x 8 bits (16 x 1 byte)
first you declare the size of your RAM width then you declare the actual depth of your RAM for example if i want an array of 512 reg variables (depth) and each is 8 bits (width) then it will be written like:
reg [7:0] ram[511:0];
so your code should look like:
reg [7:0] ram[15:0];
Related
please I have a problem with writing a code which will read a CAN message, edit it (limit to some maximum value) and then send back with same ID.
I´m using PCAN-Router Pro FD and will show you their example of such thing - basically same as mine but I have no idea what some of the numbers or operations are. [1]: https://i.stack.imgur.com/6ZDHn.jpg
My task is to: 1) Read CAN message with these parameters (ID = 0x120h, startbit 8, length 8 bit and factor 0,75)
2) Limit this value to 100 (because the message should have info about coolant temperature.)
3) If the value was below 100, dont change anything. If it was higher, change it to 100.
Thanks for any help !
Original code:
// catch ID 180h and limit a signal to a maximum
else if ( RxMsg.id == 0x180 && RxMsg.msgtype == CAN_MSGTYPE_STANDARD)
{
uint32_t speed;
// get the signal (intel format)
speed = ( RxMsg.data32[0] >> 12) & 0x1FFF;
// limit value
if ( speed > 6200)
{ speed = 6200;}
// replace the original value
RxMsg.data32[0] &= ~( 0x1FFF << 12);
RxMsg.data32[0] |= speed << 12;
}
After consulting the matter in person, we have found the answer.
The structure type of the RxMsg contains a union allowing the data to be accessed in 4-Byte chunks RxMsg.data32, 2-Byte chunks RxMsg.data16, or 1-Byte chunks RxMsg.data8. Since the temperature is located at the 8th bit and it is 1 Byte long, it can be accessed without using the binary masks, bit shifts and bitwise-logical-assignment operators at all.
// more if-else statements...
else if (RxMsg.id == 0x120 && RxMsg.msgtype == CAN_MSGTYPE_STANDARD)
{
uint8_t temperature = RxMsg.data8[1];
float factor = 0.75;
if (temperature * factor > 100.0)
{
temperature = (int)(100 / factor);
}
RxMsg.data8[1] = temperature;
}
The answer assumes that the startbit is the most significant bit in the message buffer and that the temperature value must be scaled down by the mentioned factor. Should the startbit mean the least significant bit, the [1] index could just be swapped out for [62], as the message buffer contains 64 Bytes in total.
The question author was not provided with a reference sheet for data format, so the answer is based purely on the information mentioned in the question. The temperature scaling factor is yet to be tested (will edit this after confirming it works).
I have an application where I'm continuously writing to a block ram at a slow clock speed (clk_a) and within this slow clock cycle need to read three indexes from the block ram at a fast clock speed (clk_b) to use these values as operands in a math module, the result being written back to the block ram on the next slow clock. These three indexes are the current address written to at posedge of the slow clock, plus the two immediate neighbouring addresses (addr_a -1 and addr_a +1).
What is an efficient way to synthesize this? My best attempt to date uses a small counter (triplet) running at fast clock rate that increments the addresses but I end up running out of logic as it looks like Yosys does not infer the ram properly. What is a good strategy for this?
here is what I have:
module myRam2 (
input clk_a,
input clk_b,
input we_a,
input re_a,
input [10:0] addr_a,
input [10:0] addr_b,
input [11:0] din_a,
output [11:0] leftNeighbor,
output [11:0] currentX,
output [11:0] rightNeighbor
);
parameter MEM_INIT_FILE2 = "";
initial
if (MEM_INIT_FILE2 != "")
$readmemh(MEM_INIT_FILE2, ram2);
reg [11:0] ram2 [0:2047];
reg [1:0] triplet = 3;
reg [10:0] old_addr_a;
reg [11:0] temp;
always #(posedge clk_a) begin
ram2[addr_a] <= din_a;
end
always#(posedge clk_b)
if (old_addr_a != addr_a) begin
triplet <= 0;
old_addr_a <= addr_a;
end
else
if(triplet < 3) begin
triplet <= triplet +1;
end
always #(posedge clk_b) begin
temp <= ram2[addr_a + (triplet - 1)];
end
always #(posedge clk_b) begin
case(triplet)
0: leftN <= temp;
1: X <= temp;
2: rightN <= temp;
endcase
end
reg signed [11:0] leftN;
reg signed [11:0] X;
reg signed [11:0] rightN;
assign leftNeighbor = leftN;
assign currentX = X;
assign rightNeighbor = rightN;
endmodule
Regarding the efficiency the following approach should work and removes the need for a faster clock:
module myRam2 (
input wire clk,
input wire we,
input wire re,
input wire [10:0] addr_a,
input wire [10:0] addr_b,
input wire [11:0] din_a,
output reg [11:0] leftNeighbor,
output reg [11:0] currentX,
output reg [11:0] rightNeighbor
);
reg [11:0] ram2 [2047:0];/* synthesis syn_ramstyle = "no_rw_check" */;
always #(posedge clk) begin
if(we) ram2[addr_a] <= din_a;
if(re) {leftNeighbor,currentX,rightNeighbor} <= {ram2[addr_b-1],ram2[addr_b],ram2[addr_b+1]};
end
endmodule
The synthesis keyword helped me in the past to increase the likelyhood of correctly inferred ram.
EDIT: removed second example suggesting a 1D mapping. It turned out that at least Lattice LSE cannot deal with that approach. However the first code snipped should work according to Active-HDL and Lattice LSE.
I have a fixed point Matlab code and it needs to be converted to Verilog. Below is the Matlab code. yfftshift is 5000x0 and y2shape 100x50.
rows=100;
colms=50;
r=1;
for m=0:colms-1
for n=0:rows-1
y2shape(n+1,m+1)=yfftshift(r,1);
r=r+1;
end
end
How can I create memories in Verilog and call them inside the for loop?
The easiest way to handle fixed precision in Verilog is to introduce a scale factor and allocate sufficiently large registers to hold the maximum value. For example, if you know that the maximum value of your numbers will be 40, and three digits of precision to the right of the decimal place are OK, a scaling factor of 1000 can be used with 16-bit registers. Verilog treats unsigned numbers, so if values can be negative, it's necessary to add "signed" to the declarations. The Verilog could be:
`define NUMBER_ROWS 100
`define NUMBER_COLS 50
`define MAX_ROW (`NUMBER_ROWS-1)
`define MAX_COL (`NUMBER_COLS-1)
module moveMemory();
reg clk;
reg [15:0] y2shape [`MAX_ROW:0][`MAX_COL:0];
reg [15:0] yfftshift [`NUMBER_ROWS * `NUMBER_COLS:0];
integer rowNumber, colNumber;
always #(posedge clk)
begin
for (rowNumber = 0; rowNumber < `NUMBER_ROWS; rowNumber = rowNumber + 1)
for (colNumber = 0; colNumber < `NUMBER_COLS; colNumber = colNumber + 1)
y2shape[rowNumber][colNumber] <= yfftshift[rowNumber * `NUMBER_COLS + colNumber];
end
endmodule
This is OK for an FPGA or simulation project, but for full custom work, an SRAM macro would be used to avoid the die area associated with 16,000 registers. For an FPGA implementation, you've probably already paid for the 16K registers, or you may be able to do some extra work get the synthesizer to map the registers to an on-chip SRAM.
The test bench:
// Testing code
integer loadCount, rowShowNumber, colShowNumber;
initial
begin
// Initialize array with some data
for (loadCount=0; loadCount < (NUMBER_ROWS *NUMBER_COLS); loadCount = loadCount + 1)
yfftshift[loadCount] <= loadCount;
clk <= 0;
// Clock the block
#1
clk <= 1;
// Display the results
#1
$display("Y2SHAPE has these values at time ", $time);
for (rowShowNumber = 0; rowShowNumber < `NUMBER_ROWS; rowShowNumber = rowShowNumber + 1)
for (colShowNumber = 0; colShowNumber < `NUMBER_COLS; colShowNumber = colShowNumber + 1)
$display("y2shape[%0d][%0d] is %d ", rowShowNumber, colShowNumber, y2shape[rowShowNumber][colShowNumber]);
end
The simulation results for NUMBER_ROWS=10, NUMBER_COLS=5
Y2SHAPE has these values at time 2
y2shape[0][0] is 0
y2shape[0][1] is 1
y2shape[0][2] is 2
y2shape[0][3] is 3
y2shape[0][4] is 4
.
.
.
y2shape[9][2] is 47
y2shape[9][3] is 48
y2shape[9][4] is 49
I have an ADC interrupt that I'd like to sample the channel (ADCBUF0) 8 times, then take the average of the samples. My code utilizes flags to jump out of the if statement. The code compiles and my variables are initialized elsewhere. Could someone please tell me why I am not receiving a value for SpeedADC???
///////Global////////////
int SpeedADCcount=0;
/////////////////////////
SpeedADCflag=1;
if(SpeedADCflag==1) //The following is meant to take a an average of the incoming ADC voltages
{
SpeedADCcount++;
for(i = SpeedADCcount; i < 16; i++)
{
while(!ADCON1bits.SAMP); //Sample Done?
ADCON1bits.SAMP=0; //Start Converting
while(!ADCON1bits.DONE); //Conversion Done? Should be on next Tcy cycle
SpeedADCarray[i] = ADCBUF0;
SpeedADCflag=0;
}
}
if(SpeedADCcount==15)
{
SpeedADC=SpeedADCarray[i]>>4;
SpeedADCcount=0;
// Re-enable the motor if it was turned off previous
if((SpeedADC>246) && Flags.RunMotor==0){RunMotor();}
/*Go through another stage of "filtering" for any analog input voltage below 1.25volts
You need to get the right downshift amount (to avoid dividing), such that 8 -> 3, 16 -> 4, etc. For 8 samples, you only need to downshift 3 (3 bits).
And you need to sum all of the values in a single value, not put them in separate array entries.
SpeedADCarray += ADCBUF0; /* accumulate in a single integer, not an array */
I am maintaining a Production code related to FPGA device .Earlier resisters on FPGA are of 32 bits and read/write to these registers are working fine.But Hardware is changed and so did the FPGA device and with latest version of FPGA device we have trouble in read and write to FPGA register .After some R&D we came to know FPGA registers are no longer 32 bit ,it is now 31 bit registers and same has been claimed by FPGA device vendor.
So there is need to change small code as well.Earlier we were checking that address of registers are 4 byte aligned or not(because registers are of 32 bits)now with current scenario we have to check address are 31 bit aligned.So for the same we are going to check
if the most significant bit of the address is set (which means it is not a valid 31 bit).
I guess we are ok here.
Now second scenario is bit tricky for me.
if read/write for multiple registers that is going to go over the 0x7fff-fffc (which is the maximum address in 31 bit scheme) boundary, then have to handle request carefully.
Reading and Writing for multiple register takes length as an argument which is nothing but number of register to be read or write.
For example, if the read starts with 0x7fff-fff8, and length for the read is 5. Then actually, we can only read 2 registers (which is 0x7fff-fff8, and 0x7fff-fffc).
Now could somebody suggest me some kind of pseudo code to handle this scenario
Some think like below
while(lenght>1)
{
if(!(address<<(lenght*31) <= 0x7fff-fffc))
{
length--;
}
}
I know it is not good enough but something in same line which I can use.
EDIT
I have come up with a piece of code which may fulfill my requirement
int count;
Index_addr=addr;
while(Index_add <= 7ffffffc)
{
/*Wanted to move register address to next register address,each register is 31 bit wide and are at consecutive location. like 0x0,0x4 and 0x8 etc.*/
Index_add=addr<<1; // Guess I am doing wrong here ,would anyone correct it.
count++;
}
length=count;
The root problem seems to be that the program is not properly treating the FPGA registers.
Data encapsulation would help, and, instead of treating the 31-bit FPGA registers as memory locations, they should be abstracted.
The FPGA should be treated as a vector (a one-dimensional array) of registers.
The vector of N FPGA registers should be addressable by an register index in the range of 0x0000 through N-1.
The FPGA registers are memory mapped at base addr.
So the memory address = 4 * FPGA register index + base addr.
Access to the FPGA registers should be encapsulated by read and write procedures:
int read_fpga_reg(int reg_index, uint32_t *reg_valp)
{
if (reg_index < 0 || reg_index >= MAX_REG_INDEX)
return -1; /* error return */
*reg_valp = *(uint32_t *)(reg_index << 2 + fpga_base_addr);
return 0;
}
As long as MAX_REG_INDEX and fpga_base_addr are properly defined, then this code will never generate an invalid memory access.
I'm not absolutely sure I'm interpreting the given scenario correctly. But here's a shot at it:
// Assuming "address" starts 4-byte aligned and is just defined as an integer
unsigned uint32_t address; // (Assuming 32-bit unsigned longs)
while ( length > 0 ) // length is in bytes
{
// READ 4-byte value at "address"
// Mask the read value with 0x7FFFFFFF since there are 31 valid bits
// 32 bits (4 bytes) have been read
if ( (--length > 0) && (address < 0x7ffffffc) )
address += 4;
}