everyone!
I'm working on my final project here and I find myself getting lost. essentially what I am trying to do is use my Basys board as an 8 bit signed number converter. So there are the eight switches which I pull as inputs to make a signed number such as 10111110. I then want to take that number and convert it to it's equivalent decimal value through 2's compliment. I then want to display the number on my seven-segment displays. I would love any tips or suggestions on how to start because I just can't figure out how I take the number and display it across the displays. I'll post my code and look forward to reading any suggestions you guys have for me. Thanks for the help!
input load, cup, cdown, rst;
input Sw7, Sw6, Sw5, Sw4, Sw3, Sw2, Sw1, Sw0;
output MyNumber[7];
seg7 h1(w, x, y, z, a, b, c, d, e,f,g);
clockdivider h2(clk0, ClkOut);
initial begin
MyNumber <= 8'b0000000;
end
always #(MyNumber)
w <= MyNumber[7]
MyNumber[6]
MyNumber[5]
MyNumber[4]
MyNumber[3]
MyNumber[2]
MyNumber[1]
MyNumber[0]
end
always #(posedge clk) begin
if(rst) begin
MyNumber <=0;
end else if (cup) begin
MyNumber = MyNumber + 1;
end else if (cdown) begin
MyNumber = MyNumber - 1;
end else if (load) begin
MyNumber[7] <= Sw0;
MyNumber[6] <= Sw1;
MyNumber[5] <= Sw2;
MyNumber[4] <= Sw3;
MyNumber[3] <= Sw4;
MyNumber[2] <= Sw5;
MyNumber[1] <= Sw6;
MyNumber[0] <= Sw7;
end
end
And here is my seven segment display code
input w, x, y, z;
output reg a, b, c, d, e,f,g;
reg [6:0] a_to_g;
reg [3:0] w_to_z;
initial begin
w_to_z[3] = w;
w_to_z[2] = x;
w_to_z[1] = y;
w_to_z[0] = z;
a=0;b=0;c=0;d=0;e=0;f=0;g=0;
end
always #(*) begin
w_to_z[3] = w;
w_to_z[2] = x;
w_to_z[1] = y;
w_to_z[0] = z;
case(w_to_z)
0:a_to_g=7'b0000001;
1:a_to_g=7'b1001111;
2:a_to_g=7'b0010010;
3:a_to_g=7'b0000110;
4:a_to_g=7'b1001100;
5:a_to_g=7'b0100100;
6:a_to_g=7'b0100000;
7:a_to_g=7'b0001111;
8:a_to_g=7'b0000000;
9:a_to_g=7'b0000100;
'ha:a_to_g=7'b0001000;
'hb:a_to_g=7'b1100000;
'hc:a_to_g=7'b0110001;
'hd:a_to_g=7'b1000010;
'hf:a_to_g=7'b0111000;
default a_to_g=7'b1111111;
endcase
a = a_to_g[6];
b = a_to_g[5];
c = a_to_g[4];
d = a_to_g[3];
e = a_to_g[2];
f = a_to_g[1];
g = a_to_g[0];
end
And I totally don't want to come off like I'm looking for someone to do my assignment for me. I'm just lost and could use a push in the right direction, thanks everyone.
Related
I am somewhat new to verilog, I tried running this code but it gives me an error:
module enc(in,out);
input [7:0] in;
output [3:0] out;
reg i;
reg [3:0] out;
always #*
begin
for (i=0;i<7;i=i+1)
begin
if ((in[i]==1) && (in[7:i+1]==0))
out = i;
else
out = 0;
end
end
endmodule
I think it complains about in[7:i+1] but i don't understand why ?
Can someone please advise..
EDIT
ok so I am reluctant to using the X due to their numerous problems.. I was thinking of modifying the code to something like this :
module enc(in,out);
input [7:0] in;
output [2:0] out;
reg i;
reg [2:0] out,temp;
always #*
begin
temp = 0;
for (i=0;i<8;i=i+1)
begin
if (in[i]==1)
temp = i;
end
out = temp;
end
endmodule
Do you think that will do the trick ? I currently don't have access to a simulator..
A priority encoder mean giving priority to a one bit if two or more bits meet the criteria. Looking at your code, it appears you wanted to give priority to a LSB while using a up counter. out is assigned in every look, so even if your could compile, the final result would be 6 or 0.
For an LSB priority encoder, first start with a default value for out and use a down counter:
module enc (
input wire [7:0] in,
output reg [2:0] out
);
integer i;
always #* begin
out = 0; // default value if 'in' is all 0's
for (i=7; i>=0; i=i-1)
if (in[i]) out = i;
end
endmodule
If you are only interested in simulation than your linear loop approach should be fine, something like
out = 0;
for (i = W - 1; i > 0; i = i - 1) begin
if (in[i] && !out)
out = i;
end
If you also care about performance, the question becomes more interesting. I once experimented with different approaches to writing parameterized priority encoders here. It turned out that Synopsys can generate efficient implementation even from the brain-dead loop above but other toolchains needed explicit generate magic. Here is an excerpt from the link:
output [WIDTH_LOG - 1:0] msb;
wire [WIDTH_LOG*WIDTH - 1:0] ors;
assign ors[WIDTH_LOG*WIDTH - 1:(WIDTH_LOG - 1)*WIDTH] = x;
genvar w, i;
integer j;
generate
for (w = WIDTH_LOG - 1; w >= 0; w = w - 1) begin
assign msb[w] = |ors[w*WIDTH + 2*(1 << w) - 1:w*WIDTH + (1 << w)];
if (w > 0) begin
assign ors[(w - 1)*WIDTH + (1 << w) - 1:(w - 1)*WIDTH] = msb[w] ? ors[w*WIDTH + 2*(1 << w) - 1:w*WIDTH + (1 << w)] : ors[w*WIDTH + (1 << w) - 1:w*WIDTH];
end
end
endgenerate
So my Edited solution worked... how silly !! I forgot to declare reg [2:0] i; and instead wrote reg i;
Thanks everybody
Hunks, I have to tell you, all your solutions are either too complex or non-synthesizable, or implement into slow multiplexors. Alexej Bolshakov at OpenCores uploaded an outstandin' parametrizable encoder on Aug 23, 2015, based on OR elements. No muxes, 100% synthesizable. His code (with my tiny formatting):
module encoder #(
parameter LINES = 16,
parameter WIDTH = $clog2(LINES)
)(
input [LINES-1:0] unitary_in,
output wor [WIDTH-1:0] binary_out
);
genvar i, j;
generate
for (i = 0; i < LINES; i = i + 1)
begin: loop_i
for (j = 0; j < WIDTH; j = j + 1)
begin: loop_j
if (i[j])
assign binary_out[j] = unitary_in[i];
end
end
endgenerate
endmodule
RTL viewer screenshot, Model-Sim screenshot
This solution divides the input into four blocks and checks for the first nonzero block. This block is further subdivided in the same way. It is reasonably efficient.
// find position of most significant 1 bit in 64 bits input
// (system verilog)
module bitscan(
input logic [63:0] in, // number input
output logic [5:0] out, // bit position output
output logic zeroout // indicates if input is zero
);
logic [63:0] m0; // intermediates
logic [15:0] m1;
logic [3:0] m2;
logic [5:0] r;
always_comb begin
m0 = in;
// choose between four 16-bit blocks
if (|m0[63:48]) begin
m1 = m0[63:48];
r[5:4] = 3;
end else if (|m0[47:32]) begin
m1 = m0[47:32];
r[5:4] = 2;
end else if (|m0[31:16]) begin
m1 = m0[31:16];
r[5:4] = 1;
end else begin
m1 = m0[15:0];
r[5:4] = 0;
end
// choose between four 4-bit blocks
if (|m1[15:12]) begin
m2 = m1[15:12];
r[3:2] = 3;
end else if (|m0[11:8]) begin
m2 = m1[11:8];
r[3:2] = 2;
end else if (|m0[7:4]) begin
m2 = m1[7:4];
r[3:2] = 1;
end else begin
m2 = m1[3:0];
r[3:2] = 0;
end
// choose between four remaining bits
if (m2[3]) r[1:0] = 3;
else if (m2[2]) r[1:0] = 2;
else if (m2[1]) r[1:0] = 1;
else r[1:0] = 0;
out = r;
zeroout = ~|m2;
end
endmodule
Here is another solution that uses slightly less resourcess:
module bitscan4 (
input logic [63:0] in,
output logic [5:0] out,
output logic zout
);
logic [63:0] m0;
logic [3:0] m1;
logic [3:0] m2;
logic [5:0] r;
always_comb begin
r = 0;
m0 = in;
if (|m0[63:48]) begin
r[5:4] = 3;
m1[3] = |m0[63:60];
m1[2] = |m0[59:56];
m1[1] = |m0[55:53];
m1[0] = |m0[51:48];
end else if (|m0[47:32]) begin
r[5:4] = 2;
m1[3] = |m0[47:44];
m1[2] = |m0[43:40];
m1[1] = |m0[39:36];
m1[0] = |m0[35:32];
end else if (|m0[31:16]) begin
r[5:4] = 1;
m1[3] = |m0[31:28];
m1[2] = |m0[27:24];
m1[1] = |m0[23:20];
m1[0] = |m0[19:16];
end else begin
r[5:4] = 0;
m1[3] = |m0[15:12];
m1[2] = |m0[11:8];
m1[1] = |m0[7:4];
m1[0] = |m0[3:0];
end
if (m1[3]) begin
r[3:2] = 3;
end else if (m1[2]) begin
r[3:2] = 2;
end else if (m1[1]) begin
r[3:2] = 1;
end else begin
r[3:2] = 0;
end
m2 = m0[{r[5:2],2'b0}+: 4];
if (m2[3]) r[1:0] = 3;
else if (m2[2]) r[1:0] = 2;
else if (m2[1]) r[1:0] = 1;
else r[1:0] = 0;
zout = ~|m2;
out = r;
end
endmodule
To be able to use variable indexes in part-slice suffixes, you must enclose the for block into a generate block, like this:
gen var i;
generate
for (i=0;i<7;i=i+1) begin :gen_slices
always #* begin
... do whatever with in[7:i+1]
end
end
The problem is that apllying this to your module, the way it's written, leads to other errors. Your rewritten module would look like this (be warned: this won't work either)
module enc (
input wire [7:0] in,
output reg [2:0] out // I believe you wanted this to be 3 bits width, not 4.
);
genvar i; //a generate block needs a genvar
generate
for (i=0;i<7;i=i+1) begin :gen_block
always #* begin
if (in[i]==1'b1 && in[7:i+1]=='b0) // now this IS allowed :)
out = i;
else
out = 3'b0;
end
end
endgenerate
endmodule
This will throw a synthesis error about out being driven from more than one source. This means that the value assigned to out comes from several sources at the same time, and that is not allowed.
This is because the for block unrolls to something like this:
always #* begin
if (in[0]==1'b1 && in[7:1]=='b0)
out = 0;
else
out = 3'b0;
end
always #* begin
if (in[1]==1'b1 && in[7:2]=='b0)
out = 1;
else
out = 3'b0;
end
always #* begin
if (in[2]==1'b1 && in[7:3]=='b0)
out = 2;
else
out = 3'b0;
end
.... and so on...
So now you have multiple combinational block (always #*) trying to set a value to out. All of them will work at the same time, and all of them will try to put a specific value to out whether the if block evaluates as true or false. Recall that the condition of each if statement is mutually exclusive with respect of the other if conditions (i.e. only one if must evaluate to true).
So a quick and dirty way to avoid this multisource situation (I'm sure there are more elegant ways to solve this) is to let out to be high impedance if the if block is not going to assign it a value. Something like this:
module enc (
input wire [7:0] in,
output reg [2:0] out // I believe you wanted this to be 3 bits width, not 4.
);
genvar i; //a generate block needs a genvar
generate
for (i=0;i<7;i=i+1) begin :gen_block
always #* begin
if (in[i]==1'b1 && in[7:i+1]=='b0) // now this IS allowed :)
out = i;
else
out = 3'bZZZ;
end
end
endgenerate
always #* begin
if (in[7]) // you missed the case in which in[7] is high
out = 3'd7;
else
out = 3'bZZZ;
end
endmodule
On the other way, if you just need a priority encoder and your design uses fixed and small widths for inputs and outputs, you may write your encoder as this:
module enc (
input wire [7:0] in,
output reg [2:0] out
);
always #* begin
casex (in)
8'b1xxxxxxx : out = 3'd7;
8'b01xxxxxx : out = 3'd6;
8'b001xxxxx : out = 3'd5;
8'b0001xxxx : out = 3'd4;
8'b00001xxx : out = 3'd3;
8'b000001xx : out = 3'd2;
8'b0000001x : out = 3'd1;
8'b00000001 : out = 3'd0;
default : out = 3'd0;
endcase
end
endmodule
(although there seems to be reasons to not to use casex in a design. Read the comment #Tim posted about it in this other question: How can I assign a "don't care" value to an output in a combinational module in Verilog )
In conclusion: I'm afraid that I have not a bullet-proof design for your requirements (if we take into account the contents of the paper Tim linked in his comment), but at least, you know now why i was unallowed inside a part-slice suffix.
On the other way, you can have half of the work done by studying this code I gave as an answer to another SO question. In this case, the module works like a priority encoder, parametrized and without casex statements, only the output is not binary, but one-hot encoded.
How to parameterize a case statement with don't cares?
out = in&(~(in-1))
gives you the one-hot results(FROM LSB->MSB where the first 1 at)
I want to write a module for GCD computing, using extended Euclidean algorithm. But the main problem is that I completely don't know how to do that without getting to the lowest (RTL) level. What I mean is to have FSM with three states:
IDLE (waiting for input)
COMPUTING (as many clock cycles as needed)
FINISHED (ready to read output).
However, when I try to separate FSM & computations into separate processes, like this:
module modinv(clk, reset, number, prime, finished, gcd, inverse_fail, inverse);
input [31:0] number, prime;
input wire clk, reset;
output integer gcd, inverse;
output reg finished, inverse_fail;
parameter [2:0] IDLE = 3'b001, COMPUTING = 3'b010, END = 3'b100;
reg [2:0] state, state_next;
integer a, b, c, q, p, r;
always # (posedge clk, posedge reset)
begin
if (reset == 1)
begin
state <= IDLE;
end
else
begin
state <= state_next;
end
end
always #(state or b)
begin
finished <= 0;
inverse_fail <= 0;
case (state)
IDLE:
begin
a <= number;
b <= prime;
p <= 1;
r <= 0;
state_next <= COMPUTING;
end
COMPUTING:
begin
c = a % b;
q = a / b;
a = b;
b = c;
r = p - q * r;
p = r;
if (b == 0)
begin
state_next <= END;
end
else
begin
state_next <= COMPUTING;
end
end
END:
begin
gcd <= a;
inverse <= p;
finished <= 1;
if (gcd != 1)
begin
inverse_fail <= 1;
end
end
endcase
end
endmodule
And when I try to put computation in the second process, in COMPUTING state case, it only works once - what is correct in means of verilog, because until computing is done, state doesn't change, so the process isn't called again.
However, when I put computation in the first process, there isn't any non-ugly way to limit the computations only to correct STATE, which results in wrong output (as soon as FSM is in FINISHED state, the output is already incorrect - one step further).
So, my question is - how to do it correctly without using FSM + datapath (low-level RTL) solution?
My current waveform:
You seem to be missing some clocked elements in your design.
From what I understand of your design, you seem to expect once the state goes to COMPUTING, it should keep iterating the values of a and b until b reaches 0. But the only thing you're actually clocking on a clock edge is the state variable, so there's no memory of a and b from one state to the next. If you want variables like a and b to have memory from one clock cycle to the next, then you need to latch these variables as well:
I made some modifications to your program, it might not be 100% correct, but you should see what I'm getting at. See if this makes sense how you do the combinational logic in the second block, but you register the values on the posedge so that you can use them at the start of the next clock cycle.
module modinv(clk, reset, number, prime, finished, gcd, inverse_fail, inverse);
input [31:0] number, prime;
input wire clk, reset;
output integer gcd, inverse;
output reg finished, inverse_fail;
parameter [2:0] IDLE = 3'b001, COMPUTING = 3'b010, END = 3'b100;
reg [2:0] state, state_next;
integer a, b, c, q, p, r;
integer a_next, b_next, p_next, r_next;
always # (posedge clk, posedge reset)
begin
if (reset == 1)
begin
state <= IDLE;
a <= 0;
b <= 0;
p <= 0;
r <= 0;
end
else
begin
state <= state_next;
a <= a_next;
b <= b_next;
p <= p_next;
r <= r_next;
end
end
always #* //just use the auto-triggered '#*' operator
begin
finished <= 0;
inverse_fail <= 0;
case (state)
IDLE:
begin
a_next <= number;
b_next <= prime;
p_next <= 1;
r_next <= 0;
state_next <= COMPUTING;
end
COMPUTING:
begin
c = a % b;
q = a / b;
a_next = b;
b_next = c;
r_next = p - q * r;
p_next = r;
if (b == 0)
begin
state_next <= END;
end
else
begin
state_next <= COMPUTING;
end
end
END:
begin
gcd <= a;
inverse <= p;
finished <= 1;
if (gcd != 1)
begin
inverse_fail <= 1;
end
end
endcase
end
endmodule
I have written a piece of code that will return a quotient and a reminder, based on numbers that i provide and some other data that i used to shift the numbers in place.
The problem I have now is that i cannot keep a good track of my quotient if I test more values one after another.
I need a way to initialize my cat register, so that I no longer get residual values from previous computations.
Here is the code I was talking about:
module divide(
input [7:0] a, b,
input [3:0] counter, msb,
output reg [7:0] q,
output reg [7:0] r
);
always #(*) begin
for(i = 0; i < counter + 1 ; i = i+1) begin
sum = s_a + s_b; //previously calculated values
if(sum[8-msb] == 1) begin
assign s_a = s_a;
assign s_b = s_b >>> 1;
cat[counter - i] = 1'b0;
end
else begin
assign s_a = sum;
assign s_b = s_b >>> 1;
cat[counter - i] = 1'b1;
end
assign r = s_a;
assign q = cat;
end
end
endmodule
Note: I have declared all the registers that are in this code, but for some purpose I cannot declare them here.
You do not use assign inside always or initial blocks.
The assignments to cat are combinatorial therefore it is not a flip-flop, ie has no reset. The fact that it is a reg type has nothing to do with the hardware but a simulator optimisation.
I would have written it as (no functional alterations made):
module divide#(
parameter DATA_W = 8
)(
input [7:0] a, b,
input [3:0] counter, msb,
output reg [7:0] q,
output reg [7:0] r
);
//Definitions
reg [DATA_W-1:0] sum;
reg [DATA_W-1:0] s_a;
reg [DATA_W-1:0] s_b;
integer i;
always #* begin
for(i = 0; i < (counter + 1); i = i+1) begin
sum = s_a + s_b; //previously calculated values
if(sum[8-msb] == 1'b1) begin
s_a = s_a;
s_b = s_b >>> 1;
cat[counter - i] = 1'b0;
end
else begin
s_a = sum;
s_b = s_b >>> 1;
cat[counter - i] = 1'b1;
end
r = s_a;
q = cat;
end
end
endmodule
You have the following line:
sum = s_a + s_b; //previously calculated values
You have not included any flip-flops here, unless you have implied latches which are really to be avoided, there is no memory or state involved. i.e. there are no previously calculated values.
Instead of a combinatorial block you likely want to add a flip-flop and take multiple clock cycles to calculate the result.
instead of an always #* try:
always #(posedge clk or negedge rst_n) begin
if (~rst_n) begin
s_a <= 'b0; //Reset Value
end
else begin
s_a <= next value; //Normal logic
end
end
I am writing code for an entity that takes in RGB values, averages them, then outputs the altered data.
My code looks like this:
module RGBAVG (
input clk,
input rst_n,
input [9:0] iVGA_R,
input [9:0] iVGA_G,
input [9:0] iVGA_B,
output reg [9:0] oVGA_R,
output reg [9:0] oVGA_G,
output reg [9:0] oVGA_B
);
integer avg;
integer count;
integer sum;
initial begin
count = 0;
sum = 0;
avg = 0;
end
always#(posedge clk or negedge rst_n) begin
if (!rst_n) begin //reset
sum = 0;
count = 0;
oVGA_R <= {10{1'b0}};
oVGA_G <= {10{1'b0}};
oVGA_B <= {10{1'b0}};
end
else begin //get RGB values from pixel, prepare for next avg evaluation
count = (count + 1)%307200; //640*480 = 307200
sum = sum + (iVGA_R + iVGA_G + iVGA_B)/3;
if (count == 0) begin
avg = sum/307200; //update avg
sum = 0;
end
oVGA_R <= avg;
oVGA_G <= avg;
oVGA_B <= avg;
end
end
endmodule
However, when I upload the code, all I get is a black screen. What am I doing wrong?
When you say 'compile', do you mean synthesize for a specific target? Are you trying to simulate this, or load it onto an FPGA?
I cannot say exactly what that error means, though I might make a suggestions that may make it go away.
Your logic is somewhat strange to me and probably not synthesizeable. You have an asynchronous reset to your always block, and you're saying that:
Anytime I assert this asynchronous reset, increment the value of count and sum
This kind of construct does not really exist in typical hardware, your asynchronous reset should do only one thing, which is to reset the state of all your flops. Therefore I recommend to move all this:
count = (count + 1)%307200;
sum = sum + (iVGA_R + iVGA_G + iVGA_B)/3;
if (count == 0) begin
avg = sum/307200;
sum = 0;
end
into the else clause so that it doesn't try to write new register values on asynchronous reset. I suspect that this has something to do with your error. You probably want to reset the count and sum as well on reset, is my guess.
I have problems with this Verilog code. Basically, it won't let me do the Y = 3'di statement. Basically, I want Y to equal i. I am pretty sure the problem is the i. So, is there a way to do this in Verilog? Also, W is an input with 8 bits (in other words, W[7:0]).
for (i = 7; i >= 0; i = i - 1)
begin
if(W[i]) Y=3'di;
end
Thanks.
You can select bits using brackets .
for (i = 7; i >= 0; i = i - 1)
begin
if(W[i]) Y = i[2:0];
end
But it isn't even necessary if i was declared to be an integer. It will take however many bits fit in Y automatically and you only wanted the LSBs.
You might wish to use a case statement here:
case (1'b1)
W[0]: Y=3'd0;
W[1]: Y=3'd1;
W[2]: Y=3'd2;
W[3]: Y=3'd3;
W[4]: Y=3'd4;
W[5]: Y=3'd5;
W[6]: Y=3'd6;
W[7]: Y=3'd7;
default: Y=3'd0; // to avoid inferring a latch when W==8'd0
endcase
This makes the priority more obvious to readers of your code.
I have found that its better to use state machines to do "for-loop" routine.
Something like this:
module yourthing(clk, W, i, Y)
input clk;
input [7:0] W;
output [2:0] Y;
reg [2:0] i;
always#(posedge clk) begin
if(reset) begin
i = 3'd7;
Y = 3'd0;
end
else begin
case(i)
3'd7 : begin
if(W[i]) Y = i;
i = 3'd6;
end
3'd6 : begin
if(W[i]) Y = i;
i = 3'd5;
end
3'd5 : begin
if(W[i]) Y = i;
i = 3'd4;
end
3'd4 : begin
if(W[i]) Y = i;
i = 3'd3;
end
3'd3 : begin
if(W[i]) Y = i;
i = 3'd2;
end
3'd2 : begin
if(W[i]) Y = i;
i = 3'd1;
end
3'd1 : begin
if(W[i]) Y = i;
i = 3'd0;
end
3'd0 : begin
if(W[i]) Y = i;
i = 3'd7;
end
endcase
end
endmodule
Hope this helps...