Non-integer multiple data bit width conversion 8to12
The so-called non-integer multiple is to use a cnt to periodically determine how to output the register. The value of this cnt is the least common multiple.
The register is registered normally. How to input and register?
`timescale 1ns/1ns
module width_8to12(
input clk ,
input rst_n ,
input valid_in ,
input [7:0] data_in ,
output reg valid_out,
output reg [11:0] data_out
);
reg[7:0]data_lock;
reg[1:0]valid_cnt;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
data_lock<=0;
else if(valid_in)
data_lock<=data_in;
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
valid_cnt<=0;
else if(valid_in)begin
if(valid_cnt==2'd2)
valid_cnt<=0;
else
valid_cnt<=valid_cnt+1;
end
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
valid_out<=0;
else if(valid_in&&valid_cnt==1)
valid_out<=1;
else if(valid_in&&valid_cnt==2)
valid_out<=1;
else
valid_out<=0;
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
data_out<=0;
else if(valid_in&&valid_cnt==1)
data_out<={data_lock,data_in[7:4]};
else if(valid_in&&valid_cnt==2)
data_out<={data_lock[3:0],data_in};
end
endmodule
Why don’t you need two 8-bit registers for data caching:
According to the timing diagram, data_out generates output in the next clock cycle after two data inputs. If two registers are used to cache two data, then the data must be output before the second data is cached in the register. This cannot meet the requirements. Data output for timing requirements.
According to the timing diagram, data is output after the second data arrives. When only one data arrives, no output is generated, so a counter (valid_cnt) is designed internally to indicate the data reception status. When it is detected that valid_in is pulled high, valid_cnt increases by 1, valid_cnt cycles between 0-2, and the reset value of valid_cnt is 0. When valid_cnt is 1 or 2 and valid_in is high, data is output and valid_out is pulled high.
When valid_cnt==1 and valid_in is high, data_out <= {data_lock, data_in[7:4]}; when valid_cnt==2 and valid_in is high, data_out <= {data_lock[3:0], data_in}.
That is to say, when resetting, there is no one in the register, so it cannot be output. Then after saving one, it is 1, and then it can be output. At this time, the output will output the 8 saved ones and the first 4 newly input ones. And enter 2, which means that the second input is stored in the register at this time, and the first half has been output, and the last four should be output, so the output at this time is the last four of the output register and the new input. All, at this time the inside of the register is actually equivalent to being empty.
In other words, valid_cnt determines the output signal, how to process the signal in the register
Circuit diagram
That is, sequential logic requires the use of flip-flops. <=The most direct one is the D flip-flop.
Integer multiple data bit width conversion 8to16
`timescale 1ns/1ns
module width_8to16(
input clk ,
input rst_n ,
input valid_in ,
input [7:0] data_in ,
output reg valid_out,
output reg [15:0] data_out
);
reg[0:0]cnt;
reg[7:0]ram;
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
cnt<=0;
else if(valid_in)
cnt<=(cnt)?0:1;
else
cnt<=cnt;
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)
ram<=0;
else if(valid_in)
ram<=data_in;
else
ram<=ram;
end
always@(posedge clk,negedge rst_n)begin
if(!rst_n)begin
data_out<=0;
valid_out<=0;
end
else if(cnt&&valid_in)begin
data_out<={ram,data_in};
valid_out<=1;
end
else begin
data_out<=data_out;
valid_out<=0;
end
end
endmodule
Note that when the if condition is omitted, the state before the latch is automatically generated.
Circuit diagram
QN stands for antistate, i.e. negation
An empty line means that the corresponding signal is not used, that is, no subsequent output is made.
The simple logic is to generate a simple D flip-flop
The D signal here is the signal that controls the current Q state of the flip-flop. After some processing, it becomes a two-way selector, and then there is an AND gate above it; there is no signal above because the latched signal is an 8-bit signal, not 0 or 1.
Clock divider (even
`timescale 1ns/1ns
module even_div
(
input wire rst ,
input wire clk_in,
output wire clk_out2,
output wire clk_out4,
output wire clk_out8
);
//*************code***********//
reg clk2,clk4,clk8;
always@(posedge clk_in,negedge rst)begin
if(!rst)
clk2<=0;
else
clk2<=~clk2;
end
always@(posedge clk2,negedge rst)begin
if(!rst)
clk4<=0;
else
clk4<=~clk4;
end
always@(posedge clk4,negedge rst)begin
if(!rst)
clk8<=0;
else
clk8<=~clk8;
end
assign clk_out8=clk8;
assign clk_out4=clk4;
assign clk_out2=clk2;
//*************code***********//
endmodule
D flip-flop
The D flip-flop constructs a circuit diagram, which is <= The right side is the input D signal, and the left side is the output Q current signal.
The D flip-flop interface has the clock signal that controls the triggering of the flip-flop, and the D signal, which is the signal on the right side of the equation, and the output is the converted signal.
Odd frequency division with 50% duty cycle
`timescale 1ns/1ns
module odo_div_or
#(parameter N = 7)
(
input wire rst ,
input wire clk_in,
output wire clk_out7
);
reg [3:0] cnt ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
cnt <= 'b0 ;
end
else if (cnt == N-1) begin
cnt <= 'b0 ;
end
else begin
cnt <= cnt + 1'b1 ;
end
end
reg clkp ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
clkp <= 1'b0 ;
end
else if (cnt == (N>>1)) begin
clkp <= 1 ;
end
else if (cnt == N-1) begin
clkp <= 0 ;
end
end
reg clkn ;
always @(negedge clk_in or negedge rst) begin
if (!rst) begin
clkn <= 1'b0 ;
end
else if (cnt == (N>>1) ) begin
clkn <= 1 ;
end
else if (cnt == N-1) begin
clkn <= 0 ;
end
end
assign clk_out7 = clkp | clkn ;
endmodule
For odd-numbered frequency division circuits, the main difficulty lies in the realization of 50% duty cycle. There is no way to achieve a 50% duty cycle with a single trigger edge in an odd-numbered frequency division, so you need to consider using double edges plus combinational logic to achieve a 50% duty cycle.
The first flip of clkout7 is on the rising edge, and the second time is on the falling edge.
Any decimal frequency division
Please design a clock divider that can achieve arbitrary decimal frequency division, such as a clock signal divided by 8.7
Note that rst is a low level reset
hint:
In fact, it is essentially a simple mathematical problem, that is, how to use the least common multiple to obtain the frequency ratio of the clock cycle.
Let the decimal be nn, and here we take the clock cycle divided by 8.7 times as an example.
First of all, since decimal operations cannot be performed on hardware (for example, 2.1 clocks are unrealistic, and there are no 3.3 registers), fractional frequency division cannot achieve that after division, each clock cycle is nn of the source clock. times, it is impossible to achieve a duty cycle of 1/2. Therefore, considering the fractional frequency division, the implementation should be 53 clkout clock cycles is 8.7 times of 10 clkin clock cycles.
In fact, it is almost the same as the non-integer multiple data transposition width.
Non-integer multiples of data transposition width use a counter to record which stage the current output is to.
Use a register, then record the current input signal, and finally make the corresponding output based on the signal of the counter, combined with the signal output at this time;
The difference is that for non-integer multiple data bit width conversion, a signal will be output in each clock cycle
The decimal divider is 1 within a certain period of time and 0 within a certain period of time.
The frequency divider slows down the signal frequency. It used to jump 10 times in 10 seconds, but now it only jumps once.
The idea is to approximate simulation. For large periods, decimal frequency division is used. For small periods, odd frequency division and even frequency division are used for approximation. Then a counter is used to record the large periods, and a counter is used to realize each small period. The frequency divider on the large cycle determines what frequency divider is used on the small cycle at this time, whether it is an odd number or an even number; then a FLAG flag is used to record whether the odd number divider or the even number divider is currently used. device, this FLAG will be replaced at a certain point in the middle and at the end of the entire large cycle. A certain point in the middle is calculated.
`timescale 1ns/1ns
module div_M_N(
input wire clk_in,
input wire rst,
output wire clk_out
);
parameter M_N = 8'd87;
parameter c89 = 8'd24; // 8/9时钟切换点
parameter div_e = 5'd8; //偶数周期
parameter div_o = 5'd9; //奇数周期
//*************code***********//
reg [3:0] clk_cnt;
reg [6:0] cyc_cnt;
reg div_flag;
reg clk_out_r;
always@(posedge clk_in or negedge rst) begin
if(~rst)
clk_cnt <= 0;
else if(~div_flag)
clk_cnt <= clk_cnt==(div_e-1)? 0: clk_cnt+1;
else
clk_cnt <= clk_cnt==(div_o-1)? 0: clk_cnt+1;
end
always@(posedge clk_in or negedge rst) begin
if(~rst)
cyc_cnt <= 0;
else
cyc_cnt <= cyc_cnt==(M_N-1)? 0: cyc_cnt+1;
end
always@(posedge clk_in or negedge rst) begin
if(~rst)
div_flag <= 0;
else
div_flag <= cyc_cnt==(M_N-1)||cyc_cnt==(c89-1)? ~div_flag: div_flag;
end
always@(posedge clk_in or negedge rst) begin
if(~rst)
clk_out_r <= 0;
else if(~div_flag)
clk_out_r <= clk_cnt<=((div_e>>2)+1);
else
clk_out_r <= clk_cnt<=((div_o>>2)+1);
end
assign clk_out = clk_out_r;
//*************code***********//
endmodule
In the circuit diagram, when drawing a flip-flop, you need to first look at what the clock signal is and connect it, then look at what the reset signal is and connect it; then, corresponding to the D signal, select the flip-flop. For <=, use the D flip-flop, left The side is the output Q current signal, and the right side is the input D signal. When encountering a ternary expression or else if selection, it is the selector, which selects a signal and connects it to the D signal.
No duty cycle goes to the odd divider
The so-called duty cycle is the proportion of 0 and 1 in a cycle.
Take the question on a decimal frequency divider as an example. To implement a decimal frequency divider, in a large cycle, the flag is updated at the end of the period and at a certain point in the middle. The certain point in the middle determines when to reverse, and also determines the occupancy of the flag. empty ratio
Similarly, in the frequency divider, when the output frequency division signal is reversed, it corresponds to a certain point in the middle, but it will definitely be reversed , that is, when cnt == frequency division number.
When selecting the midpoint, the duty cycle is fifty percent
`timescale 1ns/1ns
module odd_div (
input wire rst ,
input wire clk_in,
output wire clk_out5
);
//*************code***********//
reg[2:0]cnt;
reg clko;
always@(posedge clk_in,negedge rst)begin
if(!rst)
cnt<=0;
else
cnt<=cnt==4?0:cnt+1;
end
always@(posedge clk_in,negedge rst)begin
if(!rst)
clko<=0;
else
clko<=cnt<=1;
end
assign clk_out5=clko;
//*************code***********//
endmodule
vending machine 1
state machine
`timescale 1ns/1ns
module seller1(
input wire clk ,
input wire rst ,
input wire d1 ,
input wire d2 ,
input wire d3 ,
output reg out1,
output reg [1:0]out2
);
parameter s0=0,s1=1,s2=2,s3=3,s4=4,s5=5,s6=6;
reg[2:0]cs;
reg[2:0]ns;
wire[2:0]is;
assign is={d1,d2,d3};//将输入的控制信号并在一起
always@(posedge clk,negedge rst)begin
if(!rst)
cs<=s0;
else
cs<=ns;
end
always@(*)begin
case(cs)
s0:begin
case(is)
3'b100:ns=s1;
3'b010:ns=s2;
3'b001:ns=s4;
default:ns=ns;
endcase
end
s1:begin
case(is)
3'b100:ns=s2;
3'b010:ns=s3;
3'b001:ns=s5;
default:ns=ns;
endcase
end
s2:begin
case(is)
3'b100:ns=s3;
3'b010:ns=s4;
3'b001:ns=s6;
default:ns=ns;
endcase
end
default:begin
ns=s0;
end
endcase
end
always@(posedge clk,negedge rst)begin
if(!rst)begin
out1<=0;
out2<=0;
end
else begin
case(ns)
s3:begin
out1<=1;
out2<=0;
end
s4:begin
out1<=1;
out2<=1;
end
s5:begin
out1<=1;
out2<=2;
end
s6:begin
out1<=1;
out2<=3;
end
default:begin
out1<=0;
out2<=0;
end
endcase
end
end
endmodule
Vending machine 2
If sel is 0, buy the first drink, and if sel is 1, buy the second drink. You can buy it at s3, but you can only buy the first drink.
Once it can be purchased, the secondary state can only be 0, indicating the termination of this payment, and then the change will be executed on the output.
The output can only be a MEALY machine, that is, the output is related to the current state and the input signal. It cannot be a MOORE machine, otherwise there will be too many states.
It is a MEALY machine, which means that the output depends on the current state on the one hand, and the input signal on the other hand. Here is the SEL signal, or you can write a two-stage formula,
If you use a MOORE machine and use the secondary state to determine the output, you cannot be sure what you want to buy. You need SEL and the current state to jointly determine a state.
`timescale 1ns/1ns
module seller2(
input wire clk ,
input wire rst ,
input wire d1 ,
input wire d2 ,
input wire sel ,
output reg out1,
output reg out2,
output reg out3
);
//*************code***********//
parameter S0=0, S0_5=1, S1=2, S1_5=3, S2=4, S2_5=5, S3=6;
reg[2:0] state, nstate;
always@(posedge clk or negedge rst) begin
if(~rst)
state <= 0;
else
state <= nstate;
end
always@(*) begin
case(state)
S0 : nstate = d1? S0_5:
d2? S1:
nstate;
S0_5 : nstate = d1? S1:
d2? S1_5:
nstate;
S1 : nstate = d1? S1_5:
d2? S2:
nstate;
S1_5 : nstate = ~sel? S0:
d1? S2:
d2? S2_5:
nstate;
S2 : nstate = ~sel? S0:
d1? S2_5:
d2? S3:
nstate;
default: nstate = S0;
endcase
end
always@(*) begin
if(~rst) begin
{out1, out2, out3} = 3'b000;
end
else begin
case(state)
S0, S0_5, S1: {out1, out2, out3} = 0;
S1_5 : {out1, out2, out3} = ~sel? 3'b100: 3'b000;
S2 : {out1, out2, out3} = ~sel? 3'b101: 3'b000;
S2_5 : {out1, out2, out3} = ~sel? 3'b101: 3'b010;
S3 : {out1, out2, out3} = ~sel? 3'b101: 3'b011;
default : {out1, out2, out3} = 3'b000;
endcase
end
end
//*************code***********//
endmodule
Game console billing program
`timescale 1ns/1ns
module game_count
(
input rst_n, //异位复位信号,低电平有效
input clk, //时钟信号
input [9:0]money,
input set,
input boost,
output reg[9:0]remain,
output reg yellow,
output reg red
);
always@(posedge clk or negedge rst_n) begin
if(~rst_n) begin
yellow <= 0;
red <= 0;
end
else begin
yellow <= remain<10&&remain;
red <= boost? remain<2: remain<1;
end
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
remain <= 0;
else if(boost)
remain <= set ? remain+money:
remain<2? remain:
remain-2;
else
remain <= set ? remain+money:
remain<1? remain:
remain-1;
end
endmodule
`timescale 1ns/1ns
module game_count
(
input rst_n, //异位复位信号,低电平有效
input clk, //时钟信号
input [9:0]money,
input set,
input boost,
output reg[9:0]remain,
output reg yellow,
output reg red
);
always@(posedge clk or negedge rst_n)begin
if(~rst_n)
remain <= 0;
else begin
if(boost==0)
remain <= set==1? remain+money: remain-1;
else if(boost==1)
remain <= set==1? remain+money: remain-2;
end
end
always@(posedge clk or negedge rst_n)begin
if(~rst_n)begin
yellow <= 0;
red <= 0;
end
else begin
if(remain < 1)begin
yellow <= 0;
red <= 1;
end
else if(remain < 10)begin
yellow <= 1;
red <= 0;
end
else begin
yellow <= 0;
red <= 0;
end
end
end
endmodule