I'm implementing a repeating bit shifter for a 16 bit number. To do this, I have a bit counter that counts how many times I've shifted and resets when I reach 4'b1111. Then I have an assign statement that feeds the MSB to an output. However, the logic makes it so that the output skips the first MSB every time. What is the most succinct way to include the first MSB, before any shifting has occurred?
CODE
module DAC_Control(
input [15:0]data_in,
input clk,
input rst,
output data_out,
output reg cs,
output reg enable
);
//bit counter
reg [3:0] bit_counter;
//to help with shifting
reg [15:0] shifter;
always #(data_in)
shifter <= data_in;
//shifter
always #(posedge (clk)) begin
if (rst) begin
bit_counter <= 4'b0;
enable <= 1'b0;
cs <= 1'b1;
end
else if (bit_counter == 4'b1111) begin
bit_counter <= 4'b0;
enable <= 1'b1;
cs <= 1'b1;
end
else begin //this is the problem area
bit_counter <= bit_counter + 1'b1;
enable <= 1'b0;
cs <= 1'b0;
shifter <= shifter << 1;
end
end
assign data_out = shifter[15];
endmodule
Firstly it would be better to have a trigger to capture the data_in. If not then in simulation ,if the data_in changes in between the shifting it will update the shifter and cause the expected output to change. It would be preferable to capture the data_in based on a qualifying event ( e.g. counter_enable in the example below) . Synthesis will produce an error as shifter has two drivers . One the continuous assignment shifter <= data_in; and other the shifting logic shifter <= shifter << 1;
Updated sample code should serialize the data.
module DAC_Control(
input [15:0]data_in,
input counter_enable,
input clk,
input rst,
output data_out,
output reg cs,
output reg enable
);
//bit counter
reg [3:0] bit_counter;
//to help with shifting
reg [15:0] shifter;
//shifter
always #(posedge (clk)) begin
if (rst) begin
bit_counter <= 4'b0;
shifter <= 0;
end
else if (counter_enable == 1) begin
shifter <= data_in;
bit_counter <= 4'b0;
end
else begin
shifter <= shifter << 1; // shifting
bit_counter <= bit_counter + 1'b1; // counter
end
end
always #(posedge (clk)) begin
if (rst) begin
enable <= 1'b0;
cs <= 1'b1;
end
else if (bit_counter == 4'b1111) begin
enable <= 1'b1;
cs <= 1'b1;
end
else begin
enable <= 1'b0; // generate enable signals
cs <= 1'b0;
end
end
assign data_out = shifter[15];
endmodule
Related
The monostable module implements a monostable multivibrator. It takes in three inputs (clk, reset, trigger) and outputs a single (pulse).
The trigger input triggers the module. When triggered, the output signal (pulse) will switch to a high position for a period of clock ticks, and then return to a low position. The pulse width of the output signal can be set via the PULSE_WIDTH parameter, which represents the period in clock ticks that the signal should stay high.
Now, what is happening is when it gets triggered, immediately output signal (pulse) is getting high.
When triggered, the output signal (pulse) should be high on the next active edge of clk. What changes can be done ?
module monostable(
input clk,
input reset,
input trigger,
output reg pulse = 0
);
parameter PULSE_WIDTH = 20;
reg [4:0] count = 0;
wire countReset = reset | (count == PULSE_WIDTH);
always #(posedge trigger, posedge countReset) begin
if (countReset) begin
pulse <= 1'b0;
end else begin
pulse <= 1'b1;
end
end
always #(posedge clk, posedge countReset) begin
if(countReset) begin
count <= 0;
end else begin
if(pulse) begin
count <= count + 1'b1;
end
end
end
endmodule
module monostable_tb();
reg clk;
reg reset;
reg trigger;
wire pulse;
parameter PULSE_WIDTH = 20;
monostable imonostable(.*);
initial begin
clk=0;
forever #50 clk=~clk;
end
initial begin
$monitor("trigger=%b pulse=%b, count = %0d",trigger,pulse,imonostable.count);
$dumpfile("monostable_tb.vcd");
$dumpvars(0,monostable_tb);
trigger=1'b0;
reset = 1'b0;
#(posedge clk) reset = 1'b1;
#(posedge clk) reset = 1'b0;
#(posedge clk) trigger=1'b1;
#(posedge clk) trigger=1'b0;
repeat(25) #(posedge clk);
$finish;
end
endmodule
Here is a simplified design which sets the output one cycle after the input trigger pulse, and keeps the output high for 20 cycles:
module monostable(
input clk,
input reset,
input trigger,
output reg pulse = 0
);
parameter PULSE_WIDTH = 20;
reg [4:0] count;
always #(posedge clk, posedge reset) begin
if (reset) begin
pulse <= 1'b0;
end else if (trigger) begin
pulse <= 1'b1;
end else if (count == PULSE_WIDTH-1) begin
pulse <= 1'b0;
end
end
always #(posedge clk, posedge reset) begin
if(reset) begin
count <= 0;
end else if (pulse) begin
count <= count + 1'b1;
end
end
endmodule
It now uses a single clock signal, instead of 2. It also uses a simple reset signal, which can avoid potential glitches causing unwanted asynchronous resets.
You should also use nonblocking assignments in the testbench:
#(posedge clk) reset <= 1'b1;
#(posedge clk) reset <= 1'b0;
#(posedge clk) trigger<= 1'b1;
#(posedge clk) trigger<= 1'b0;
If a 1-clock synchronous delay is needed, then run the output thru a flip flop.
module monostable(
input clk,
input reset,
input trigger,
output reg pulse = 0
);
parameter PULSE_WIDTH = 20;
reg [4:0] count = 0;
reg reg_pulse_temp;
wire countReset = reset | (count == PULSE_WIDTH);
always #(posedge trigger, posedge countReset) begin
if (countReset) begin
reg_pulse_temp <= 1'b0;
end else begin
reg_pulse_temp <= 1'b1;
end
end
always #(posedge clk, posedge countReset) begin
if(countReset) begin
count <= 0;
// reset the flop
pulse <= 0;
end else begin
if(pulse) begin
count <= count + 1'b1;
end
end
// flip flop
pulse <= reg_pulse_temp;
end
endmodule
I am looking to create an AND gate which gets the result after a delay of lets say 10ns an my clock is 500 ps. How will i delay the assignment without using # delays ?
I have tried to make a counter which increments but how to model it so that it only starts when my input changes. Also the input won't change till the first output is evaluated and assigned. Initial Counter is 0 and lets say delay is 3'b111 so i want the counter to go from 1 to 3'b111 and then assign it to y. Inputs are a and b to the and gate.
always#(posedge clk)begin
if (!reset) begin y <=0; counter <=0; end
else begin
counter <= counter +1'b1;
if(counter==delay)begin
y <= a & b;
counter <=0;
end
end
Well if your clock cycle is 500 ps then you will need to count to a higher value to reach 10ns. I rewrote your code and also added a testbench for you to try. It's kind of sloppy, I usually write vhdl and not verilog. Hope this helps.
//Module
module count_and (
input clk,
input reset,
input a,
input b,
output reg y,
output reg [4:0] counter
);
reg ready;
always#(posedge clk)begin
if (!reset) begin
y <=0;
counter <=0;
ready <= 0;
end
else if (ready == 1'b1) begin
counter <= counter +1'b1;
if (counter==5'b10011) begin
y <= a & b;
counter <=0;
ready <= 0; //turn it off after passing to y
end
end
end
always #(a,b) begin
ready <= 1'b1;
end
endmodule
//TestBench
`timescale 1ps/1ps
module tb_count ();
reg a,b;
reg clk;
reg reset;
wire [4:0] counter;
wire y;
initial begin
clk = 1'b1;
reset = 1'b0;
a = 1'b0;
b = 1'b0;
end
always begin
reset <= #50 1'b1;
clk = #250 ~clk;
a <= #1000 1'b1;
b <= #1000 1'b1;
end
count_and count_and_inst (
.clk(clk),
.reset(reset),
.a(a),
.b(b),
.y(y),
.counter(counter)
);
endmodule
I am trying to learn valid/ready handshake in verilog. In particular, I am interested to use ready as a flag that indicates the successful transaction of data (i.e., ready_in becomes high after valid_out goes high). I would like to explain my problem using a very simple Verilog example. I have written a convolutional encoder (code below)
module Conv_Encoder_Core(
input wire clk,
input wire reset,
input wire in_bit,
output reg out_A,
output reg out_B,
input wire sleep,
input wire valid_in,
input wire ready_in,
output reg valid_out,
output reg ready_out);
reg [5:0] S;
wire S_A, S_B, clkON;
assign S_A = S[1] ^ S[2] ^ S[4] ^S[5];
assign S_B = S[0] ^ S[1] ^ S[2] ^S[5];
assign clkON = clk & !sleep;
always #(posedge clkON)begin
if (reset) begin
S <=0;
valid_out <=0;
ready_out <=0;
end else if (valid_in) begin
out_A <= in_bit ^ S_A;
out_B <= in_bit ^ S_B;
valid_out <=1;
if (ready_in)begin
S<= S<<1;
S[0] <=in_bit;
ready_out <=1;
end else begin
ready_out <=0;
end
end else begin
valid_out <=0;
ready_out <=0;
end
end
endmodule
I am interested to use ready_in flag as an indicator that data out_A and out_B are received by the next block, so my block can accept the new data by setting ready_out flag high. I have written a testbench for this block, however, I am not getting the results I am expecting
`timescale 1 ns/1 ns
module TB_Conv();
reg clk;
//---------------clock generator-----------------------
initial begin
clk = 1'b0;
#5;
clk = 1'b1;
forever begin
#5 clk = ~clk;
end
end
//------------------ dump -----------------------
initial begin
$dumpfile("dumpVCD.vcd");
$dumpvars(10);
end
localparam N_DATA=10;
reg in_bits_vec [0:N_DATA-1];
initial begin
in_bits_vec[0] = 1'b1;
in_bits_vec[1] = 1'b0;
in_bits_vec[2] = 1'b0;
in_bits_vec[3] = 1'b0;
in_bits_vec[4] = 1'b0;
in_bits_vec[5] = 1'b0;
in_bits_vec[6] = 1'b0;
in_bits_vec[7] = 1'b0;
in_bits_vec[8] = 1'b0;
in_bits_vec[9] = 1'b1;
end
reg in_bit, ready_in,reset, valid_in;
Conv_Encoder_Core UUT(.clk(clk),
.reset(reset),
.in_bit(in_bit),
.out_A(out_A),
.out_B(out_B),
.sleep(1'b0),
.valid_in(valid_in),
.ready_in(ready_in),
.valid_out(valid_out),
.ready_out(ready_out));
//---------------- code starts here -------------------//
reg [3:0] addr;
always #(posedge clk) begin
if (reset)begin
addr<=0;
valid_in <=0;
in_bit <=0;
end else if (addr < 10) begin
in_bit <= in_bits_vec[addr];
valid_in <=1'b1;
if (ready_out) begin
addr <= addr+1'b1;
end
end else begin
in_bit <=0;
valid_in <=0;
end
if (valid_out==1) ready_in <= 1;
else ready_in <= 0;
end
// ----------- reset logic -----------//
reg [3:0] cnt;
initial cnt=0;
always #(negedge clk)begin
if (cnt<5) begin
reset = 1;
cnt=cnt+1;
end else reset =0;
end
initial begin
#1000;
$finish;
end
endmodule
if you look at the input data (in the testbech), you can see it is 1000000000. I am expecting to see 1 being passed through S register as follows:
S = 000000 //at beginning
S = 000001 // after ready_out=1
S = 000010
S = 000100
however, the results I get is entirely different(please see snapshot).
Another problem I have is that inbit=1 continues two clock cycles more than what I expect. in fact when ready_out=1, I expect to see that in_bit becomes zero but this happens two clock cycles later(yellow cursor in the snapshot ).
I would be most grateful if someone could explain what I do wrong in this example.
Conv_Encoder_Core
module Conv_Encoder_Core
(
input wire clk,
input wire reset,
input wire in_bit,
output reg out_A,
output reg out_B,
input wire sleep,
// input channel
input wire inp_valid_i,
output wire inp_ready_o,
// output channel
output reg out_valid_o,
input reg out_ready_i
);
reg [5:0] S;
wire S_A, S_B, clkON;
assign S_A = S[1] ^ S[2] ^ S[4] ^S[5];
assign S_B = S[0] ^ S[1] ^ S[2] ^S[5];
assign clkON = clk & !sleep;
// -- Changes start here -- //
wire wr_en;
reg full_r;
assign wr_en = ~full_r | out_ready_i;
always #(posedge clkON)begin
if (reset) begin
S <=0;
full_r <=0;
end else begin
if (wr_en) begin
if (inp_valid_i) begin
full_r <= 1;
out_A <= in_bit ^ S_A;
out_B <= in_bit ^ S_B;
S <= S<<1;
S[0] <=in_bit;
end else begin
full_r <= 0;
end
end
end
end
assign inp_ready_o = wr_en;
assign out_valid_o = full_r;
endmodule
tb
`timescale 1 ns/1 ns
module tb();
reg clk;
//---------------clock generator-----------------------
initial begin
clk = 1'b0;
#5;
clk = 1'b1;
forever begin
#5 clk = ~clk;
end
end
//------------------ dump -----------------------
initial begin
$dumpfile("dumpVCD.vcd");
$dumpvars(10);
end
localparam N_DATA=10;
reg in_bits_vec [0:N_DATA-1];
initial begin
in_bits_vec[0] = 1'b1;
in_bits_vec[1] = 1'b0;
in_bits_vec[2] = 1'b0;
in_bits_vec[3] = 1'b0;
in_bits_vec[4] = 1'b0;
in_bits_vec[5] = 1'b0;
in_bits_vec[6] = 1'b0;
in_bits_vec[7] = 1'b0;
in_bits_vec[8] = 1'b0;
in_bits_vec[9] = 1'b1;
end
reg in_bit, reset, inp_valid, inp_ready, out_valid, out_ready;
Conv_Encoder_Core UUT(.clk(clk),
.reset(reset),
.in_bit(in_bit),
.out_A(out_A),
.out_B(out_B),
.sleep(1'b0),
// input channel
.inp_valid_i(inp_valid),
.inp_ready_o(inp_ready),
// output channel
.out_valid_o(out_valid),
.out_ready_i(out_ready));
//---------------- code starts here -------------------//
reg [3:0] addr;
// -- Transmitter Side -- //
always #(posedge clk) begin: ff_addr
if (reset)begin
addr <= 0;
end else begin
if (addr < 10) begin
if (inp_valid && inp_ready) begin
addr <= addr + 1;
end
end else begin
addr <= 0;
end
end
end
assign inp_valid = (addr < 10) ? 1'b1 : 1'b0;
assign in_bit = in_bits_vec[addr];
// -- Receiver Side -- //
always #(posedge clk) begin: ff_ready_in
if (reset) begin
out_ready <= 0;
end else begin
out_ready <= $urandom_range(0, 1); // some randomness on the receiver, otherwise, we won't see if our DUT behaves correctly in case of ready=0
end
end
// ----------- reset logic -----------//
reg [3:0] cnt;
initial cnt=0;
always #(negedge clk)begin
if (cnt<5) begin
reset = 1;
cnt=cnt+1;
end else reset =0;
end
initial begin
#1000;
$finish;
end
endmodule
Issues with your implementation
Bad protocol definition & implementation
You are defining a protocol that looks more like "request/acknowledge" than "ready/valid" one, because data transmissions in your protocol are acknowledged after a one-cycle delay. What you need is concurrent transmission acknowledge in the same cycle, something like the following:
A valid data transmission is indicated by the Transmitter through valid=1 and are acknowledged by the Receiver through ready=1. So, a data transmission is valid only when valid && ready in the same cycle. Note that input data is equivalent to in_bit in your case, while output data is out_A and out_B.
Input/Output ready/valid channel confusion
If you add a processing/buffering unit between the Transmitter and the Receiver of the above channel, then what you got is something like this:
In that case, your buffer is the Conv_Encoder_Core module and, apart from its internal core logic, it must expose an input ready/valid channel, from which it receives input data, and an output one, from which it outputs its data. Also note that the Transmitter and the Receiver, are implemented by the testbench code (tb module). See
"Transmitter Side" and "Receiver Side" comments in code.
wanted to implement PWM sequence using top-level verilog 2005 module:
module PWM_ENHANCER (
input clk,
input rst,
input sent,
//input
input [7:0] BUF, //BUFFER - The PWM reads from it only when 'sent' signal is received, and the current run is done.
//output
output reg PWM_WAIT,
output reg PWM_OUT
);
reg [7:0] SAMPLE;
reg [7:0] counter;
reg WORK;
always#(posedge clk or negedge rst)
begin
if( !rst )
begin
WORK <= 1'b0; //When receiving a reset, everything zeroes.
counter <= 8'b0;
PWM_WAIT <= 1'b1;
SAMPLE <= 8'b0;
PWM_OUT <= 1'b0;
end
else if (sent == 1 && WORK == 0)
begin //If the pwm was OFF, and i received sign from the array, i start running PWM.
SAMPLE <= BUF;
WORK <= 1'b1;
PWM_WAIT <= 1'b0;
end
else if(WORK == 1)
begin //The running block - sending '0' and '1' as needed.
if ( (counter <= SAMPLE) && (SAMPLE != 0) )
begin
PWM_OUT <= 1'b1;
counter = counter + 1'b1;
end
else if ( counter > SAMPLE )
begin
if ( counter == 8'b11111111 )
begin
counter <= 8'b0;
WORK <= 1'b0;
end
else
begin
counter = counter + 1'b1;
PWM_OUT <= 1'b0;
end
end;
if(counter == 200)
begin // 50 cycles before the end, PWM sends acknowledge for the array to send the next sample.
PWM_WAIT <= 1'b1;
end
end
else
begin
; // if NOT receiving 'sent' from the array - the PWM does nothing.
end
end
endmodule
received error when compiling:
"Internally generated reset in top design unit 'PWM_ENHANCER' is not allowed."
How can i have a reset included in the #always statement?
Two possibility (both synthesis related):
Your synthesizer needs additional hand-holding for the asynchronous reset
if(!rst) begin
WORK <= 1'b0;
counter <= 8'b0;
PWM_WAIT <= 1'b1;
SAMPLE <= 8'b0;
PWM_OUT <= 1'b0;
end
else begin
// other logic in here
end
Your standard cell library lacks flops with asynchronous reset/preset. FPGA's tend to have a limited number of flops with asynchronous reset/preset. Some FPGA do not have any. If this is the case the simplest thing that can be done is change the for asynchronous reset to synchronous reset by changing the top of your always block to always#(posedge clk) (omitting the or negedge rst).
If you are on FPGA, then you may want to add an initial block to initialize the defaults of the registers.
i'm a verilog beginner, i'm try to write a "event counter" on verilog.... this is my code, but it work only with "period" set to 16'b0000000000000001, if try set period to 16'b0000000000001000, result(out_event) is always '0'.
Someone can help me to fix it ?
module mymodule(
input wire clk,
input wire enable,
input wire reset,
input wire [15:0] period,
input wire in_event,
output reg out_event
);
reg en = 1'b0;
reg re = 1'b0;
reg [15:0] count = 16'b0000000000000000;
always #(posedge clk) en <= enable;
always #(posedge clk) re <= reset;
always #(in_event)begin
if(in_event == 1'b1)begin
if(re)begin
count <= 0 ;
out_event <= 1'b0;
end else begin
if(en) begin
if(count == period-1)begin
out_event <= 1'b1;
count <= 0;
end else begin
count <=count + 1;
out_event <= 1'b0;
end
end else begin
out_event <= 1'b0;
end
end
end else begin
out_event <= 1'b0;
end
end
endmodule
thanks in advance
The counter counts number of posedge of in_event wire. So, can you use #(posedge in_event)?
I simulated your code, providing a testbench to it.
I do not have much knowledge about hardware synthesis, but personally, I would suggest to write your logic based on edge/level of clock.
This code works completely well. Have a look at this link.
You can configure various values of period in testbench, hope this will be helpful.
I came up with a test bench and the design for your problem and it works.
`timescale 1s / 1s
module TB();
reg clk;
reg enable;
reg reset;
reg [15:0] period;
wire out_event;
wire [15:0] counter;
initial begin
clk = 1'b0;
forever begin
#1 clk = ~clk;
end
end
stack_exch_code test (.clk(clk),
.enable(enable),
.reset(reset),
.period(period),
.out_event(out_event),
.tb_counter(counter)
);
integer i;
initial
begin
#(negedge clk) reset = 1'b1; enable = 1'b0; period = 16'h0000;
#(negedge clk) reset = 1'b0; enable = 1'b1; period = 16'h00FF;
for (i = 0 ; i < 500 ; i = i + 1) begin
#(negedge clk) period = period - 1;
#(posedge clk) $display ("Period = %h , Counter = %h, Out_Event = %b ", period, counter, out_event);
end
#(negedge clk) $finish;
end
endmodule //TB
module stack_exch_code (input clk,
input enable,
input reset,
input [15:0] period,
//input inevent,
output reg out_event,
output [15:0] tb_counter
);
// initialization doesnt matter in hardware, its not C or C++
reg en;
reg re;
reg [15:0] count;
always # (posedge clk) begin
re <= reset;
en <= enable;
end
always # (posedge clk) begin
if (re) begin
count <= 16'h0000;
out_event <= 1'b0;
end
else if (en) begin
if ((count == period - 1) && !(period == 16'h0000)) begin
out_event <= 1'b1;
count <= 16'h0000;
end
else if (!(period == 16'h0000)) begin
count <= count + 1;
out_event <= 1'b0;
end
else if (period == 16'h0000)
out_event <= 1'b0;
end
end
assign tb_counter = count;
endmodule //stack_exch_code