Esta es la salida de la simulación ISim:
Quierodisminuirtx_data_ctren1cuandoflags_from_clk_divcambiea4'b0000,porloquesda_flag_from_transmit_bytetomaelbitinicialdetx_data[7:0].Sinembargo,nopudeencontrarunamaneradehacerlo.Loquerealmentepreguntoessihayunamaneradeestablecerunamarcaohaceralgomásdemanerasincrónicaconelcambiosegurodeunregistro?
Escomo@(reg_x==4'b0001)
-do_stuffpero,porsupuesto,séquenoexistetalcomando.
También,¿alguienpuedehacercosasconposedgecomocuandouncambioderegistroejecutaalgodeinmediato?
Usoconfiguracionescomo:
always@(posedgestart)begin//stuffstuffend
pero,¿podemosaplicaralgocomoestoaunregistroquetengamásdeunbyte?Esperopoderexplicarlo.
editar:heañadidoloscódigosacontinuación:
scl_counter.v:
modulescl_counter(inputrst,inputstart,outputreg[3:0]flags,inputclk);parameterclk_divider=0;reg[15:0]scl_counter;always@(posedgestart)beginflags=4'b0;scl_counter=16'b0;endalways@(posedgeclk)beginif(rst)beginflags=4'b0;scl_counter=16'b0;endelseif(!rst)beginif(clk_divider!=1)beginif(scl_counter!=(clk_divider*2))beginscl_counter=scl_counter+1;if(scl_counter==(clk_divider/2))beginflags[0]=1'b1;endelseif(scl_counter==(clk_divider*3/2))beginflags[1]=1'b1;endendelseif(scl_counter==(clk_divider*2))beginscl_counter=16'b0;flags=4'b0;endendelseif(clk_divider==1)beginendendendendmodule
transmit_byte.v:
'include"scl_counter.v"
module transmit_byte(
output reg [0:0] sda_flag_from_transmit_byte,
input [7:0] tx_data,
output reg [7:0] rx_data,
input clk,
output reg [0:0] scl_flag_from_transmit_byte,
input start_scl_div,
output reg [0:0] reset_to_clk_div,
input [3:0] flags_from_clk_div,
output reg [2:0] tx_data_ctr
);
reg [2:0] rx_data_ctr;
reg [0:0] ready_to_start_flag;
reg [0:0] resetter_flag_clk_div;
always @(posedge start_scl_div) begin
scl_flag_from_transmit_byte = 1'b0;
ready_to_start_flag = 1'b0;
resetter_flag_clk_div = 1'b0;
tx_data_ctr = 3'b111;
rx_data_ctr = 3'b0;
ready_to_start_flag = #1 1'b1;
end
always @(negedge clk)
begin: RESETTER_TO_CLK_DIV
if (ready_to_start_flag) begin
if (start_scl_div) begin
if (resetter_flag_clk_div == 1'b1) begin
reset_to_clk_div = 1'b0;
end
else if (resetter_flag_clk_div == 1'b0) begin
reset_to_clk_div = 1'b1;
resetter_flag_clk_div = 1'b1;
end
end
end
end
always @(posedge clk) begin
if (start_scl_div) begin
if (ready_to_start_flag) begin
if (flags_from_clk_div == 4'b0) begin
sda_flag_from_transmit_byte = tx_data[tx_data_ctr];
end
else if (flags_from_clk_div == 4'b0001) begin
scl_flag_from_transmit_byte = 1'b1;
end
else if (flags_from_clk_div != 4'b0001) begin
scl_flag_from_transmit_byte = 1'b0;
end
end
end
end
always @(negedge start_scl_div) begin
ready_to_start_flag = 1'b0;
resetter_flag_clk_div = 1'b0;
end
//b01100100
scl_counter #(16'b00001000) c_1(
.rst (reset_to_clk_div),
.start (start_scl_div),
.flags (flags_from_clk_div),
.clk (clk)
);
endmodule
timer_A.v:
module timer_A(
input clk, // which clock?
input rst, // sets to 0 or up counter
//output [7:0] flags_timer_A, // sets flag when counts to the value
input mode, // if mode 0, counts up to A only flags A, if 1 counts to
// A and B, C, D ... flags if they are not 0.
input [15:0] count_to_A, // counts to first value
input [15:0] count_to_B, // counts to second value
input count_to_C,
input count_to_D,
input count_to_E,
input count_to_F,
input count_to_G,
input count_to_H,
output reg [7:0] flags_timer_A
);
reg [15:0] timer_A_Reg;
//reg [7:0] flags_timer_A;
/*
timer_A_flag_A = flags_timer_A[0]
timer_A_flag_B = flags_timer_A[1]
timer_A_flag_C = flags_timer_A[2]
timer_A_flag_D = flags_timer_A[3] ...
*/
always @(posedge rst) begin
flags_timer_A = 8'b0;
timer_A_Reg = 16'b0;
end
always @(posedge clk) begin
if (rst) begin
flags_timer_A = 8'b0;
timer_A_Reg = 16'b0;
end
else if (!rst) begin
if (mode == 1'b0) begin
if (timer_A_Reg != count_to_A) begin
timer_A_Reg <= timer_A_Reg + 1;
end
else begin
flags_timer_A[0] <= 1'b1;
end
end
else begin
if (timer_A_Reg != count_to_A) begin
timer_A_Reg = timer_A_Reg + 1;
if (timer_A_Reg == count_to_B) begin
flags_timer_A[1] = 1'b1;
end
else if (timer_A_Reg == count_to_C) begin
flags_timer_A[2] = 1'b1;
end
else if (timer_A_Reg == count_to_D) begin
flags_timer_A[3] = 1'b1;
end
else if (timer_A_Reg == count_to_E) begin
flags_timer_A[4] = 1'b1;
end
else if (timer_A_Reg == count_to_F) begin
flags_timer_A[5] = 1'b1;
end
else if (timer_A_Reg == count_to_G) begin
flags_timer_A[6] = 1'b1;
end
else if (timer_A_Reg == count_to_H) begin
flags_timer_A[7] = 1'b1;
end
end
else begin
flags_timer_A[0] <= 1'b1;
end
end
end
end
endmodule
start_i2c.v:
'include "timer_A.v"
module start_i2c(
input start,
input [7:0] flags_timer_A,
input clk,
output reg [0:0] rst_to_tmr,
output reg [0:0] start_done,
output reg [0:0] scl_flag_from_start_i2c,
output reg [0:0] sda_flag_from_start_i2c
);
reg [0:0] resetter_flag;
reg [0:0] mode_to_tmr;
/*
timer_A_flag_A = flags[0]
timer_A_flag_B = flags[1]
timer_A_flag_C = flags[2]
timer_A_flag_D = flags[3] ...
*/
always @(posedge start) begin
resetter_flag <= 1'b0;
mode_to_tmr <= 1'b1;
start_done <= 1'b0;
scl_flag_from_start_i2c <= 1'b1;
sda_flag_from_start_i2c <= 1'b1;
end
parameter min_SDA_on_time = 0;
parameter min_SDA_SCL_fall_delay = 0;
always @(negedge clk)
begin: RESETTER // this resets up when start is on immediately
if (start && !resetter_flag) begin
rst_to_tmr = 1'b1;
resetter_flag = 1'b1;
end
else if (start && resetter_flag) begin
rst_to_tmr <= 1'b0;
end
end
always @(posedge clk) begin
if (start) begin
if (flags_timer_A[1]) begin
sda_flag_from_start_i2c <= 1'b0;
end
if (flags_timer_A[0]) begin
scl_flag_from_start_i2c <= 1'b0;
start_done <= 1'b1;
end
end
else begin
end
end
always @(negedge start) begin
resetter_flag = 1'b0;
//start_done <= 1'b0;
end
timer_A start_timer(
.clk (clk), // which clock?
.rst (rst_to_tmr), // sets to 0 or up counter
.mode (mode_to_tmr), // if mode 0, counts up to A only flags A, if 1 counts to
// A and B, C, D ... flags if they are not 0.
.count_to_A (min_SDA_on_time + min_SDA_SCL_fall_delay), // counts to first value
.count_to_B (min_SDA_on_time), // counts to second value
.count_to_C (16'b0),
.count_to_D (16'b0),
.count_to_E (16'b0),
.count_to_F (16'b0),
.count_to_G (16'b0),
.count_to_H (16'b0),
.flags_timer_A (flags_timer_A) // sets flag when counts to the value
);
endmodule
**start_i2c_tb.v:**
'include "start_i2c.v"
'include "transmit_byte.v"
module start_i2c_tb(
);
//defparam start_test.min_SDA_on_time = 16'b11001000;
//defparam start_test.min_SDA_SCL_fall_delay = 16'b01100100;
reg [0:0] start_start_i2c;
reg [0:0] start_scl_div;
reg [7:0] tx_data;
wire [7:0] flags_timer_A;
reg [0:0] clk;
wire sda_flag_from_transmit_byte;
wire scl_flag_from_transmit_byte;
wire scl_flag_from_start_i2c;
wire sda_flag_from_start_i2c;
wire [3:0] flags_from_clk_div;
wire [2:0] tx_data_ctr;
initial begin
clk = 1'b0;
start_scl_div = 1'b0;
start_start_i2c = 1'b0;
#5 start_start_i2c = 1'b1;
tx_data = 8'b10101010;
#40000 $finish;
end
always begin
#1 clk = ~ clk;
end
always @(clk) begin
if (start_done && start_start_i2c) begin
start_start_i2c = 1'b0;
end
else if (start_done && !start_start_i2c) begin
start_start_i2c = 1'b0;
start_scl_div = 1'b1;
end
end
start_i2c #(16'b11001000, 16'b01100100) start_test(
.start (start_start_i2c),
.flags_timer_A (flags_timer_A),
.clk (clk),
.rst_to_tmr (rst_to_tmr),
.start_done (start_done),
.scl_flag_from_start_i2c (scl_flag_from_start_i2c),
.sda_flag_from_start_i2c (sda_flag_from_start_i2c)
);
transmit_byte start_transmit(
.sda_flag_from_transmit_byte (sda_flag_from_transmit_byte),
.tx_data (tx_data),
.rx_data (rx_data),
.clk (clk),
.scl_flag_from_transmit_byte (scl_flag_from_transmit_byte),
.start_scl_div (start_scl_div),
.reset_to_clk_div (reset_to_clk_div),
.flags_from_clk_div (flags_from_clk_div),
.tx_data_ctr (tx_data_ctr)
);
endmodule
EDITAR: Basado en la respuesta de Dave Tweed, agregué el siguiente bloque de código y ahora funciona. ¿Es la forma correcta de hacerlo?
always @(posedge clk) begin
if (flags_from_clk_div == 4'b0) begin
if (tx_check) begin
tx_data_ctr = tx_data_ctr + 1;
tx_check = 1'b0;
end
end
if (flags_from_clk_div == 4'b0011) begin
tx_check = 1'b1;
end
end