I use AXI IIC BUS IP Core on vivado.Even if I write the corresponding data to the register, there is no change on the sda data line.
Here is the registers of the ip core.
Register of AXI IIC
And the Programming Sequence are as below.
The sequence
It seems that I only need to complete the first and the second steps and I can see the wavefrom changes on SDA
Here is a top.v (it's not my original,reference from Bad s_axi_bvalid, s_axi_wready, and s_axi_awready signals using Vivado IIC IP Flow)
module i2c_channel #(
parameter CHANNEL_OUTPUT_WIDTH = 16
)(
input clk,
input reset,
//the address of the slave;
input [6:0] slave_address,
//The width of the message expected from the slave at the specified address;
input [127:0] slave_message_width,
inout sda,
inout scl,
output [CHANNEL_OUTPUT_WIDTH - 1:0] channel_output
);
wire iic2intc_irpt ;
//AXI Global System Signals
wire s_axi_aclk;
assign s_axi_aclk = clk;
reg s_axi_aresetn ;
//AXI Write Address Channel Signals
reg [31:0] s_axi_awaddr ;
reg s_axi_awvalid ;
wire s_axi_awready;
//AXI Write Data Channel Signals
reg [31:0] s_axi_wdata ;
reg [3:0] s_axi_wstrb ;
reg s_axi_wvalid ;
wire s_axi_wready;
//AXI Write Response Channel Signals
wire [1:0] s_axi_bresp;
wire s_axi_bvalid;
reg s_axi_bready ;
//AXI Read Address Channel Signals
reg [31:0] s_axi_araddr ;
reg s_axi_arvalid ;
wire s_axi_arready;
//AXI Read Data Channel Signals
wire [31:0] s_axi_rdata;
wire [1:0] s_axi_rresp;
wire s_axi_rvalid;
reg s_axi_rready ;
//IIC signals
reg sda_i ;
wire sda_o;
wire sda_t;
reg scl_i ;
wire scl_o;
wire scl_t;
reg gpo ;
reg state_done;
//i2C state
`define SET_TX_FIFO 4'b0000
`define SET_RX_FIFO_PIRQ 4'b0001
`define SET_CR_MSMS_TX 4'b0010
`define SET_CR_TXAK 4'b0011
reg[3:0]state;
initial begin
state<=4'b0000;
end
//tri-state open-collector buffers to convert the iic signals to bi-directional inouts.
assign sda = sda_t ? sda_o : sda_i;
assign sda = scl_t ? scl_o : scl_i;
axi_iic_1 iic (
.iic2intc_irpt(),
.s_axi_aclk(s_axi_aclk),
.s_axi_aresetn(s_axi_aresetn),
.s_axi_awaddr(s_axi_awaddr[8:0]),
.s_axi_awvalid(s_axi_awvalid),
.s_axi_awready(s_axi_awready),
.s_axi_wdata(s_axi_wdata),
.s_axi_wstrb(s_axi_wstrb),
.s_axi_wvalid(s_axi_wvalid),
.s_axi_wready(s_axi_wready),
.s_axi_bresp(s_axi_bresp),
.s_axi_bready(s_axi_bready),
.s_axi_bvalid(s_axi_bvalid),
.s_axi_araddr(s_axi_araddr),
.s_axi_arvalid(s_axi_arvalid),
.s_axi_arready(s_axi_arready),
.s_axi_rdata(s_axi_rdata),
.s_axi_rvalid(s_axi_rvalid),
.s_axi_rresp(s_axi_rresp),
.sda_i(sda_i),
.sda_o(sda_o),
.sda_t(sda_t),
.scl_i(scl_i),
.scl_o(scl_o),
.scl_t(scl_t)
);
always #(clk) begin
s_axi_aresetn <= ~reset;
end
//Sets an axi data write operation.
task set_a_axi_w ;
input [31:0] awaddr;
input [31:0] wdata;
begin
s_axi_awaddr = awaddr;
s_axi_wdata = wdata;
s_axi_awvalid = 1'b1;
s_axi_bready = 1'b1;
s_axi_wvalid = 1'b1;
end
endtask
//set the state of the operation.
task set_state ;
input[3:0] new_state;
if(s_axi_awready) begin
state = new_state;
end
endtask
//when the module is initialized, write the i2c address of the target slave to the TX_FIFO register.
//Write the IIC peripheral device addresses for the first slave device to the TX_FIFO.
always #(posedge clk) begin
case (state)
`SET_TX_FIFO : begin
set_a_axi_w(32'h108, slave_address);
set_state(`SET_RX_FIFO_PIRQ);
end
`SET_RX_FIFO_PIRQ : begin
set_a_axi_w(32'h120, slave_message_width - 2);
set_state(`SET_CR_MSMS_TX);
end
`SET_CR_MSMS_TX : begin
set_a_axi_w(32'h100, 8'b00000101);
set_state(`SET_CR_TXAK);
end
endcase
if(s_axi_awready) begin
//s_axi_awaddr <= '0;
s_axi_awvalid <= 1'b0;
end
if(s_axi_wready) begin
//s_axi_wdata <= '0;
s_axi_wvalid <= 1'b0;
end
if (s_axi_bvalid) begin
s_axi_bready <= 1'b0;
end/**
else begin
s_axi_bready <=1'b0;
end**/
end
endmodule
Here is the simulation file:
module i2c_channel_tb();
//Parameters
parameter CLK_PERIOD = 10;
reg clk = 1'b1;
reg reset = 1'b1;
reg [6:0] slave_address = 6'b0;
wire sda;
wire scl;
i2c_channel i2c_channel_1 (
.clk(clk),
.reset(reset),
.slave_address(slave_address),
.slave_message_width(128'd16),
.sda(sda),
.scl(scl)
);
/*
i2c_channel_slave_model i2c_channel_slave_model_1 (
.sda(sda),
.scl(scl)
);**/
initial begin
clk <= 1'b0;
reset <= 1'b0;
slave_address <= 7'b100_1011;
end
//psuedo-clock
always #10 begin
clk <= ~clk;
end
endmodule
the waveform result is below:
Result waveform
As shown in the figure,the data is written to the register,but no changes occur on the sda_o and scl_o.
Could anybody tell me why?
Thanks!
One obvious mistake is that your SDA and SCL should be pulled up in their initial state.
Your waveform shows that sda_o, sda_i, scl_o, and scl_i are not pulled up at any given time. So perhaps you need to check that. (Either it is some hardware schematic to check, or some IO constraint to set.)
Related
module mac #(
parameter integer A_BITWIDTH = 8,
parameter integer B_BITWIDTH = A_BITWIDTH,
parameter integer OUT_BITWIDTH = 20,
parameter integer C_BITWIDTH = OUT_BITWIDTH - 1
)
(
input clk,
input rstn,
input en,
input add,
input [A_BITWIDTH-1:0] data_a,
input [B_BITWIDTH-1:0] data_b,
input [C_BITWIDTH-1:0] data_c,
output reg done,
output [OUT_BITWIDTH-1:0] out
);
localparam
STATE_IDLE = 2'b00,
STATE_MULT = 2'b01,
STATE_ACCM = 2'b10;
reg [1:0] state;
reg signed [OUT_BITWIDTH-1:0] out_temp;
reg signed [A_BITWIDTH-1:0] data_a_bf;
reg signed [B_BITWIDTH-1:0] data_b_bf;
reg signed [C_BITWIDTH-1:0] data_c_bf;
assign out = out_temp;
always # (posedge clk or negedge rstn) begin
if(!rstn) begin
state <= STATE_IDLE;
data_a_bf <= {A_BITWIDTH{1'b0}};
data_b_bf <= {B_BITWIDTH{1'b0}};
data_c_bf <= {C_BITWIDTH{1'b0}};
done <= 1'b0;
out_temp <={OUT_BITWIDTH{1'b0}};
end
else begin
case(state)
STATE_IDLE: begin
// TO DO
// Done flag reset!
data_a_bf <= {A_BITWIDTH{1'b0}};
data_b_bf <= {B_BITWIDTH{1'b0}};
data_c_bf <= {C_BITWIDTH{1'b0}};
out_temp <={OUT_BITWIDTH{1'b0}};
done <= 1'b0;
if(en && !done) begin
// If en == 1 and done != 1, then running state.
// And capture data_a, data_b, data_c to buffer
data_a_bf <= data_a;
data_b_bf <= data_b;
data_c_bf <= data_c;
state <= STATE_MULT;
end
else begin
// If not, just waiting for condition.
end
end
STATE_MULT: begin
// TO DO;
if (!add) begin
// If add signal is low, do muliply with data_a_bf and data_b_bf.
//out_temp <= data_a_bf * data_b_bf;
out_temp <= {{{A_BITWIDTH{data_a_bf[7]}}, data_a_bf}*{{B_BITWIDTH{data_b_bf[7]}}, data_b_bf}}[15:0]; // >> this invokes a error, which is syntax error near "["
end
else begin
// If add signal is high, shift data_a_bf to match bit representation.
//out_temp <= {data_a_bf, 8'b0};
out_temp <= {data_a_bf, 8'b0};
end
state <= STATE_ACCM;
end
STATE_ACCM: begin
// TO DO
// Do add and make output 'done' flag high.( done = 1)
out_temp <= out_temp + data_c_bf;
done <= 1'b1;
state <= STATE_IDLE;
end
default:;
endcase
end
end
endmodule
I want to do 'bit select' concatenation of data_a_bf signed extension * data_b_bf signed extension and assign it to out_temp, but it occurs a syntax error. How can I do this?
I don't know how to do bit select of it.
I think you just need to see error line.
I just upload all code.
Selecting a bit of a concatenation is a feature of SystemVerilog, not Verilog. Make sure your file has a .sv file extension. The tool that you are using might also have a switch to turn on support for SystemVerilog.
A Verilog friendly solution would be to create a bit mask.
For example, change:
out_temp <= {{{A_BITWIDTH{data_a_bf[7]}}, data_a_bf}*{{B_BITWIDTH{data_b_bf[7]}}, data_b_bf}}[15:0]; // >> this invokes a error, which is syntax error near "["
To:
out_temp <= {{{A_BITWIDTH{data_a_bf[7]}}, data_a_bf}*{{B_BITWIDTH{data_b_bf[7]}}, data_b_bf}} & 'h0FFFF;
module alucontrol(iw,cntrl,Ra,Rb,Wa);
input [14:0]iw;
output reg [3:0]cntrl;
output reg [3:0]Ra;
output reg [3:0]Rb;
output reg [3:0]Wa;
always#(*)
begin
cntrl=iw[14:12];
Ra=iw[11:8];
Rb=iw[7:4];
Wa=iw[3:0];
end
endmodule
////////////////////////////////////////////
module alumemory(Ra,Rb,Wa,A,B);
input wire [3:0]Ra,Rb,Wa;
output reg [3:0]A,B;
reg [3:0] mem [0:15];
reg array[3:0][0:15];
always#(*)
begin
array[3:0][0]=4'b0100;
array[3:0][1]=4'b1001;
array[3:0][2]=4'b0110;
array[3:0][3]=4'b0010;
array[3:0][4]=4'b0100;
array[3:0][5]=4'b1101;
array[3:0][6]=4'b0100;
array[3:0][7]=4'b0001;
array[3:0][8]=4'b0000;
array[3:0][9]=4'b1111;
array[3:0][10]=4'b1000;
array[3:0][11]=4'b1001;
array[3:0][12]=4'b1000;
array[3:0][13]=4'b1011;
array[3:0][14]=4'b1100;
array[3:0][15]=4'b1010;
end
integer my_int1;
always#(1)
begin
my_int1=Ra;
A[3:0]=array[3:0][my_int1];
end
integer my_int2;
always#(1)
begin
my_int2=Rb;
B[3:0]=array[3:0][my_int2];
end
integer my_int3;
always#(1)
begin
my_int3=Wa;
array[3:0][my_int3]=C[3:0];
end
endmodule
////////////////////////////////////
module Decoder(cntrl[3:0],adden, suben, mulen, diven, anden, oren, xoren, noten);
input [3:0]cntrl;
output adden, suben, mulen, diven, anden, oren, xoren, noten;
assign adden=(~a&~b&~c),
suben=(~a&~b&c),
mulen=(~a&b&~c),
diven=(~a&b&c),
anden=(a&~b&~c),
oren=(a&~b&c),
xoren=(a&b&~c),
noten=(a&b&c);
endmodule
//////////////////////////////////////////////////
module alu_arith(input[3:0]A,
input adden, input suben,input mulen,input diven,input anden,input oren,input xoren,input noten,
input[3:0]B,
output reg [7:0]C
);
reg cntrlinp[7:0];
//wire[3:0]A;
//wire[3:0]B;
assign cntrlinp[0]=adden,
cntrlinp[1]=suben,
cntrlinp[2]=mulen,cntrlinp[3]=diven,cntrlinp[4]=anden,cntrlinp[5]=oren,cntrlinp[6]=xoren,cntrlinp[7]=noten;
always#(*)
begin
case(ctrlinp[7:0])
00000001:C=A+B;
00000010:C=A-B;
00000100:C=A*B;
00001000:C=A/B;
00010000:C=A&B;
00100000:C=A|B;
01000000:C=A^B;
10000000:C=~A;
default: C=8'b00000001;
endcase
end
endmodule
///////////////////////////////////////////////////////
module testbench;
reg[14:0]iw;
wire[7:0]C;
alucontrol a1(iw, cntrl,Ra,Rb,Wa);
alumemory a2(Ra,Rb,Wa,A,B);
alu_arith a3(A,B,C);
Decoder a4(cntrl,adden, suben, mulen, diven, anden, oren, xoren, noten);
initial begin
$display("time\t A B cntrl C");
$monitor("%g\t %b %b %b %b",
$time, A, B, cntrl, C);
#0 C=8'b00000000;
iw=15'b101000101011010;
#5 iw=15'b001100110011001;
#10 iw=15'b010101110101110;
end
endmodule
So i'm trying to make a very basic design of a processor(a simple ALU with register file and control unit) where the control unit takes the opcode, divides it into iw(instruction word), Ra(Read A),Rb(Read B) and Wa(Write A) and sends the last three of those to the register file to write/read registers.
The parameters that are output for control unit are input for register file, and my code is repeatedly giving the following error in two lines after alumemory module begins:
syntax error
error: Invalid variable list in port declaration.
I don't understand what's exactly causing a syntax error. Please help.
I've created a 2d array for register file and I'm accessing it using the following block:
integer my_int2;
always#(1)
begin
my_int2=Rb;
B[3:0]=array[3:0][my_int2];
end
I think I've declared ports and wire and reg in an appropriate way.
module alucontrol(iw,cntrl,Ra,Rb,Wa);
input [14:0]iw;
output [3:0]cntrl;
output[3:0]Ra;
output[3:0]Rb;
output[3:0]Wa;
reg [3:0]Ra;
reg [3:0]Rb;
reg [3:0]Wa;
reg [3:0]cntrl;
always#(*)
begin
cntrl=iw[14:12];
Ra=iw[11:8];
Rb=iw[7:4];
Wa=iw[3:0];
end
endmodule
////////////////////////////////////////////
module alumemory(Ra,Rb,Wa,A,B);
input [3:0]Ra,input [3:0]Rb;input [3:0]Wa;
output[3:0]A;output [3:0]B;
wire [3:0]Ra; wire [3:0]Rb; wire [3:0]Wa;
reg[3:0]A;
reg[3:0]B;
reg [3:0] mem [0:15];
reg array[3:0][0:15];
always#(*)
begin
array[3:0][0]=4'b0100;
array[3:0][1]=4'b1001;
array[3:0][2]=4'b0110;
array[3:0][3]=4'b0010;
array[3:0][4]=4'b0100;
array[3:0][5]=4'b1101;
array[3:0][6]=4'b0100;
array[3:0][7]=4'b0001;
array[3:0][8]=4'b0000;
array[3:0][9]=4'b1111;
array[3:0][10]=4'b1000;
array[3:0][11]=4'b1001;
array[3:0][12]=4'b1000;
array[3:0][13]=4'b1011;
array[3:0][14]=4'b1100;
array[3:0][15]=4'b1010;
end
integer my_int1;
always#(1)
begin
my_int1=Ra;
A[3:0]=array[3:0][my_int1];
end
integer my_int2;
always#(1)
begin
my_int2=Rb;
B[3:0]=array[3:0][my_int2];
end
integer my_int3;
always#(1)
begin
my_int3=Wa;
array[3:0][my_int3]=C[3:0];
end
endmodule
Declare your ports this in this much simpler way:
module alumemory(
input wire [3:0] Ra, Rb, Wa,
output reg [3:0] A,B
);
reg [3:0] mem [0:15];
reg array[3:0][0:15];
...
I am trying to understand state machine in VHDL for detecting the edge on a signal in VHDL. in next state I dont understand why we put the:
"next_etat<= reg_etat" because I think it could work without any problem even without it .
I'd would what are the default value of reg_etat and next_etat when we have just run the program because their is no real default value like in c for example int var=0;
entity machine_etat is
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
entree : in STD_LOGIC;
tc : out STD_LOGIC);
end machine_etat;
architecture architecture_machine_etat of machine_etat is
type T_etat is (idle,edge,one);
signal next_etat, reg_etat : T_etat;
begin
registre_etat: process(clk)
begin
if rising_edge(clk) then
if rst = ’1’ then
reg_etat <= idle;
else
reg_etat <= next_etat;
end if;
end if;
end process registre_etat;
tc <= ’1’ when reg_etat = edge else ’0’;
etat_suivant: process(reg_etat,entree)
begin
next_etat <= reg_etat;-- defaults values here i dont see their purpose
case reg_etat is
when idle =>
if entree =’1’ then
next_etat <= edge;
end if;
when edge =>
next_etat <= one;
when one =>
if entree =’0’ then
next_etat <= idle;
end if;
end case;
end process etat_suivant;
end architecture_machine_etat;
If you don't assign next_etat (pardon my French) in all situations, logical synthesis will infer a latch to remember it's state. A latch is something you don't want, as it is very sensitive to digital logic latencies and might become metastable: also something you don't want.
HDL programming significantly differs from CPU programming.
I am writing something in verilog in quartus, and appeared to me something strange, but pretty simple actually
This code increments the address correctly
module counter(
input wire clock,
input wire reset,
output reg [4:0]address
);
initial
begin
address = 5'b0
end
always#(posedge clock)
begin
if(reset)
begin
address <= 5'b0;
end
else
begin
address <= address + 5'b00001;
end
end
endmodule
this, the bits that change become not matter, it happens when I start the output to something other than 0
module counter(
input wire clock,
input wire reset,
output reg [4:0]address
);
initial
begin
address = 5'b11101;
end
always#(posedge clock)
begin
if(reset)
begin
address <= 5'b0;
end
else
begin
address <= address + 5'b00001;
end
end
endmodule
Does anyone know any way to solve this problem?
While it is difficult to tell exactly what you are saying, it seems you are curious as to why changing the starting value in the initial block seems to have no affect on where the counter starts.
It seems you are likely performing a reset as part of your testbench, so when you look at address, the value always starts at 0 (because the initial block setting is changed by the reset in the always block).
This part is suspicious to me:
if(reset)
begin
address <= 5'b0;
end
Should be:
if(reset)
begin
address <= 5'b00000;
end
You can try use this implementation with load and start signal:
module Counter(load,clk,start,data_in,data_out);
input load;
input clk;
input start;
input [5-1:0] data_in;
output [5-1:0] data_out;
reg [5-1:0] tmp;
initial
begin
tmp = 5'b0000;
end
always # ( posedge clk)
begin
if(~start)
begin
tmp <= 5'b0000;
end
else if(load)
tmp <= data_in;
else
tmp <= tmp + 1'b1;
end
assign data_out = tmp;
endmodule
This must be the most common problem among people new to VHDL, but I don't see what I'm doing wrong here! This seems to conform to all of the idioms that I've seen on proper state machine design. I'm compiling in Altera Quartus 9.2, for what it's worth. The actual error is:
"Can't infer register for "spiclk_out" at [file] [line] because it does not hold its value outside the clock edge"
ENTITY spi_state_machine IS
PORT(
spiclk_internal : IN STD_LOGIC;
reset : IN STD_LOGIC;
spiclk_out : BUFFER STD_LOGIC
);
END spi_state_machine;
PROCESS(spiclk_internal, reset)
BEGIN
IF reset = '1' THEN
spiclk_out <= '0';
END IF;
IF spiclk_internal = '1' AND spiclk_internal'EVENT THEN --error here
spiclk_out <= NOT spiclk_out;
END IF;
END PROCESS;
Thanks for your time.
As written, the process would cause spiclk_out to toggle on spiclk_internal edges even when reset is active, which is not how flip-flops with asynchronous resets should behave.
What you probably want is
SPICLK: process(spiclk_internal, reset)
if reset = '1' then
spiclk_out <= '0';
elsif spiclk_internal'event and spiclk_internal='1' then
spiclk_out <= not spiclk_out;
end if;
end process SPICLK;