I have instantiated a stopwatch module into this multiplexer module. The stopwatch is working as it is supposed to and is producing the expected output. This is also picked up by the instantiated registers. But, if I want to use this data further down the module, it does not work.
Here is the simulation showing my problem:
The values picked up from the stopwatch module are working perfectly. These values are then transferred to the registers regd0, regd1, regd2, regd3 which, instead of displaying the values are displaying 0?
Here is the code that produced the above simulation:
module muxer(
input clock,
input reset,
input [1:0] select,
output a,
output b,
output c,
output d,
output e,
output f,
output g,
output dp,
output [3:0] an
);
reg go_hi, go_start;
wire[3:0] wire_d0, wire_d1, wire_d2, wire_d3; // timer registers that will hold the individual counts
wire[3:0] wire_hd0, wire_hd1, wire_hd2, wire_hd3; //regsiters to hold the "hi" values
reg [3:0] regd0, regd1, regd2, regd3; //registers for LED multiplexing
//instantiate the "hi" module
say_hi sayhi(.clock(clock), .reset(reset), .go(go_hi), .hi_d0(wire_hd0), .hi_d1(wire_hd1), .hi_d2(wire_hd2), .hi_d3(wire_hd3)) ;
//instantiate the stopwatch module
stopwatch timer(.clock(clock), .reset(reset), .start(go_start), .d0(wire_d0), .d1(wire_d1), .d2(wire_d2), .d3(wire_d3) );
always # (select)
begin
case(select)
00: //hi
begin
go_start = 0; //make sure timer module is off
go_hi = 1'b1; //enable go signal to display "hi"
regd0 = wire_hd0; //transfer values to the multiplexing circuit
regd1 = wire_hd1;
regd2 = wire_hd2;
regd3 = wire_hd3;
end
01: //timer
begin
go_hi = 0; //make sure "hi" module is off
go_start = 1'b1; //enable start signal to start timer
regd0 = wire_d0;
regd1 = wire_d1;
regd2 = wire_d2;
regd3 = wire_d3;
end
10: //stop timer
begin
go_hi = 0;
go_start = 1'b0;
end
endcase
end
//The Circuit for 7 Segment Multiplexing -
localparam N = 8; //18 for implementation, 8 for simulation
reg [N-1:0]count;
always # (posedge clock or posedge reset)
begin
if (reset)
count <= 0;
else
count <= count + 1;
end
reg [6:0]sseg;
reg [3:0]an_temp;
reg reg_dp;
always # (*)
begin
case(count[N-1:N-2])
2'b00 :
begin
sseg = regd0;
an_temp = 4'b1110;
reg_dp = 1'b1;
end
2'b01:
begin
sseg = regd1;
an_temp = 4'b1101;
reg_dp = 1'b0;
end
2'b10:
begin
sseg = regd2;
an_temp = 4'b1011;
reg_dp = 1'b1;
end
2'b11:
begin
sseg = regd3;
an_temp = 4'b0111;
reg_dp = 1'b0;
end
endcase
end
assign an = an_temp;
reg [6:0] sseg_temp;
always # (*)
begin
case(sseg)
4'd0 : sseg_temp = 7'b1000000; //display 0
4'd1 : sseg_temp = 7'b1111001; //display 1
4'd2 : sseg_temp = 7'b0100100;// display 2
4'd3 : sseg_temp = 7'b0110000;
4'd4 : sseg_temp = 7'b0011001;
4'd5 : sseg_temp = 7'b0010010;
4'd6 : sseg_temp = 7'b0000010;
4'd7 : sseg_temp = 7'b1111000;
4'd8 : sseg_temp = 7'b0000000;
4'd9 : sseg_temp = 7'b0010000;
4'd10 : sseg_temp = 7'b0001001; //to display H
4'd11 : sseg_temp = 7'b0000111; //to display I
default : sseg_temp = 7'b0111111; //dash
endcase
end
assign {g, f, e, d, c, b, a} = sseg_temp;
assign dp = reg_dp;
endmodule
My guess is that select does not equal 01. You should show that in waves as well.
Here are a couple of other observations.
If you want regd0 to model combinational logic, you should change always #(select) to always #*. Same for d1-d3. Currently, I think you are modeling latches.
In your case statement 10 refers to decimal 10. You probably wanted 2'b10.
Related
So I'm trying to instantiate a module within a module. The root module has output ports that drive the output pins and I want the inner module to drive those ports directly but I can't get it work anyway round.
/*
A root module for the 005_135-scanner_mainboard_revA_sch-pcb. Can be used as a test bench for testing peripheral devices but has been designed to be the master root module for the final code.
All IO is included and reset pins on peripheral devices driven active reset with data lines driven to an appropriate value (located in the ‘initial block’).
George Waller. 09/08/15.
*/
module root_module( ft_reset, ft_usb_prsnt, ft_bus_pwrsav, ft_bus_oe, ft_bus_clkout, ft_bus_siwu, ft_bus_wr, ft_bus_rd, ft_bus_rxf, ft_bus_txe, ft_bus_d,
mtr_fault, mtr_config, mtr_m1, mtr_m0, mtr_rst, mtr_out_en, mtr_step, mtr_dir,
ccd_driver_oe, ccd_p1, ccd_p2, ccd_cp, ccd_rs, ccd_sh,
dac1_sdin, dac1_sclk, dac1_sync, dac2_sdin, dac2_sclk, dac2_sync,
adc_pwrdn, adc_encode, adc_d,
fpga_reset,
clk,
gpio,
led_ctrl,
leds);
//Input declarations
input wire ft_usb_prsnt, ft_bus_clkout, ft_bus_rxf, ft_bus_txe,
mtr_fault,
fpga_reset,
clk;
input wire [7:0] adc_d;
//Output declarations
output reg ft_reset, ft_bus_pwrsav, ft_bus_oe, ft_bus_siwu, ft_bus_wr, ft_bus_rd,
mtr_config, mtr_m1, mtr_m0, mtr_rst, mtr_out_en, mtr_step, mtr_dir,
ccd_driver_oe, ccd_p1, ccd_p2, ccd_cp, ccd_rs, ccd_sh,
adc_pwrdn, adc_encode,
led_ctrl;
output reg dac1_sdin, dac1_sclk, dac1_sync, dac2_sdin, dac2_sclk, dac2_sync;
output reg [7:0] leds;
//Input output declarations.
inout reg [7:0] ft_bus_d;
inout reg [16:0] gpio;
//Variables go here
integer count, count1, state, pixel_n, line_n, t_int;
integer data[8];
reg en;
//Initial values on start up.
initial
begin
//IO initial setup values.
ft_reset = 1; ft_bus_pwrsav = 1; ft_bus_oe = 1; ft_bus_siwu = 0; ft_bus_wr = 1; ft_bus_rd = 1; //NEED TO APPLY REAL VAULES!!!
mtr_config = 1; mtr_m1 = 1; mtr_m0 = 1; mtr_rst = 1; mtr_out_en = 1; mtr_step = 0; mtr_dir = 0;
ccd_driver_oe = 1; ccd_p1 = 0; ccd_p2 = 0; ccd_cp = 0; ccd_rs = 0; ccd_sh = 0;
dac1_sdin = 0; dac1_sclk = 0; dac1_sync = 0; dac2_sdin = 0; dac2_sclk = 0; dac2_sync = 0;
adc_pwrdn = 0; adc_encode = 0;
led_ctrl = 0;
leds = 0;
gpio = 0;
ft_bus_d = 0;
//Variables setup values.
count = 0;
count1 = 0;
state = 0;
pixel_n = 0;
line_n = 0;
t_int = 10000; //t_int = integration time. integration time (seconds) = t_int * 10x10^-9.
end //End initial
//Some other code goes here.
always #(posedge ft_bus_clkout)
begin
if(count == 50000000)
begin
en <= 1;
count = 0;
end
else
begin
en <= 0;
count = count + 1;
end
end //End always
AD5601_module AD5601(.en(en), .clk(clk), .data(127),.sdout(dac1_sdin),
.sclk(dac1_sclk), .sync(dac1_sync));
endmodule //End module.
And the inner module:
module AD5601_module(en, clk, data, sdout, sclk, sync);
input wire clk;
input wire en;
input wire [7:0] data;
output reg sdout, sclk, sync;
integer sclk_count;
integer data_state;
integer delay_counter;
integer pd[2];
initial
begin
sclk_count = 0;
data_state = 99;
delay_counter = 0;
pd[0] = 0;
pd[1] = 0;
sdout = 0;
sclk = 0;
sync = 1;
end
always # (posedge en)
begin
if(data_state == 99)data_state <= 0;
end
always # (posedge clk)
begin
if(sclk_count == 49)
begin
sclk_count = 0;
sclk = ~sclk;
end
else sclk_count = sclk_count + 1;
end
always # (posedge sclk)
begin
case(data_state)
0: begin
sync = 0;
sdout <= pd[1];
data_state <= 1;
end
1: begin
sdout <= pd[0];
data_state <= 2;
end
2: begin
sdout <= data[7];
data_state <= 3;
end
3: begin
sdout <= data[6];
data_state <= 4;
end
4: begin
sdout <= data[5];
data_state <= 5;
end
5: begin
sdout <= data[4];
data_state <= 6;
end
6: begin
sdout <= data[3];
data_state <= 7;
end
7: begin
sdout <= data[2];
data_state <= 8;
end
8: begin
sdout <= data[1];
data_state <= 9;
end
10:begin
sdout <= 0;
if(delay_counter == 6)
begin
data_state <= 99;
delay_counter <= 0;
sync = 1;
end
else delay_counter = delay_counter + 1;
end
endcase
end
endmodule
So with the code as is I get the error
'output or inout port should be connected to a structural net
expression'
.
If I change the outputs in the root module or the inner module to wire I get the error 'the expression on the left hand side should be of a variable type'.
So at this point I have no idea how you nest outputs! Some help would be appreciated!
Thanks
inout ports should be a net type (wire or tri) and not a reg. A reg does not have conflict resolution (when there are two or more active driver). An inout should not be assigned in a procedural block (e.g. always-block, initial-block). It should be a simple assign statement as below. The designer must ensure there is only on active driver on the IO at any point.
assign io_port_name = driver_enable ? io_out_value : 'bz; // io_out_value should be a flop
An output should only be declared an output reg if it is assigned in a procedural block (e.g. always-block, initial-block) within the current module. All other outputs should be output or output wire (these identifiers are synonymous; the former is implicit while the latter is explicit). An should only be assigned within one always. FPGAs allow initial blocks, ASIC/IC does not.
If SystemVerilog is enabled, replace output reg with output logic. logic can be used for flops and single directional nets. logic is not recommended for inout; logic like reg does not have conflict resolution.
The arrays integer data[8]; and integer pd[2]; are SystemVerilog syntax and not compatible with Verilog. Either enable SystemVerilog or change to integer data[0:7]; and integer pd[0:1];
SystemVerilog can be enabled per file by changing the file extension from .v to .sv; recommended. Simulators/synthesizers typically have a switch to force all Verilog to be treated as SystemVerilog; not recommended, refer to the simulator/synthesizer manual if desired to go this route.
i'm beginner in verilog and digital circuits, and i have one doubt in the code below. In this code i made a state machine that saves values in a "reg" into another module in verilog. I made this code just to explain my doubt:
//STATE MACHINE
module RegTest(clk,enable,reset, readData1_out);
parameter State1 = 0;
parameter State2 = 1;
parameter State3 = 2;
parameter State4 = 3;
parameter State5 = 4;
parameter State6 = 5;
parameter State7 = 6;
parameter State8 = 7;
parameter State9 = 8;
parameter State10 = 9;
parameter Beg = 10;
input clk, enable, reset;
output readData1_out;
wire clk,enable, reset;
reg[5:0] State;
reg writeEn ;
reg [15:0] writeData;
wire [15:0] readData1;
wire writeEn_out = writeEn;
RegFile registrador_component (
.dataIn(writeData),
.dataOut(readData1),
.clock(clk),
.writeEnable(writeEn)
);
defparam
registrador_component.WIDTH = 16;
always #(posedge clk or posedge reset) begin
if (reset)
begin
State = Beg;
end else begin
case (State)
Beg:
begin
State = State1;
end
State1:
begin
writeEn = 1 ;
writeData = 10;
State = State2;
end
State2:
begin
writeEn = 0 ;
State = State3;
end
State3:
begin
writeEn = 1;
writeData = readData1 + 10;
State = State4;
end
State4:
begin
writeEn = 0 ;
State = State5;
end
State5:
begin
writeEn = 1 ;
writeData = readData1 + 10;
State = State6;
end
State6:
begin
writeEn = 0 ;
State = State7;
end
State7:
begin
writeEn = 1 ;
writeData = readData1 + 10;
State = State8;
end
State8:
begin
writeEn = 0 ;
State = State9;
end
endcase
end
end
endmodule
//Example of a register file
module RegFile(clock, writeEnable, dataIn, dataOut);
parameter WIDTH = 16;
input clock, writeEnable;
input [WIDTH-1 : 0] dataIn;
output [WIDTH-1 : 0] dataOut;
wire [WIDTH-1 : 0] dataOut;
reg [WIDTH-1 : 0] wha;
assign dataOut = wha;
always#( posedge clock)
begin
if (writeEnable)
wha = dataIn;
end
endmodule
My doubt is, why do I need to wait 1 cycle to get the value that is stored in RegFile?
Why can't I skip the State2 for example?
You do in fact have 2 clock cycles of delay in the code you wrote above. It would help if you simulated this so you can see it for yourself, but I'll describe it.
On the first cycle, WriteEnable goes high. It takes 1 full clock cycle to be valid to other parts of the logic. So after the first clock cycle is done, WriteEnable will be available for use elsewhere.
On the second cycle, your regFile module can "see" the fact that WriteEnable went high previously. It then will put dataIn into wha signal, which gets passed to dataOut. So after the second clock cycle is done, dataOut will be available for use elsewhere. (It gets used on the third clock cycle in State 3).
This is why you need to go to state 2. State 2 allows for the 1 extra clock cycle needed for RegFile to register the output data.
Clock cycle delay is an extremely important concept to understand, so it's good that you're putting in the time when you are still new to fully grasp it.
For more information see this tutorial here, it explains registers and clock cycle delay and will be useful for you.
Clock Cycle Delays and Registered Logic
Can anyone help me create a testbench or just the input code for my following code? I'm using XILINX.
module fsmb (input rst,clk,a,
output reg x);
parameter sta = 2'b00, stb = 2'b01, stc = 2'b10,
std = 2'b11;
reg[1:0] st, nst;
always #(posedge clk)
begin
if (rst)
st <= 2'b00;
else
st <= nst;
end
always #*
begin
st = nst; x =0'b0;
case (st)
sta: if(a) nst = stb;
else nst = sta;
stb: if(a) nst = stc;
else nst = stb;
stc: begin
if(a) nst = stc;
else nst = std;
x =1'b1;
end
std: begin
if(a) nst = stc;
else nst = sta;
x = 1'b1;
end
default: nst = sta;
endcase
end
endmodule
Testbench 101
Create a new module (tb).
Create a reg for each input of your DUT.
Create a wire for each output of your DUT.
Create an instance of your DUT.
Connect your regs and wires to your DUT.
Generate a clock
Drive your other inputs
Create checkers for your outputs (I'll leave this up to you).
Example:
module tb;
reg rst,clk,a;
wire x;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
rst = 1;
a = 0;
#50 rst = 0;
#50 $finish;
end
fsmb fsmb (
.clk (clk),
.rst (rst),
.a (a),
.x (x)
);
endmodule
Other simple testbench examples are provided on EDA playgound. You can sign up for a free account and look at samples such as: Published Playgounds -> D flip flop
Xilinx ISE will generate a skeleton test fixture automatically. Go to menu item Project->New Source. The dialog box will ask you to "Select Source Type" click "Verilog Test Fixture" and give it a name like testbench1 and click Next. Then it will then ask you which module in your project to associate with it. Select fsmb. Click Next and Finish.
You still have to tweak the testbench like setting the initial input values, generating a clock, and lifting reset after a few clocks.
I have a analogue to digital converter that after conversion stores its results in two 14 bit registers. I have to display this value onto a 2 digit 7 segment display.
Here is the simulation showing the 14 bit result:
As can be seen the values are quite large for a 2 digit display. I can display these values to a one tenth of a volt. Here is the display multiplexing circuit:
module muxer(
input clock,
input reset,
input [3:0] second,
input [3:0] first,
output a_m,
output b_m,
output c_m,
output d_m,
output e_m,
output f_m,
output g_m,
output [1:0] cat_m
);
//The Circuit for 7 Segment Multiplexing -
localparam N = 18;
reg [N-1:0]count; //the 18 bit counter which allows us to multiplex at 1000Hz
always # (posedge clock)
begin
if (reset)
count <= 0;
else
count <= count + 1;
end
reg [3:0]sseg; //the 4 bit register to hold the data that is to be output
reg [1:0]cat_temp; //register for the 2 bit enable
always # (*)
begin
case(count[N-1:N-2]) //MSB and MSB-1 for multiplexing
2'b00 :
begin
sseg = first;
cat_temp = 2'b01;
end
2'b01:
begin
sseg = second;
cat_temp = 2'b10;
end
endcase
end
assign cat_m = cat_temp;
reg [6:0] sseg_temp;
always # (*)
begin
case(sseg)
4'd0 : sseg_temp = 7'b1000000; //display 0
4'd1 : sseg_temp = 7'b1111001; //display 1
4'd2 : sseg_temp = 7'b0100100; //display 2
4'd3 : sseg_temp = 7'b0110000; //display 3
4'd4 : sseg_temp = 7'b0011001; //display 4
4'd5 : sseg_temp = 7'b0010010; //display 5
4'd6 : sseg_temp = 7'b0000010; //display 6
4'd7 : sseg_temp = 7'b1111000; //display 7
4'd8 : sseg_temp = 7'b0000000; //display 8
4'd9 : sseg_temp = 7'b0010000; //display 9
default : sseg_temp = 7'b0111111; //dash
endcase
end
assign {g_m, f_m, e_m, d_m, c_m, b_m, a_m} = sseg_temp;
endmodule
I have made it so that I can display the digits by passing the values to the first and second register. but dont know how to accomplish this with the values of DataA and DataB shown in simulation.
Thanks
Well, you can do this no problem. It's just that you won't be displaying 'digits' on the seven segment display in the sense of them being recognizable numbers in decimal or hex. Each of the segments can represent a bit. You have seven segments per 'digit' and 2 'digits'. 7 * 2 = 14.
You could scroll the 5 digits you have across the two physical digits displayed. It might be quite unpleasant to read though.
I have a simple verilog program that increments a 32 bit counter, converts the number to an ASCII string using $sformat and then pushes the string to the host machine 1 byte at a time using an FTDI FT245RL.
Unfortunately Xilinx XST keeps optimizing away the string register vector. I've tried mucking around with various initialization and access routines with no success. I can't seem to turn off optimization, and all of the examples I find online differ very little from my initialization routines. What am I doing wrong?
module counter(CK12, TXE_, WR, RD_, LED, USBD);
input CK12;
input TXE_;
output WR;
output RD_;
output [7:0] LED;
inout [7:0] USBD;
reg [31:0] count = 0;
reg [7:0] k;
reg wrf = 0;
reg rd = 1;
reg [7:0] lbyte = 8'b00000000;
reg td = 1;
parameter MEM_SIZE = 88;
parameter STR_SIZE = 11;
reg [MEM_SIZE - 1:0] str;
reg [7:0] strpos = 8'b00000000;
initial
begin
for (k = 0; k < MEM_SIZE; k = k + 1)
begin
str[k] = 0;
end
end
always #(posedge CK12)
begin
if (TXE_ == 0 && wrf == 1)
begin
count = count + 1;
wrf = 0;
end
else if (wrf == 0) // If we've already lowered the strobe, latch the data
begin
if(td)
begin
$sformat(str, "%0000000000d\n", count);
strpos = 0;
td = 0;
end
str = str << 8;
wrf = 1;
strpos = strpos + 1;
if(strpos == STR_SIZE)
td = 1;
end
end
assign RD_ = rd;
assign WR = wrf;
assign USBD = str[87:80];
assign LED = count[31:24];
endmodule
Loading device for application
Rf_Device from file '3s100e.nph' in
environment /opt/Xilinx/10.1/ISE.
WARNING:Xst:1293 - FF/Latch str_0
has a constant value of 0 in block
. This FF/Latch will be
trimmed during the optimization
process.
WARNING:Xst:1896 - Due to other
FF/Latch trimming, FF/Latch str_1
has a constant value of 0 in block
. This FF/Latch will be
trimmed during the optimization
process.
WARNING:Xst:1896 - Due to other
FF/Latch trimming, FF/Latch str_2
has a constant value of 0 in block
. This FF/Latch will be
trimmed during the optimization
process.
The $sformat task is unlikely to be synthesisable - consider what hardware the compiler would need to produce to implement this function! This means your 'str' register never gets updated, so the compiler thinks it can optimize it away. Consider a BCD counter, and maybe a lookup table to convert the BCD codes to ASCII codes.
AFAIK 'initial' blocks are not synthesisable. To initialize flops, use a reset signal. Memories need a 'for' loop like you have, but which triggers only after reset.