`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 20:07:59 12/16/2017
// Design Name:
// Module Name: keyscan
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module keyscan(key, clk, reset, keyout);
input [9:0] key;
input clk, reset;
output reg [127:0] keyout;
reg [3:0] keyp [31:0] ;
reg [3:0] key_bcd;
integer i, count;
///////ERROR help me ㅠ.ㅠ
always # (posedge reset) begin
if(reset==1) begin
for(i=0; i<32; i=i+1)begin
keyp[i] <= 4'hF;
end
key_bcd <= 4'b1111;
count <= 0;
end
end
always # (*) begin
case(key)
10'b0000000001 :
begin
key_bcd = 4'b0000; //0
count = count + 1;
end
10'b0000000010 :
begin
key_bcd = 4'b0001; // 1
count = count + 1;
end
10'b0000000100 :
begin
key_bcd = 4'b0010; // 2
count = count + 1;
end
10'b0000001000 :
begin
key_bcd = 4'b0011; // 3
count = count + 1;
end
10'b0000010000 :
begin
key_bcd = 4'b0100; // 4
count = count + 1;
end
10'b0000100000 :
begin
key_bcd = 4'b0101; // 5
count = count + 1;
end
10'b0001000000 :
begin
key_bcd = 4'b0110; // 6
count = count + 1;
end
10'b0010000000 :
begin
key_bcd = 4'b0111; // 7
count = count + 1;
end
10'b0100000000 :
begin
key_bcd = 4'b1000; // 8
count = count + 1;
end
10'b1000000000 :
begin
key_bcd = 4'b1001; // 9
count = count + 1;
end
default : key_bcd = 4'b1111; // ??
endcase
if(count == 32)
count = 0;
end
always# (count) begin
if(key_bcd != 4'b1111)
keyp[count-1] <= key_bcd;
end
always# (posedge clk)begin
keyout = {keyp[31],124'hfffffffffffffffffffffffffffffff};
end
endmodule
ERROR ㅠ.ㅠ
HDLCompiler:1401 - "C:\Users\com603\Desktop\verilog\aqx\keyscanf.v" Line 44: Signal keyp[31][3] in unit keyscanf is connected to following multiple drivers:
you have 2 always block which drive the same register keyp:
always # (posedge reset) begin
if(reset==1) begin
for(i=0; i<32; i=i+1)begin
keyp[i] <= 4'hF; // <<<<<<<<<<<<<<<<<
end
...
and
always# (count) begin
if(key_bcd != 4'b1111)
keyp[count-1] <= key_bcd; // <<<<<<<<<<<<<<<<<
end
In simulation it will produce unpredictible result since the last driver will win. But there is no way to say which one is the last. Synthesis should complain about it.
You need to find a way to combine both statements in the same always block.
First of all you need to synchronize your code using clock. You even have clk as an input, so use with #(posedge clk) in your block.
I guess something like the following should work:
always # (posedge clk or posedge reset) begin
if(reset==1) begin
for(i=0; i<32; i=i+1)begin
keyp[i] <= 4'hF;
end
key_bcd <= 4'b1111;
end
else if(key_bcd != 4'b1111)
keyp[count-1] <= key_bcd;
end
Related
this is a very basic question but if somebody can help me with these errors, I'd really appreciate it. I am an EE undergrad, new to Verilog, and I'd appreciate any help/explanation.
The errors I received were:
10028 Can't resolve multiple constant drivers for "led" at compare_block.sv (66)
10029 Constant driver at compare_block.sv(61)
What are the multiple constant drivers here? Originally, I had the led assignment (led <= led_val) within the second always block, and I thought moving it up to the first always block would change the errors, but it did not.
module compare_block (clk, reset_n, result, led);
parameter data_width = 8; /
parameter size = 1000;
input clk, reset_n;
input [data_width:0] result;
logic [(data_width):0] data_from_rom;
logic [9:0] addr_to_rom;
output reg led;
reg [(data_width):0] comp_sig [size-1:0];
reg [data_width:0] comp_sig_temp;
reg [(data_width):0] filt_sig [size-1:0];
reg [(data_width):0] ans_sig [size-1:0];
integer i, iii;
reg [9:0] ii ;
integer sum_array;
wire [(data_width+3):0] array_avg;
reg [data_width:0] summed_arr [size-2 : 0];//container for all summation steps
wire total_sum;
reg ans_sig_done;
reg [data_width : 0] summed_ans;
reg [data_width:0] max_val, error_val;
initial begin
i = 0;
ii = 0;
led=0;
data_from_rom='b000000000;
summed_ans='b000000000;
max_val='b000000000;
for (iii=0;iii<(size-1);iii=iii+1) begin
filt_sig[iii]=0;
ans_sig [iii]=0;
comp_sig[iii]=0;
summed_arr[iii]=0;
end
end
//port map to ROM
rom_compare ref_wave(
.clk(clk),
.addr(addr_to_rom), //text file?
.data(data_from_rom)
);
//Moore FSM
localparam [3:0]
s0=0, s1 = 1, s2 = 2, s3 = 3, s4 = 4, s5 = 5;
reg [3:0] state_reg, state_next;
initial state_next = 0;
always #(posedge clk, negedge reset_n) begin
if (reset_n == 'b0) begin //reset is active low
state_reg <= s0;
end else begin
state_reg <= state_next;
led <= led_val;
end
end
always #(state_reg) begin
state_next = state_reg;
led=0;
case (state_reg)
s0 : begin //initial state, reset state
if (!reset_n) begin
led <= 0;
ii <= 0;
end else begin
state_next <= s1;
end
end
s1 : begin
if (ii>(size)) begin
ii <= 0;
end else begin
addr_to_rom <= ii;
state_next <= s2;
end
end
s2 : begin
comp_sig_temp <= data_from_rom;
filt_sig [ii] <= result;
state_next <= s3;
end
s3 : begin
comp_sig[ii] <= comp_sig_temp;
state_next <= s4;
end
s4 : begin
ans_sig[ii] <= filt_sig[ii] - comp_sig[ii];
state_next <= s5;
end
s5 : begin
if (ii>(size-2)) begin
ans_sig_done = 1;
end else begin
ans_sig_done = 0;
end
ii <= ii+1;
state_next <= s0;
end
endcase
end
reg [(data_width+2):0] sum;
integer j;
always #* begin
sum = 0;
if (ans_sig_done == 1) begin
for (j=4; j<(size-1); j=j+2) begin
sum = sum +ans_sig[j];
if (ans_sig[j] > max_val) begin
max_val = ans_sig[j];
end
end
end
end
assign array_avg = sum >> 'd3; //2^3 = 8
always #(clk, result) begin //posedge clk, result
filt_sig [i] <= result;
i <= i + 1;
end
assign error_val = max_val >> 'd2; //approx 25% of max value of array
reg led_val;
always #(*)
begin
if (array_avg < error_val) begin
led_val <= 'b1;
end else begin
led_val <= 'b0;
end
end
endmodule
I figured it out!
The two instances were me trying to initialize one led = 0 in one always block and then assigning led <= led_val in another. You can't refer to an output in two different always blocks.
I have the main module with FIFO stuff.
Here it is:
module syn_fifo #(
parameter DATA_WIDTH = 8, // inpit capacity
parameter DATA_DEPTH = 8 // the depth of the FIFO
)
(
input wire clk,
input wire rst,
// Write_______________________________________________
input wire [DATA_WIDTH-1:0]din, // the input data
input wire wren, // Write anable
output wire full,
// Read________________________________________________
output wire [DATA_WIDTH-1:0]dout, // The output data
input wire rden, // Read enable
output wire empty
);
integer q_size; // The queue size(length)
integer golova; // The queue beginning
integer hvost; // The end of queue
reg [DATA_WIDTH-1:0]fifo[DATA_DEPTH-1:0];
assign full = (q_size == DATA_DEPTH) ? 1'b1: 1'b0; // FIFO is full
/*
True { full = (q_size==DATA_TEPTH) = 1 }, then wire "full" goes to "1" value
False { full = (q_size==DATA_TEPTH) = 0 }, then wire "full" goes to "0" value
*/
assign empty = (golova == hvost); // FIFO is empty
assign dout = fifo[hvost]; // FWFT (other write mode)
integer i;
//___________(The queue fullness)___________________
always #(posedge clk or posedge rst)
begin
if (rst == 1'b1)
begin
for (i = 0; i < DATA_DEPTH; i = i + 1) // incrementing the FIFO
fifo[i] <= 0; // Resetting the FIFO
golova <= 0; // Resetting the queue start variable
end
else
begin //Write_______________________________________
if (wren && ~full)
begin
fifo[golova] <= din; // putting data in to the golova
if (golova == DATA_DEPTH-1) // restrictions for the queue beginning
golova <= 0; // Reset the beginning
else
golova <= golova + 1; // other occurence incrementing
end
end
end
//Reading
always #(posedge clk or posedge rst)
begin
if (rst == 1'b1)
begin
hvost <= 0;
end
else
begin
if (rden && !empty)
/*for staying inside the queue limits - make the check of non equality of the "hvost" & "queue size"*/
begin
if (hvost == DATA_DEPTH-1) // if hvost = DATA_DEPTH-1, then
hvost <= 0; // Reset hvost
else
hvost <= hvost + 1;
end
end
end
always # (posedge clk)
begin
if (rst == 1'b1) begin
q_size <= 0;
end
else
begin
case ({wren && ~full, rden && ~empty} )
2'b01: q_size <= q_size + 1; // RO
2'b10: q_size <= q_size - 1; // WO
default: q_size <= q_size; // read and write at the same time
endcase
end
end
endmodule
Also i've got the testbench module down delow:
`timescale 1ns / 1ps
module fifo_tb();
localparam CLK_PERIOD = 10;
reg clk;
reg rst;
always begin
clk <= 1'b0;
#(CLK_PERIOD / 2);
clk <= 1'b1;
#(CLK_PERIOD / 2);
end
localparam DATA_WIDTH = 8;
localparam DATA_DEPTH = 4;
reg [DATA_WIDTH-1:0]din;
reg wren;
reg rden;
wire [DATA_WIDTH-1:0]dout;
wire empty;
wire full;
wire wr_valid;
wire rd_valid;
task write;
input integer length;
begin
if (length) begin
#(posedge clk);
wren <= 1'b1;
while (length) begin
#(posedge clk);
if (wr_valid) begin
length <= length - 1;
if (length == 1) begin
wren <= 1'b0;
end
end
end
end
end
endtask
task read;
input integer length;
begin
if (length) begin
#(posedge clk);
rden <= 1'b1;
while (length) begin
#(posedge clk);
if (rd_valid) begin
length <= length - 1;
if (length == 1) begin
rden <= 1'b0;
end
end
end
end
end
endtask
initial begin
rst <= 1'b0;
wren <= 1'b0;
rden <= 1'b0;
#50;
rst <= 1'b1;
#50;
rst <= 1'b0;
#200;
/* Test Start */
//write(4);
//read(4);
/* Test Stop */
#1000;
$finish;
end
assign wr_valid = wren & ~full;
assign rd_valid = rden & ~empty;
always #(posedge clk) begin
if (rst == 1'b1) begin
din <= 0;
end else begin
if (wr_valid == 1'b1) begin
din <= din + 1;
end
end
end
// write?
always begin
#400;
write(5);
#15;
write(7);
#25;
write(3);
#15;
write(9);
#15;
write(1);
#10000;
end
// read?
always begin
#420;
read(3);
#37;
read(13);
#21;
read(7);
#15;
read(9);
#15;
read(4);
#20;
read(7);
#10000;
end
initial begin
$dumpfile("test.vcd");
$dumpvars(0,fifo_tb);
end
syn_fifo #(.DATA_WIDTH(DATA_WIDTH),
.DATA_DEPTH(DATA_DEPTH)) dut ( .clk(clk),
.rst(rst),
.din(din),
.wren(wren),
.full(full),
.dout(dout),
.rden(rden),
.empty(empty));
endmodule
Trying to compile all of it with iVerilog + GTKwave + Win10 by next command:
C:\Program Files\iverilog\bin>iverilog -o fifo.v fifo_tb.v
The compiler gives me the next message:
fifo_tb.v:138:error: Unknown module type:syn_fifo
2 error(s) during elaboration.
These modules were missing:syn_fifo referenced 1 times
At the necessary line "138" maybe the main mistake is covered by the "Number sign" in module instantiation?
/*132|*/ initial begin
/*133|*/ $dumpfile("test.vcd");
/*134|*/ $dumpvars(0,fifo_tb);
/*135|*/ end
/*136|*/
/*137|*/ syn_fifo #(.DATA_WIDTH(DATA_WIDTH),
/*138|*/ .DATA_DEPTH(DATA_DEPTH)) dut ( .clk(clk),
/*139|*/ .rst(rst),
/*140|*/ .din(din),
/*141|*/ .wren(wren),
/*142|*/ .full(full),
/*143|*/ .dout(dout),
/*144|*/ .rden(rden),
/*145|*/ .empty(empty));
/*146|*/
/*147|*/ endmodule
I'm not shure of that.
Seems like you are indicating fifo.v to be your output file, try:
iverilog -o syn_fifo.tb -s fifo_tb fifo_tb.v fifo.v
-o -> output file
-s -> top module (in this case, the test one)
(after everything, include all the files)
Then, to run it:
vvp syn_fifo.tb
Thank you, dear #m4j0rt0m
I just forgot to type in the output file name at the CMD window. Was very exhausted so haven't noticed such a detail)))
Usually it looks like:
iverilog -o OUTPUT_FILE_NAME fifo_tb.v fifo.v
And also I tried your advice, and it's finally done!
i wrote a fifo in system verilog
i try to push some data to this fifo (i wrote a tb) and when i push data the fifo_wr_ptr, fifo_fre_space,fifo_used_space don't update (only data write to mem[0])
i will be glad for help (why my ptr don't increment by 1 for example)
Thanks alot!
and here is my simulation that shows my problem:
i attached my code:
module fifo
#(parameter WIDTH = 32, parameter DEPTH = 64 ) ( clk, rst_l, sw_rst, fifo_din, fifo_push_en, fifo_pop_en, fifo_dout, fifo_o_full, fifo_o_empty, fifo_used_space, fifo_free_space );
function integer log2; //can use the $clog2() function
input [31:0] value;
reg [31:0] value_tmp;
begin value_tmp = value; for(log2=0; value_tmp>0; log2=log2+1)
value_tmp=(value_tmp>>1);
end endfunction
localparam DEPTH_LOG2 = log2(DEPTH);
//interface input clk; input rst_l; input sw_rst; input[WIDTH-1:0] fifo_din; input fifo_push_en; input fifo_pop_en; output logic[WIDTH-1:0] fifo_dout; output logic fifo_o_full; output logic fifo_o_empty; output logic[DEPTH_LOG2-1:0] fifo_used_space; output logic[DEPTH_LOG2-1:0] fifo_free_space; logic debug_flag; //internal logic logic[WIDTH-1:0] mem[DEPTH_LOG2-1:0]; logic[DEPTH_LOG2-1:0] fifo_rd_ptr,fifo_wr_ptr;
assign fifo_o_empty = (fifo_used_space==0); assign fifo_o_full = (fifo_free_space==0);
always # (posedge clk or negedge rst_l) begin if(~rst_l) begin
fifo_free_space <= DEPTH;
fifo_used_space <= 0;
fifo_rd_ptr <= 0;
fifo_wr_ptr <= 0;
debug_flag <=0 ;
end else if (~sw_rst) begin
fifo_free_space <= DEPTH;
fifo_used_space <= 0;
fifo_rd_ptr <= 0;
fifo_wr_ptr <= 0;
debug_flag <= 0;
end else if(fifo_push_en==1 && fifo_o_full==0 && fifo_pop_en==0) begin //the fifo isn't full and can perform the write trasaction (and no read transaction)
fifo_used_space <= fifo_used_space + 1;
fifo_free_space <= fifo_free_space - 1;
mem[fifo_wr_ptr]<= fifo_din;
debug_flag <= 1;
if(fifo_wr_ptr == (DEPTH - 1))
fifo_wr_ptr <= 0;
else
fifo_wr_ptr++;
end else if (fifo_pop_en==1 && fifo_o_empty==0 && fifo_push_en==0) begin // the fifo isn't empty and can perform the read trasaction (and no write trasaction)
fifo_used_space <= fifo_used_space - 1;
fifo_free_space <= fifo_free_space + 1;
fifo_dout <= mem[fifo_rd_ptr];
if(fifo_rd_ptr == (DEPTH - 1)) begin
fifo_rd_ptr <= 0;
end else begin
fifo_rd_ptr <= fifo_rd_ptr + 1;
end end else begin
fifo_rd_ptr <= fifo_rd_ptr;
//fifo_wr_ptr <= fifo_wr_ptr;
//fifo_dout <= fifo_dout;
//fifo_used_space <= fifo_used_space;
fifo_free_space <= fifo_free_space; end end
endmodule
and here is the tb code:
`define WIDTH 32
`define DEPTH 64
module fifo_tb();
function integer log2; //can use the $clog2() function
input [31:0] value;
reg [31:0] value_tmp;
begin
value_tmp = value;
for(log2=0; value_tmp>0; log2=log2+1)
value_tmp=(value_tmp>>1);
end
endfunction
localparam DEPTH_LOG2 = log2(`DEPTH);
logic clk,rst_l,sw_rst,fifo_push_en,fifo_pop_en,fifo_o_full,fifo_o_empty;
logic[`WIDTH-1:0] fifo_din,fifo_dout,tempdata;
logic[DEPTH_LOG2-1:0] fifo_used_space,fifo_free_space;
fifo #(`WIDTH,`DEPTH) ff(.clk(clk), .rst_l(rst_l), .sw_rst(sw_rst), .fifo_din(fifo_din),
.fifo_push_en(fifo_push_en), .fifo_pop_en(fifo_pop_en),
.fifo_dout(fifo_dout), .fifo_o_full(fifo_o_full), .fifo_o_empty(fifo_o_empty),
.fifo_used_space(fifo_used_space), .fifo_free_space(fifo_free_space) );
initial
begin
clk =0;
rst_l = 0;
sw_rst= 0;
fifo_push_en=0;
fifo_pop_en=0;
fifo_din=0;
tempdata=0;
#15 rst_l=1;
#1 sw_rst=1;
push(10);
push(20);
push(30);
push(40);
pop(tempdata);
push(tempdata);
end
always
#5 clk=~clk;
task push;
input[`WIDTH-1:0] data;
if(fifo_o_full)
$display("--- Cannot push: Buffer full ----");
else begin
$display("Pushed: ",data);
#(posedge clk);
fifo_din = data;
fifo_push_en=1;
#(posedge clk);
fifo_push_en=0;
end
endtask
task pop;
output [`WIDTH-1:0] data;
if(fifo_o_empty)
$display("Cannot pop: buffer empty ---");
else begin
#(posedge clk);
fifo_pop_en=1;
#(posedge clk);
fifo_pop_en=0;
data=fifo_dout;
$display("----- Poped : ",data);
end
endtask
endmodule
Taking aside the oddity related to pointer incrementation, the code itself is confusing and difficult to deal with. Pasting reference FIFO module that should do the job, this also should help you to grasp on basics of coding style.
//----------------------------------------------------
// Module Name: fifo_sync.v
//----------------------------------------------------
// Description: generic sync FIFO module
//----------------------------------------------------
module fifo_sync #
(
parameter FIFO_DATA_WIDTH = 'd32,
parameter FIFO_PTR_WIDTH = 'd6
)
(
//------------------------------------------------
// Inputs
//------------------------------------------------
input clk,
input rst_n,
input wr_en,
input [FIFO_DATA_WIDTH-1:0] wr_data,
input rd_en,
//------------------------------------------------
// Outputs
//------------------------------------------------
output reg [FIFO_DATA_WIDTH-1:0] rd_data,
output stat_full,
output stat_empty,
output [ FIFO_PTR_WIDTH-1:0] stat_occupancy
);
//------------------------------------------------
// Local Parameters
//------------------------------------------------
localparam FIFO_DEPTH = 2**(FIFO_PTR_WIDTH-1);
//------------------------------------------------
// Internal Register(s)/Wire(s)/Integer(s)
//------------------------------------------------
reg [ FIFO_PTR_WIDTH-1:0] wr_ptr;
reg [ FIFO_PTR_WIDTH-1:0] rd_ptr;
reg [FIFO_DATA_WIDTH-1:0] fifo_array [FIFO_DEPTH-1:0];
integer int_i;
//------------------------------------------------
// Write Pointer Logic
//------------------------------------------------
always #(posedge clk or negedge rst_n)
begin: p_wr_ptr
if (!rst_n)
wr_ptr <= {FIFO_PTR_WIDTH{1'b0}};
else if (wr_en & !stat_full)
wr_ptr <= wr_ptr + 1'b1;
end
//------------------------------------------------
// Read Pointer Logic
//------------------------------------------------
always #(posedge clk or negedge rst_n)
begin: p_rd_ptr
if (!rst_n)
rd_ptr <= {FIFO_PTR_WIDTH{1'b0}};
else if (rd_en & !stat_empty)
rd_ptr <= rd_ptr + 1'b1;
end
//------------------------------------------------
// Status Interface
//------------------------------------------------
// FIFO full status flag
assign stat_full = (wr_ptr[FIFO_PTR_WIDTH-1] ^ rd_ptr[FIFO_PTR_WIDTH-1]) & (wr_ptr[FIFO_PTR_WIDTH-2:0] == rd_ptr[FIFO_PTR_WIDTH-2:0]);
// FIFO empty status flag
assign stat_empty = (wr_ptr == rd_ptr);
// FIFO occupancy status
assign stat_occupancy = wr_ptr - rd_ptr;
//-----------------------------------------------
// FIFO Write
//-----------------------------------------------
always #(posedge clk or negedge rst_n)
begin: p_fifo_write
if (!rst_n)
for (int_i = 0; int_i < FIFO_DEPTH - 1; int_i = int_i + 1)
fifo_array[int_i] <= {FIFO_DATA_WIDTH{1'b0}};
else if (wr_en & !stat_full)
fifo_array[wr_ptr] <= wr_data;
end
//-----------------------------------------------
// FIFO Read
//-----------------------------------------------
always #(posedge clk or negedge rst_n)
begin: p_fifo_read
if (!rst_n)
rd_data <= {FIFO_DATA_WIDTH{1'b0}};
else if (rd_en & !stat_empty)
rd_data <= fifo_array[rd_ptr];
end
endmodule
I want to implement in Verilog the following Matlab code:
symBuf = [symBuf(numFFT/2+1:end); zeros(numFFT/2,1)];
symBuf(KF+(1:KF)) = symBuf(KF+(1:KF)) + txSymb;
It is a simple overlap and add operation.
Here is my implementation:
module overlap
#(K = 3,
FFT = 128
)
(
input signed [15:0] symbInReal ,
input signed [15:0] symbInImag ,
input clock ,
input reset ,
input readyIn ,
input validIn ,
input lastIn ,
output signed [15:0] outReal ,
output signed [15:0] outImag ,
output reg lastOut ,
output wire readyOut ,
output reg validOut
);
reg signed [15:0] previousSymbolReal [2*FFT*K-1:0] ;
reg signed [15:0] previousSymbolImag [2*FFT*K-1:0] ;
reg signed [15:0] txSymbolBuffReal [K*FFT-1:0] ;
reg signed [15:0] txSymbolBuffImag [K*FFT-1:0] ;
reg [15:0] counter ;
reg [1:0] state ;
reg [3:0] nextstate ;
reg [15:0] clockcount ;
reg signed [15:0] outputValueReal ;
reg signed [15:0] outputValueImag ;
reg [15:0] buffcount ;
reg [7:0] symboutcount ;
reg [7:0] symbincount ;
reg last ;
reg lastvalidout ;
wire lastout ;
integer i;
initial begin
for (i=0; i<2*FFT*K ; i = i + 1) begin
previousSymbolReal[i] = 0;
previousSymbolImag[i] = 0;
end
end
always#(posedge clock) begin
if(~reset) begin
counter <= 0;
end else begin
counter <= counter +1;
if(nextstate != state)
counter <= 0;
end
end
always#(*) begin
if(~reset) begin
nextstate = 0;
end else begin
nextstate = state;
if(readyIn) begin
case(state)
4'd0: begin
if(validIn || last) begin
nextstate = 1;
end
end
4'd1: begin
if (counter == (FFT*K-2)) begin
nextstate = 2;
end
end
4'd2: begin
nextstate = 0;
end
endcase
end
end
end
always#(posedge clock) begin
if(~reset) begin
state <= 0;
end else begin
if(readyIn)
state <= nextstate;
end
end
always#(posedge clock) begin
if(~reset) begin
clockcount <= 0;
symboutcount <= 0;
lastOut <= 0;
end else begin
if(readyIn) begin
clockcount <= clockcount +1 ;
case(state)
4'd0: begin
validOut <= 0;
clockcount <= 0;
lastOut <= 0;
end
4'd1: begin
if(~lastvalidout)
validOut <= 1;
outputValueReal <= previousSymbolReal[clockcount+ FFT/2];
outputValueImag <= previousSymbolImag[clockcount+ FFT/2];
end
4'd2: begin
outputValueReal <= previousSymbolReal[clockcount + FFT/2];
outputValueImag <= previousSymbolImag[clockcount + FFT/2];
clockcount <= 0;
if(~lastvalidout)
validOut <= 1;
if(symboutcount == symbincount + 1 && last)
lastOut <= 1;
symboutcount <= symboutcount +1 ;
end
endcase
end
end
end
assign readyOut = readyIn;
genvar M;
generate
for(M=0;M<K*FFT;M=M+1) begin
always#(posedge clock) begin
if(state==2) begin
previousSymbolReal[M] <= previousSymbolReal[M+FFT/2];
previousSymbolImag[M] <= previousSymbolImag[M+FFT/2];
end
end
end
for(M=K*FFT;M<2*K*FFT-FFT/2;M=M+1) begin
always#(posedge clock) begin
if(state==2) begin
previousSymbolReal[M] <= previousSymbolReal[M+FFT/2]+txSymbolBuffReal[M-K*FFT];
previousSymbolImag[M] <= previousSymbolImag[M+FFT/2]+txSymbolBuffImag[M-K*FFT];
end
end
end
for(M=2*K*FFT-FFT/2;M<2*K*FFT;M=M+1) begin
always#(posedge clock) begin
if(state==2) begin
previousSymbolReal[M] <= txSymbolBuffReal[M-K*FFT];
previousSymbolImag[M] <= txSymbolBuffImag[M-K*FFT];
end
end
end
endgenerate
always#(posedge clock) begin
if(~reset) begin
buffcount <= 0;
symbincount <= 0;
last <= 0;
end else begin
if(validIn) begin
txSymbolBuffReal[buffcount] <= symbInReal;
txSymbolBuffImag[buffcount] <= symbInImag;
buffcount <= buffcount +1;
if(buffcount == K*FFT-1) begin
symbincount <= symbincount + 1;
buffcount <= 0;
end
if(lastIn)
last <= 1;
end
end
end
always#(posedge clock) begin
if(~reset)
lastvalidout <= 0;
else begin
if(last && lastOut)
lastvalidout <= 1;
end
end
assign outReal = outputValueReal;
assign outImag = outputValueImag;
endmodule
The problem here is that I have 4 huge arrays which take up to 4 times what is available in my FPGA.
Hence, I want to be able to use block RAMs. However, I don't think it's possible due to the number of read and write operations performed.
Does anyone have a solution for this?
However, I don't think it's possible due to the number of read and write operations performed.
Correct. At least, not without major changes to your design.
A typical block RAM element can only read or write one (or sometimes two) values per clock cycle, but your generate loops are trying to update every element in the RAM at once!
To make this operation use a block RAM, you will need to implement a state machine to update one element per clock cycle, and to sequence operations such that other states wait until the updates have completed.
If you want to accelerate this, you may be able to split the array into multiple block RAMs so that multiple values can be updated in parallel. (You will need to carefully consider which elements need to be read/written to avoid conflicts.)
I'm creating the I2C protocol in verilog to read data from a sensor (BMP180), AS you know, the sensor sends me a bit of ack recognition. How do I use the inout i2c_sda port to send and how do I receive.
As delivery and receipt i2c_sda the same line, if my variable is declared of type inout.
module stepPrueba(
input wire clk1,
input wire reset,
input wire start,
inout i2c_sda,
inout i2c_scl,
output wire ready,
output reg led1,
output reg led2
);
reg i2c_scl_out;
assign i2c_scl1= (i2c_scl_out == 1'b0) ? 1'b0 : 1'bz;
wire i2c_scl_in = i2c_scl;
assign i2c_scl = (i2c_scl_enable == 0) ? i2c_scl1 : clk1;
reg clk;
assign clk1 = (clk == 1)? 1'bz:1'b0;
reg i2c_sda_out;
assign i2c_sda = (i2c_sda_out == 1'b0) ? 1'b0 : 1'bz;
wire i2c_sda_in = i2c_sda ;
reg [6:0] addr;
reg [7:0] data;
reg enable; //(read=1, write=0)
reg datas;
reg enable2; //(read=1, write = 0)
reg [7:0] state;
reg [7:0] count;
reg i2c_scl_enable = 0;
reg [6:0] saved_addr;
reg [7:0] saved_data;
//goal es escribir al dispositivo direccion 0X55, 0Xaa
localparam STATE_IDLE = 0;
localparam STATE_START = 1;
localparam STATE_ADDR =2;
localparam STATE_RW = 3;
localparam STATE_WACK = 4;
localparam STATE_DATA = 5;
localparam STATE_WACK2 = 6;
localparam STATE_STOP = 7;
always#(posedge clk)
begin
//enable2 <= 0; //i2c_scl==zetas & c_lectura=z;
if(reset == 1)
begin
i2c_scl_out<=1;
i2c_scl_enable <= 0;
end
else
begin
if((state == STATE_IDLE) || (state == STATE_START) )
begin
//i2c_scl_enable <= 0; //dats == 1 --> ztas == z
i2c_scl_out<=1;
i2c_scl_enable <= 0;
end
else
begin
i2c_scl_enable <= 1; // dats==clk;
clk<=clk1;
end
end
end
always#(posedge clk)
begin
if(reset == 1)
begin
led1 <=0;
led2 <=0;
state <=0;
i2c_sda_out <= 1;// i2c_sda ==z;
addr <= 7'b1110111; // direccion del sensor
count <= 8'd0;
data <= 8'b11110100; //direccion interna PRESION
end
else //reset ==0
begin
case (state)
STATE_IDLE:
begin //idle
//datas <= 1; //zetas==z
i2c_scl_out<=1;
i2c_scl_enable <= 0;
i2c_sda_out <= 1;
if(start)
begin
state <= STATE_START;
saved_addr <= addr;
saved_data <= data;
// reg i2c_scl_out;
// assign i2c_scl1= (i2c_scl_out == 1'b0) ? 1'b0 : 1'bz;
// wire i2c_scl_in = i2c_scl;
// assign i2c_scl = (i2c_scl_enable == 0) ? i2c_scl1 : ~clk;
end
else
begin
state <= STATE_IDLE;
end
end
STATE_START:
begin // start
//enable <= 0; // lectura==z; --> i2c_sda==zetas
i2c_sda_out <= 0;
//datas <= 0; // zetas==0
state<= STATE_ADDR;
count <= 6;
end
STATE_ADDR:
begin //msb addres bit
//enable <= 0; // lectura==z; --> i2c_sda==zetas
i2c_sda_out <= saved_addr[count]; // datas ==0 --> zetas==0 || datas==1 --> zetas==z
if (count == 0)
begin
state <= STATE_RW;
end
else
begin
count <= count - 1;
end
end
STATE_RW:
begin
//enable <= 0; //enable==0 --> i2c_sda==zetas
i2c_sda_out <= 0;//datas <= 0;
state <= STATE_WACK;
end
STATE_WACK:
begin
//enable <= 1; //enable==1 lee i2c_sda==z & lectura==i2c_sda
//enable <= 0;
//if(APA)
if(i2c_sda_in==1)
begin
state <= STATE_IDLE;
end
else
begin
state <= STATE_DATA;
led1 <= 1;
end
count <= 7;
end
STATE_DATA:
begin
//enable <= 0;
i2c_sda_out <= saved_data[count];
if(count ==0)
begin
state <= STATE_WACK2;
end
else
begin
count <= count - 1;
end
end
STATE_WACK2:
begin
//enable <= 1;
if(i2c_sda_in ==1)
begin
state <= STATE_IDLE;
end
else
begin
state <= STATE_STOP;
led2 <= 1;
end
end
STATE_STOP:
begin
//enable <= 0;
i2c_sda_out <= 0;
state <= STATE_IDLE;
end
endcase
end
end
endmodule
If you have a module pin defined as
inout wire pin
then you can access it like so
wire pin_input = pin;
assign pin = pin_oe ? pin_output : 1'bz;
this should infer a tristate buffer.
However, I would be careful when doing this, as if you infer a tristate buffer too early, it can limit what you can do with the module. For example, it would be possible to connect multiple internal I2C components together, such as allowing multiple masters inside the FPGA access to the same pins. However, tristate signals cannot be routed inside the FPGA, so if you implement the tristate inside the I2C master module, this becomes impossible. Instead, what you might consider is implementing each pin as three module pins: input, output, and output enable/tristate. This allows multiple modules to be connected with an emulated tristate bus, and allows them to share one set of tristate buffers to the actual I/O pin on the chip.
For a good example of how this works, see the comments in https://github.com/alexforencich/verilog-i2c/blob/master/rtl/i2c_master.v .