Heat FPGA elements using verilog - verilog

I would like to know what is the best way to write code that would fill in the various elements of the FPGA (lut, fdce, ram, dsp)?
I want something like this to choose between elements:
//`define LUT
//`define FDCE
//`define DSP
`define BRAM
And I have one good version for fdce, but idk how to fill other elements:
`ifdef FDCE
wire [NUM_ELEMENTS_FDCE-1:0] out_wire_FDCE_1;
genvar k;
generate
for (k=0; k < NUM_ELEMENTS_FDCE; k=k+1)
begin: NUM2
wire out_FDCE_1;
FDCE_1 #(
.NUM_MODUL(600)
)FDCE_1_inst (
.fclk (fclk ),
.enable_heater(enable_heater ),
.out (NUM2[k].out_FDCE_1)
);
assign out_wire_FDCE_1[k] = NUM2[k].out_FDCE_1;
end
endgenerate
assign out_FDCE = (out_wire_FDCE_1=={NUM_ELEMENTS_FDCE{1'b1}}) ? 1 : 0 ;
`endif

Related

How do I generate N counters inside a generate block to load test an FPGA?

I need to estimate the maximum number of 16-bit counters that a FPGA board can fit. I created a 16-bit counter module with enable (en) and terminal count (TC), and instantiated this inside a generate block in a top level module. However, I need to generate these counters in a chain where the TC output of one acts as the enable for the next counter in the chain. I'm unable to figure out the logic for this. Can anyone help me ?
16-bit counter code:
module counter_16 (clk, Q, TC, en);
input clk, en;
output [15:0] Q;
output TC;
wire clk, en;
reg [15:0] Q = 0; //initial value for the output count
reg TC;
always #(posedge clk)
begin
if(en == 1)
begin
Q <= Q+1;
end
TC = &Q; //TC is 1 when all bits of Q is high
end
endmodule
Counter generation module:
module counter_generator
#(
parameter n = 10
)
(output [15:0] cnt_out,
output TC,
input clk, en);
wire [n-1:0] temp_en;
temp_en[0] <= 0;
wire [15:0] temp_out;
generate
genvar i;
for(i=1;i<=n;i=i+1)
begin : counter_identifier
counter_16 counter_16_gen (
.clk(clk),
.Q(temp_out),
.TC(temp_en[i-1]),
.en(en));
end
endgenerate
endmodule
The first thing to do is make the loop start from 0, not 1, so that the signal indexes align.
Create a signal tc_out that is n bits wide and connect that directly to the TC port in the generate block, using the index [i]. TC of instance 0 is connected to tc_out[0], etc. This is straightforward, and it helps us with the en connections.
Create a signal temp_en that is also n bits wide and connect that directly to the en port in the generate block. The key is to assign this signal to the tc_out signal as seen below.
en of instance 0 is driven by the en input of counter_generator
en of instance 1 is driven by the TC output of instance 0
en of instance 2 is driven by the TC output of instance 1
etc.
Lastly, create an array of n 16-bit wires, temp_out, and connect that directly to the Q port in the generate block.
module counter_generator
#(
parameter n = 10
)
(
output [15:0] cnt_out,
output TC,
input clk, en
);
wire [n-1:0] tc_out;
wire [n-1:0] temp_en = {tc_out[n-2:0], en};
wire [15:0] temp_out [n];
assign TC = temp_out[n-1];
generate
genvar i;
for (i=0; i<n; i=i+1) begin : counter_identifier
counter_16 counter_16_gen (
.clk (clk),
.Q (temp_out[i]),
.TC (tc_out [i]),
.en (temp_en [i])
);
end
endgenerate
endmodule

How can I use genvar variable to access input signals?

I have a module with 30-vector inputs.. I need help in the for loop assignment.
module test (
input [3:0] i0,
input [3:0] i1,
input [3:0] i2,
...
input [3:0] i29
);
wire [3:0] int_i [0:29];
genvar j;
generate
for (j=0; j<30; j=j+1) begin
assign int_i[j] = i(j) //need help here
end
endgenerate
endmodule
Is there a easy way to do this in Verilog. I know I can do this in System verilog by creating a 2-d vector of inputs. But is there a way to do this in Verilog?
The only way to do this in Verilog is to flatten out the 2-D array into a single vector.
module test (
input [30*4-1:0] i;
);
wire [3:0] int_i [0:29];
genvar j;
for (j=0; j<30; j=j+1) begin
assign int_i[j] = i[4*j+:4];
end
This is a systemverilog feature, in verilog, this should be packing the input array into a vector (I included a parameter in order to automatize things):
module test
# (
parameter WIDTH = 4,
parameter DEPTH = 30
) (input [(WIDTH*DEPTH)-1:0] i);
wire [WIDTH-1:0] int_i [DEPTH-1:0];
genvar j;
generate
for(j=0; j<DEPTH; j=j+1) begin: assign_i_gen //..(don't forget to name the for loop)
assign int_i[j] = i[(WIDTH*j)+:WIDTH];
end
endgenerate

Instantiate a module based on a condition in Verilog

I have a 1023 bit vector in Verilog. All I want to do is check if the ith bit is 1 and if it is 1 , I have to add 'i' to another variable .
In C , it would be something like :
int sum=0;
int i=0;
for(i=0;i<1023;i++) {
if(a[i]==1) {
sum=sum+i;
}
Of course , the addition that I am doing is over a Galois Field . So, I have a module called Galois_Field_Adder to do the computation .
So, my question now is how do I conditionally check if a specific bit is 1 and if so call my module to do that specific addition .
NOTE: The 1023 bit vector is declared as an input .
It's hard to answer your question without seeing your module, as we can't gage where you are in your Verilog. You always have to think of how your code translates in gates. If we want to translate your C code into synthesizable logic, we can take the same algorithm, go through each bit one after the other, and add to the sum depending on each bit. You would use something like this:
module gallois (
input wire clk,
input wire rst,
input wire [1022:0] a,
input wire a_valid,
output reg [18:0] sum,
output reg sum_valid
);
reg [9:0] cnt;
reg [1021:0] shift_a;
always #(posedge clk)
if (rst)
begin
sum[18:0] <= {19{1'bx}};
sum_valid <= 1'b0;
cnt[9:0] <= 10'd0;
shift_a[1021:0] <= {1022{1'bx}};
end
else
if (a_valid)
begin
sum[18:0] <= 19'd0;
sum_valid <= 1'b0;
cnt[9:0] <= 10'd1;
shift_a[1021:0] <= a[1022:1];
end
else if (cnt[9:0])
begin
if (cnt[9:0] == 10'd1022)
begin
sum_valid <= 1'b1;
cnt[9:0] <= 10'd0;
end
else
cnt[9:0] <= cnt[9:0] + 10'd1;
if (shift_a[0])
sum[18:0] <= sum[18:0] + cnt[9:0];
shift_a[1021:0] <= {1'bx, shift_a[1021:1]};
end
endmodule
You will get your result after 1023 clock cycles. This code needs to be modified depending on what goes around it, what interface you want etc...
Of importance here is that we use a shift register to test each bit, so that the logic adding your sum only takes shift_a[0], sum and cnt as an input.
Code based on the following would also work in simulation:
if (a[cnt[9:0])
sum[18:0] <= sum[18:0] + cnt[9:0];
but the logic adding to sum would in effect take all 1023 bits of a[] as an input. This would be quite hard to turn into actual lookup tables.
In simulation, you can also implement something very crude such as this:
reg [1022:0]a;
reg [9:0] sum;
integer i;
always #(a)
begin
sum[9:0] = 10'd0;
for (i=0; i < 1023; i=i+1)
if (a[i])
sum[9:0] = sum[9:0] + i;
end
If you were to try to synthesize this, sum would actually turn into a chunk of combinatorial logic, as the 'always' block doesn't rely on a clock. This code is in fact equivalent to this:
always #(a)
case(a):
1023'd0: sum[18:0] = 19'd0;
1023'd1: sum[18:0] = 19'd1;
1023'd2: sum[18:0] = 19'd3;
etc...
Needless to say that a lookup table with 1023 input bits is a VERY big memory...
Then if you want to improve your code, and use your FPGA as an FPGA and not like a CPU, you need to start thinking about parallelism, for instance working in parallel on different ranges of your input a. But this is another thread...

CPLD Breathing LED with flexible set points

This is my first post and my first attempt at using a PLD.
I have written some code to make a breathing LED with 7 set points. The code produces a pwm output according to the first set point. It then slowly increases/decreases the pwm towards the next set point (7 in total).
The code works but I think it can be done better as I need to put 16 instantiations of this into a Lattice 4256 CPLD (not possible with my code).
I am keen to learn how a professional Verilog programmer would tackle this.
Many thanks in advance for your support.
PWM Generation
module LED_breath (led, tmr_clk);
output reg led;
input tmr_clk;
reg [7:0] cnt;
reg [6:0] pwm_cnt;
reg [6:0] pwm_val;
reg [2:0] pat_cnt;
reg [9:0] delay_cnt;
reg [6:0] cur_pat;
reg [6:0] nxt_pat;
parameter pattern = {7'h00, 7'h00, 7'h00, 7'h00, 7'h00, 7'h00, 7'h00, 7'h00};
always #(posedge tmr_clk)
begin
pwm_cnt = cnt[7] ? ~cnt[6:0] : cnt[6:0]; //Generate triangle wave
if(pwm_cnt > pwm_val) //Generate pwm
led <= 1'b0;
if(pwm_cnt < pwm_val)
led <= 1'b1;
cnt = cnt + 1;
end
always #(posedge tmr_clk) //breathing pattern
begin
if(!delay_cnt) //Add delay
begin
cur_pat <= ((pattern >> (7*pat_cnt)) & 7'b1111111); //Find correct pattern No. from parameter list
if((pat_cnt+1) == 8) //Check for last pattern - overflow, set to 0
nxt_pat <= (pattern & 7'b1111111);
else
nxt_pat <= ((pattern >> (7*(pat_cnt+1))) & 7'b1111111);
if(pwm_val == nxt_pat) //If pwm is at max or min increment count to get next pattern
pat_cnt <= pat_cnt + 1;
if(cur_pat <= nxt_pat) //Current pattern < next pattern, count up
pwm_val <= pwm_val + 1;
if(cur_pat >= nxt_pat) //Current pattern < next pattern, count down
pwm_val <= pwm_val - 1;
end
delay_cnt <= delay_cnt + 1;
end
endmodule
module top (led_0, led_1, led_2, led_3);
output led_0;
output led_1;
output led_2;
output led_3;
defparam I1.TIMER_DIV = "128";
OSCTIMER I1 (.DYNOSCDIS(1'b0), .TIMERRES(1'b0), .OSCOUT(osc_clk), .TIMEROUT(tmr_clk));
LED_breath #(.pattern({7'h20, 7'h70, 7'h50, 7'h70, 7'h40, 7'h10, 7'h60, 7'h10})) led_A(
.led (led_0),
.tmr_clk (tmr_clk)
);
LED_breath #(.pattern({7'h70, 7'h10, 7'h30, 7'h20, 7'h60, 7'h40, 7'h70, 7'h10})) led_B(
.led (led_1),
.tmr_clk (tmr_clk)
);
LED_breath #(.pattern({7'h10, 7'h30, 7'h10, 7'h18, 7'h40, 7'h50, 7'h30, 7'h60})) led_C(
.led (led_2),
.tmr_clk (tmr_clk)
);
LED_breath #(.pattern({7'h50, 7'h70, 7'h40, 7'h50, 7'h40, 7'h70, 7'h60, 7'h70})) led_D(
.led (led_3),
.tmr_clk (tmr_clk)
);
endmodule
Can you explain a bit what you are trying to achieve in this always block ?
always #(posedge tmr_clk)
I think you're using a fixed frequency and changing duty cycle to get desired breathing effect.
1) Is my thinking correct ?
2) If yes, how do you decide when to change the pattern ?

Shift Register Design using Structural Verilog outputs X

I am designing a shift register using hierarchical structural Verilog. I have designed a D flip flop and an 8 to 1 mux that uses 3 select inputs. I am trying to put them together to get the full shift register, but my output only gives "XXXX" regardless of the select inputs.
Flip Flop Code
module D_Flip_Flop(
input D,
input clk,
output Q, Q_bar
);
wire a,b,c,d;
nand(a,D,b);
nand(b,a,clk,d);
nand(c,a,d);
nand(d,c,clk);
nand(Q,d,Q_bar);
nand(Q_bar,b,Q);
endmodule
8 to 1 Mux
module Mux8to1(
input [2:0]S,
input A,B,C,D,E,F,G,H,
output Out
);
wire a,b,c,d,e,f,g,h;
and(a, A,~S[2],~S[1],~S[0]);
and(b, B,~S[2],~S[1],S[0]);
and(c, C,~S[2],S[1],~S[0]);
and(d, D,~S[2],S[1],S[0]);
and(e, E,S[2],~S[1],~S[0]);
and(f, F,S[2],~S[1],S[0]);
and(g, G,S[2],S[1],~S[0]);
and(h, H,S[2],S[1],S[0]);
or(Out, a,b,c,d,e,f,g,h);
endmodule
Hierarchical Combination of the Two
module shiftRegister_struct(
input clk,
input [2:0]S,
input [3:0]L,
output reg [3:0]V
);
wire a,b,c,d;
wire V_bar[3:0];
Mux8to1 stage3(S[2:0],V[3],V[0],V[2],1'b0,V[2],V[3],V[2],L[3],a);
Mux8to1 stage2(S[2:0],V[2],V[3],V[1],V[3],V[1],V[3],V[1],L[2],b);
Mux8to1 stage1(S[2:0],V[1],V[2],V[0],V[2],V[1],V[2],V[1],L[1],c);
Mux8to1 stage0(S[2:0],V[0],V[1],V[3],V[1],1'b0,V[1],1'b0,L[0],d);
D_Flip_Flop stage3b(a,clk,V[3],V_bar[3]);
D_Flip_Flop stage2b(b,clk,V[2],V_bar[2]);
D_Flip_Flop stage1b(c,clk,V[1],V_bar[1]);
D_Flip_Flop stage0b(d,clk,V[0],V_bar[0]);
end module
Any thoughts on what might be screwing up my output? The output is V[3:0].
I should also include my test bench code:
module Shift_Test_Bench;
// Inputs
reg [2:0] S;
reg [3:0] L;
reg clk;
integer i;
integer j;
// Outputs
wire [3:0] V;
// Instantiate the Unit Under Test (UUT)
shiftRegister_struct uut (
.clk(clk),
.S(S),
.L(L),
.V(V)
);
initial begin
// Initialize Inputs
S = 7;
L = 3;
clk = 1;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
for(i = 0; i < 16; i = i+1)
begin
S = i;
for(j = 0; j < 2; j = j+1)
begin
clk = !clk;
#5;
end
end
end
endmodule
You have a wiring bug in your D_Flip_Flop module. When I simulated your testbench, I got compiler warnings:
Implicit wire 'f' does not have any driver, please make sure this is
intended.
Implicit wire 'e' does not have any driver, please make sure this is
intended.
Here are the lines:
nand(Q,d,f);
nand(Q_bar,b,e);
Your missing a reset condition, either synchronous or asynchronous. Your flops have an unknown value and never reach known state because the data input is dependent on the flop output. By adding a reset to can put the flops into a known state independent of its outputs (V/V_bar).
In this case adding a synchronous is be easier. Simply add some 2-to-1 muxes and a new reset pin.
Mux2to1 syncrst3(a_d,a,1'b0,reset);
// ...
D_Flip_Flop stage3b(a_d,clk,V[3],V_bar[3]);
// ...

Resources