I have a file data.txt that has 1200 lines, each representing a 16 bit binary string such as the following.
"0001111111000000"
I'm trying to write a testbench using Icarus Verilog that reads in each line of the file and sends each line to a .v file that will run some simple if statements on each line of the file (a simple classification algorithm).
My code is below.
// Verilog test bench for generate.v
`timescale 1ns/100ps
`include "generate.v"
module generate_tb;
$display('running test bench')
integer data_file ; // file handler
integer scan_file ; // file handler
logic signed [21:0] captured_data;
`define NULL 0
initial begin
$dumpfile("generate.vcd");
$dumpvars(0, generate_tb);
data_file = $fopen("./data.txt", "r");
if (data_file == `NULL) begin
$display("data_file handle was NULL");
$finish;
end
end
always #(posedge clk) begin
scan_file = $fscanf(data_file, "%b\n", captured_data);
if (!$feof(data_file)) begin
generate the_circuit(output, captured_data); // HERE
end
end
$finish;
endmodule
and my generate.v file:
module generate(actual_class, data_row);
output actual_class;
input data_row;
wire stby_flag ;
wire [0:15] vect;
reg [0:1] classe;
assign vect = data_row;
always #(posedge clk) begin
if (vect[3] == 0) begin
classe = 2'b10;
end
if (vect[11] == 0) begin
classe = 2'b01;
end
if (vect[8] == 1 && vect[4] + vect[5] + vect[6] + vect[7] >= 3) begin
classe = 2'b00;
end
if (vect[0] + vect[1] + vect[2] + vect[3] + vect[4] + vect[5] + vect[6] + vect[7] + vect[8] + vect[9] + vect[10] + vect[11] + vect[12] + vect[13] + vect[14] + vect[15] <= 1) begin
classe = 2'b11;
end
end
assign actual_class = classe;
endmodule
I am stuck on this part of the code. I'm not sure how I can call the generate.v file for each line of the file.
if (!$feof(data_file)) begin
generate the_circuit(output, captured_data); // HERE
end
A better way to do this would be to save my data into and use $readmemb but I'm hoping to do it this way.
Any advice is much appreciated.
To start off: it is a very bad idea to name your module after a reserved word 'generate'.
I'm not sure how I can call the generate.v
It is a module, not a function. You can not 'call' a module.
You read each line from the file and assign it to a input variable of the module. Make sure you wait long enough before reading the next line for your module (and all subsequent triggered modules) to finish processing the input. You can wait a number of clock cycles or use a 'ready' signal.
A better way to do this would be..
Maybe. If your pattern gets very big you need a big memory.
Related
Problem: I'm synthesizing my code, which reads 1200 16 bit binary vectors, analyzes them and sets a 2 bit register named classe depending on the behavior of 4 if statements. The problem seems to be that classe is stuck on the last if statement - where classe is set to bit 11, or 3.
My code worked fine in when I was using a testbench.
I'm thinking it is stuck because somehow the always block is reading all 1200 vectors at once, as seen in the simulation, instead of one every clock edge?
I've attached a simulation screenshot here: https://imgur.com/a/No2E9cq
module final_final_code
(
output reg [ 0:1] classe
);
reg [0:15] memory [0:1199];
reg[0:15] vect:
integer i;
//// Internal Oscillator
defparam OSCH_inst.NOM_FREQ = "2.08";
OSCH OSCH_inst
(
.STDBY(1'b0), // 0=Enabled, 1=Disabled also Disabled with Bandgap=OFF
.OSC(osc_clk),
.SEDSTDBY() // this signal is not required if not using SED
);
initial begin
$readmemb("C:/Users/KP/Desktop/data.txt", memory, 0, 1199);
i = 0;
end
always #(posedge osc_clk) begin
vect = memory[i];
if ((memory[i][3] == 1'b0)) begin
classe = 2'b10;
end
if ((memory[i][11] == 1'b0)) begin
classe = 2'b01;
end
if ((memory[i][8] == 1'b1 && memory[i][4] + memory[i][5] + memory[i][6] + memory[i][7] >= 4'b0100)) begin
classe = 2'b00;
end
if ((memory[i][0] + memory[i][1] + memory[i][2] + memory[i][3] + memory[i][4] + memory[i][5] + memory[i][6] + memory[i][7] + memory[i][8] + memory[i][9] + memory[i][10] + memory[i][11] + memory[i][12] + memory[i][13] + memory[i][14] + memory[i][15] <= 1'b1)) begin
classe = 2'b11;
end
i = i + 1'd1;
if (i == 4'd1199) begin
i = 0;
end
end
endmodule
Apart from what john_log says:
Your last if statement is always TRUE. You are adding 1-bit operands and comparing against a 1-bit result thus the results is 1'b1 or 1'b0 which is always <= 1'b1.
You should check if your FPGA tool supports this:
initial begin
$readmemb("C:/Users/KP/Desktop/data.txt", memory, 0, 1199);
i = 0;
end
Especially the loading of a memory from a file by the synthesis tool. It was not possible the last time I used an FPGA.
Having a bit of trouble with looping through a 1D reg array.
ultimately I am trying to accomplish the following.
in "Listen" state, the rx_values fill a read buffer (4 8-bit characters) to store the characters being typed in a console and echo back the character by setting tx_data to the last character (this works)
when the enter key is hit, the state switches to "Read" which sets the tx_data to the readbuffer with each iteration until the 4th character is reached at which time the state is reset to idle. (this doesnt work)
I get to the read state;however,the counter does not work as expected.
any help would be greatly appreciated.
module receiver (
input clk,
input rst,
output reg [7:0] tx_data,
output reg new_tx_data,
input tx_busy,
input [7:0] rx_data,
input new_rx_data
);
localparam idle = 4'h0 ,listen = 4'h1 ,read = 4'h2, write = 4'h3;
reg [3:0] state = idle;
reg [7:0] readbuff[3:0];
integer buffdex;
always #* begin
end
always #(posedge clk) begin
new_tx_data = 1'b0;
case (state)
idle: begin
if(new_rx_data) begin
state<=listen;
end
end
listen: begin
new_tx_data = 1'b1;
readbuff[buffdex] = rx_data;
tx_data = readbuff[buffdex];
//tx_data = buffdex;
buffdex = buffdex + 1';
if(rx_data == 8'h0D) begin
tx_data = "\n";
buffdex = 0;
state <= read;
end else begin
state<=idle;
end
end
read: begin
new_tx_data = 1'b1;
tx_data = readbuff[buffdex];
buffdex = buffdex + 1;
if (buffdex == 3) begin
state <= idle;
end
//tx_data = state;
end
endcase
end
endmodule
Sorry to use "answer" feature instead of comment but I don't have enough points yet. This is intended as a "comment". Since you wanted any help I hope this fits.
1) Your code needs some improvement both in functionality and readability (empty combo blocks, mixing BA with NBA -> mixing combo with sequential logic, reset input but no reset logic, commented logic lines, latches on FSM).
Consider rewriting it according to some good coding practices, e.g. http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf
You also have inconsistencies like buffdex = buffdex + 1' and buffdex = buffdex + 1. (And thus doesn't compile on incisive).
2) Can you provide a testbench for this module? Have you tried strobing signals to check their values? Does buffdex increment in read state? Is the if statement reachable?
3) Since this isn't a 1st problem with Mojo (seems like under developement) you may consider free https://www.edaplayground.com/ for both testing and compiling/syntax checking.
So I read the paper (along with other various IEEE instructions) and finally got a working version. below is the code. as before I am open the suggestions as to how the code can be made more efficient or functional. I think the read buffer is one big latch, but not sure how to fix it.
module receiver (
//inputs
input clk,
input rst,
input tx_busy,
input [7:0] rx_data,
input new_rx_data,
//outputs
output reg [7:0] tx_data,
output reg new_tx_data,
output reg [0:4] LED
);
//local parameters
localparam IDLE = 2'b00 , LISTEN = 2'b01 ,NEWLINE = 2'b10, READ = 2'b11;
//fsm state reg and readbuff reg
reg [1:0] stated, stateq;
reg [3:0] cntrd,cntrq;
reg [7:0] readbuff [15:0];
reg nl;
//on clock edge set flip-flop - non-blocking assignments
always #(posedge clk ) begin
if(rst) begin
stateq <= IDLE;
cntrq<=4'b0000;
end else begin
//update the state and readbuff index values to be current.
stateq <= stated;
cntrq <=cntrd;
end
end
//sequential and combinational blocking assignments
always #(*) begin
//set default states to avoid latches.
stated = stateq;
cntrd = cntrq;
LED = cntrq;
//set output defaults
tx_data = 8'hxx;
new_tx_data = 1'b0;
case (stateq)
IDLE: begin
//move to listen state
cntrd=4'b0;
stated = stateq + 1'b1;
end
LISTEN: begin
if(new_rx_data) begin
//set readbuffer[indx] to the rx data
readbuff[cntrq] = rx_data;
new_tx_data = 1'b1;
tx_data = readbuff[cntrq];
cntrd = cntrq + 1'b1;
//if enter is pressed change states, otherwise, echo and increase the read buffer.
if(rx_data == "\r" || rx_data == "\n") begin
stated = stateq + 1'b1;
cntrd=4'b0000;
end
end
end
NEWLINE: begin
if(!tx_busy) begin
new_tx_data = 1'b1;
tx_data = 8'h0A;
nl = 1'b1;
stated = stateq + 1'b1;
end
end
READ: begin
//check the value of cntrq for the enter statement
if(readbuff[cntrq] == "\r" || readbuff[cntrq] == "\n" ) begin
stated = IDLE;
//otherwise write out the value of the readbuff - tx busy should sync to avr clock
end else begin
if (!tx_busy) begin
new_tx_data = 1'b1;
tx_data = readbuff[cntrq];
cntrd = cntrq + 1'b1;
end
end
end
endcase
end
endmodule
I'm doing a LOTTT of pipelining with varying width signals and wanted a SYNTHESIZEABLE module wherein i could pass 2 parameters : 1) number of pipes (L) and 2) width of signal (W).
That way i just have to instantiate the module and pass 2 values which is so much simple and robust than typing loads and loads of signal propagation via dummy registers...prone to errors and et all.
I have HALF written the verilog code , kindly request you to correct me if i am wrong.
I AM FACING COMPILE ERROR ... SEE COMMENTS
*****************************************************************
PARTIAL VERILOG CODE FOR SERIAL IN SERIAL OUT SHIFT REGISTER WITH
1) Varying number of shifts / stages : L
2) Varying number of signal / register width : W
*****************************************************************
module SISO (clk, rst, Serial_in, Serial_out); // sIn -> [0|1|2|3|...|L-1] -> sOut
parameter L = 60; // Number of stages
parameter W = 60; // Width of Serial_in / Serial_out
input clk,rst;
input reg Serial_in;
output reg Serial_out;
// reg [L-1:0][W-1:0] R;
reg [L-1:0] R; // Declare a register which is L bit long
always #(posedge clk or posedge rst)
begin
if (rst) // Reset = active high
//**********************
begin
R[0] <= 'b0; // Exceptional case : feeding input to pipe
Serial_out <= 'b0; // Exceptional case : vomiting output from pipe
genvar j;
for(j = 1; j<= L; j=j+1) // Ensuring ALL registers are reset when rst = 1
begin : rst_regs // Block name = reset_the_registers
R[L] <= 'b0; // Verilog automatically assumes destination width # just using 'b0
end
end
else
//**********************
begin
generate
genvar i;
for(i = 1; i< L; i=i+1)
begin : declare_reg
R[0] <= Serial_in; // <---- COMPILE ERROR POINTED HERE
R[L] <= R[L-1];
Serial_out <= R[L-1];
end
endgenerate;
end
//**********************
endmodule
//**********************
Why so complicated? The following code would be much simpler and easier to understand:
module SISO #(
parameter L = 60, // Number of stages (1 = this is a simple FF)
parameter W = 60 // Width of Serial_in / Serial_out
) (
input clk, rst,
input [W-1:0] Serial_in,
output [W-1:0] Serial_out
);
reg [L*W-1:0] shreg;
always #(posedge clk) begin
if (rst)
shreg <= 0;
else
shreg <= {shreg, Serial_in};
end
assign Serial_out = shreg[L*W-1:(L-1)*W];
endmodule
However, looking at your code there are the following problems:
You declare Serial_in as input reg. This is not possible, an input cannot be a reg.
You are using generate..endgenerate within an always block. A generate block is a module item and cannot be used in an always block. Simply remove the generate and endgenerate statements and declare i as integer.
Obviously Serial_in and Serial_out must be declared as vectors of size [W-1:0].
You are using R as a memory. Declare it as such: reg [W-1:0] R [0:L-1].
You are not using i in you for loop. Obviously you meant to chain all the elements of R together, but you are just accessing the 0th, (L-1)th and Lth element. (Obviously the Lth element is nonexisting, this array would be going from 0 to L-1.
I'm now stopping writing this list because, I'm sorry, I think there really is not much to gain by improving the code you have posted..
I'm tring to write universal fifo buffer.
To make it universal i used code like this.
genvar i;
generate
for(i=0;i<BusWidthIn;i=i+1) begin: i_buffin
always # (negedge clkin) begin
if (!full)
Buffer[wr_ptr+i] <= datain[i*BitPerWord+BitPerWord-1:i*BitPerWord];
end
end
endgenerate
In simulation it works properly, but in Quartus it gives
Error (10028): Can't resolve multiple constant drivers for net "Buffer[30][6]" at fifo.v(33) and so on.
All Code
module fifo_m(clkin,datain,clkout,dataout,full,empty);
parameter BusWidthIn = 3, //in 10*bits
BusWidthOut = 1, //in 10*bits
BufferLen = 4, // in power of 2 , e.g. 4 will be 2^4=16 bytes
BitPerWord = 10;
input clkin;
input [BusWidthIn*BitPerWord-1:0] datain;
input clkout;
output [BusWidthOut*BitPerWord-1:0] dataout;
output full;
output empty;
reg [BusWidthOut*BitPerWord-1:0] dataout;
reg [BitPerWord-1:0] Buffer [(1 << BufferLen)-1 : 0];
wire [BusWidthIn*BitPerWord-1:0] tbuff;
reg [BufferLen - 1 : 0] rd_ptr, wr_ptr;
wire [BufferLen - 1 : 0] cnt_buff;
wire full;
wire empty;
assign cnt_buff = wr_ptr > rd_ptr ? wr_ptr - rd_ptr : (1 << BufferLen) - rd_ptr + wr_ptr;
assign full = cnt_buff > (1 << BufferLen) - BusWidthIn;
assign empty = cnt_buff < BusWidthOut;
initial begin
rd_ptr = 0;
wr_ptr = 0;
end
genvar i;
generate
for(i=0;i<BusWidthIn;i=i+1) begin: i_buffin
always # (negedge clkin) begin
if (!full)
Buffer[wr_ptr+i] <= datain[i*BitPerWord+BitPerWord-1:i*BitPerWord];
end
end
endgenerate
always # (negedge clkin)
begin
if (!full)
wr_ptr = wr_ptr + BusWidthIn;
end
genvar j;
generate
for(j=0;j<BusWidthOut;j=j+1) begin : i_buffout
always # (posedge clkout) begin
dataout[j*BitPerWord+BitPerWord-1:j*BitPerWord] <= Buffer[rd_ptr+j];
end
end
endgenerate
always # (posedge clkout)
begin
if (!empty)
rd_ptr = rd_ptr + BusWidthOut;
end
endmodule
To solve this problem I must put for inside always, but how I can do it?
I think the issue is that synthesis doesn't know that wr_ptr is always a multiple of 3, hence from the synthesis point of view 3 different always blocks can assign to each Buffer entry. I think you can recode your logic to assign just a single Buffer entry per always block.
genvar i, j;
generate
for(i=0;i < (1<<(BufferLen)); i=i+1) begin: i_buffin
for(j = (i%BusWidthIn);j == (i%BusWidthIn); j++) begin // a long way to write 'j = (i%BusWidthIn);'
always # (negedge clkin) begin
if (!full) begin
if (wr_ptr*BusWidthIn + j == i) begin
Buffer[i] <= datain[j*BitPerWord+BitPerWord-1:j*BitPerWord];
end
end
end
end
end
endgenerate
Also at http://www.edaplayground.com/x/23L (based off of Morgan's copy).
And, don't you need to add a valid signal into the fifo, or is the data actually always available to be pushed in ?
Other then the *_ptr in your code should be assigned with non-blocking assignment (<=), there really isn't anything wrong with your code.
If you want to assign Buffer with a for-loop inside of an always block, you can use the following:
integer i;
always #(negedge clkin) begin
if (!full) begin
for (i=0;i<BusWidthIn;i=i+1) begin: i_buffin
Buffer[wr_ptr+i] <= datain[i*BitPerWord +: BitPerWord];
end
wr_ptr <= wr_ptr + BusWidthIn;
end
end
datain[i*BitPerWord+BitPerWord-1:i*BitPerWord] will not compile in Verilog because the MSB and LSB select bits are 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 +:.
I am coding in Verilog a typical count-to-n-then-reset-to-0 counter. My module has the logic to increment and reset the counter.
My issue is that I don't know where the counter itself should be defined.
I could pass the counter (as inout?) to the module. That's ok, but the counter still has to be defined somewhere so it this doesn't do me any good.
Nothing else except this module should touch the counter, so I'd like to have the counter created within this module, and not passed in or out.
Is this reasonably standard, and if so, will someone point to a reference please on how to instantiate the counter?
(I'm on day 2 of Verilog, so be afraid, heh)
EDIT - here's the code. As far as I can tell, it works. I haven't implemented DIR == REVERSE yet.
Couple of interesting gotchas. The (now commented out) STEPPER=0 line was causing an error in a schematic; it thought that STEPPER was tied to ground as well as other logic.
Also, I use = instead of <= in some places involving counter - I was getting timing problems (I suppose.) The procedural assignment removed (hid?) the problem.
module cam(
input [7:0] DIVISOR,
input DIR,
input SPINDLE,
output reg STEPPER
);
parameter FORWARD = 1'b1;
parameter REVERSE = !FORWARD;
reg[7:0] counter = 0;
always #(posedge SPINDLE) begin
// STEPPER = 0;
if (DIR == FORWARD) begin
counter = counter + 1;
if (counter == DIVISOR) counter = 0;
end
else begin
// counter <= counter - 1;
// if (counter == (-1)) counter <= DIVISOR;
end
end
always #(negedge SPINDLE) begin
STEPPER = (counter == 0) ? 1 : 0;
end
endmodule
Should just be defined as a register within the module. Here's an example from some of my code.
module trigger(clk, rxReady, rxData, txBusy, txStart, txData);
input clk;
input [7:0] rxData;
input rxReady;
input txBusy;
output reg txStart;
output reg[7:0] txData;
integer count81; // Number of cells received over serial (start solving after 81)
reg[8:0] data[0:8][0:8];
integer state;
always #(posedge clk) begin
case (state)
read:
if (rxReady) begin
data[count81 % 9][count81 / 9] = rxData ? 1<<(rxData-1) : -1;
if (count81 < 80) count81 <= count81 + 1;
else begin
count81 <= 0;
state <= solving;
end
end
etc....
endcase
end
endmodule
Congrats on getting out of the Java world for the time being. FPGAs are the only thing that seems exciting anymore.